Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
tc-v850.c File Reference
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
#include "opcode/v850.h"
#include "dwarf2dbg.h"

Go to the source code of this file.

Classes

struct  reg_name
struct  v850_fixup
struct  v850_seg_entry

Defines

#define SEXT16(x)   ((((x) & 0xffff) ^ (~0x7fff)) + 0x8000)
#define MAX_INSN_FIXUPS   5
#define SDATA_SECTION   0
#define TDATA_SECTION   1
#define ZDATA_SECTION   2
#define SBSS_SECTION   3
#define TBSS_SECTION   4
#define ZBSS_SECTION   5
#define ROSDATA_SECTION   6
#define ROZDATA_SECTION   7
#define SCOMMON_SECTION   8
#define TCOMMON_SECTION   9
#define ZCOMMON_SECTION   10
#define CALL_TABLE_DATA_SECTION   11
#define CALL_TABLE_TEXT_SECTION   12
#define BSS_SECTION   13
#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct reg_name))
#define SYSREG_NAME_CNT   (sizeof (system_registers) / sizeof (struct reg_name))
#define SYSREGLIST_NAME_CNT   (sizeof (system_list_registers) / sizeof (struct reg_name))
#define CC_NAME_CNT   (sizeof (cc_names) / sizeof (struct reg_name))
#define CHECK_(name, reloc)

Functions

static void do_v850_seg (int i, subsegT sub)
static void v850_seg (int i)
static void v850_offset (int ignore ATTRIBUTE_UNUSED)
static void v850_comm (int area)
static void set_machine (int number)
static void v850_longcode (int type)
static int reg_name_search (const struct reg_name *regs, int regcount, const char *name, bfd_boolean accept_numbers)
static bfd_boolean register_name (expressionS *expressionP)
static bfd_boolean system_register_name (expressionS *expressionP, bfd_boolean accept_numbers, bfd_boolean accept_list_names)
static bfd_boolean cc_name (expressionS *expressionP)
static void skip_white_space (void)
static char * parse_register_list (unsigned long *insn, const struct v850_operand *operand)
void md_show_usage (FILE *stream)
int md_parse_option (int c, char *arg)
symbolS * md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
char * md_atof (int type, char *litp, int *sizep)
void md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP)
valueT md_section_align (asection *seg, valueT addr)
void md_begin (void)
static bfd_reloc_code_real_type handle_lo16 (const struct v850_operand *operand)
static bfd_reloc_code_real_type handle_ctoff (const struct v850_operand *operand)
static bfd_reloc_code_real_type handle_sdaoff (const struct v850_operand *operand)
static bfd_reloc_code_real_type handle_zdaoff (const struct v850_operand *operand)
static bfd_reloc_code_real_type handle_tdaoff (const struct v850_operand *operand)
static bfd_reloc_code_real_type v850_reloc_prefix (const struct v850_operand *operand)
static unsigned long v850_insert_operand (unsigned long insn, const struct v850_operand *operand, offsetT val, char *file, unsigned int line, char *str)
void md_assemble (char *str)
arelenttc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
void v850_handle_align (fragS *frag)
int md_estimate_size_before_relax (fragS *fragp, asection *seg ATTRIBUTE_UNUSED)
long v850_pcrel_from_section (fixS *fixp, segT section)
void md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
void parse_cons_expression_v850 (expressionS *exp)
void cons_fix_new_v850 (fragS *frag, int where, int size, expressionS *exp)
bfd_boolean v850_fix_adjustable (fixS *fixP)
int v850_force_relocation (struct fix *fixP)

Variables

static bfd_reloc_code_real_type hold_cons_reloc = BFD_RELOC_UNUSED
static bfd_boolean warn_signed_overflows = FALSE
static bfd_boolean warn_unsigned_overflows = FALSE
static int machine = -1
static int processor_mask = -1
const char comment_chars [] = "#"
const char line_comment_chars [] = ";#"
const char line_separator_chars [] = ";"
const char EXP_CHARS [] = "eE"
const char FLT_CHARS [] = "dD"
const relax_typeS md_relax_table []
static int v850_relax = 0
static int fc
const pseudo_typeS md_pseudo_table []
static struct hash_controlv850_hash
static struct reg_name []
const char * md_shortopts = "m:"
size_t md_longopts_size = sizeof (md_longopts)
static char copy_of_instruction [128]

Class Documentation

struct reg_name

Definition at line 28 of file tc-mn10200.c.

Class Members
unsigned int length
const char * name
char name
unsigned int regno
int value
struct v850_fixup

Definition at line 87 of file tc-v850.c.

Collaboration diagram for v850_fixup:
Class Members
expressionS exp
int opindex
bfd_reloc_code_real_type reloc
struct v850_seg_entry

Definition at line 97 of file tc-v850.c.

Collaboration diagram for v850_seg_entry:
Class Members
flagword flags
const char * name
segT s

Define Documentation

#define BSS_SECTION   13

Definition at line 156 of file tc-v850.c.

#define CALL_TABLE_DATA_SECTION   11

Definition at line 154 of file tc-v850.c.

#define CALL_TABLE_TEXT_SECTION   12

Definition at line 155 of file tc-v850.c.

#define CC_NAME_CNT   (sizeof (cc_names) / sizeof (struct reg_name))

Definition at line 642 of file tc-v850.c.

#define CHECK_ (   name,
  reloc 
)
Value:
if (strncmp (input_line_pointer, name "(", strlen (name) + 1) == 0)   \
    {                                                          \
      input_line_pointer += strlen (name);                            \
      return reloc;                                            \
    }
#define MAX_INSN_FIXUPS   5

Definition at line 85 of file tc-v850.c.

#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct reg_name))

Definition at line 579 of file tc-v850.c.

#define ROSDATA_SECTION   6

Definition at line 149 of file tc-v850.c.

#define ROZDATA_SECTION   7

Definition at line 150 of file tc-v850.c.

#define SBSS_SECTION   3

Definition at line 146 of file tc-v850.c.

#define SCOMMON_SECTION   8

Definition at line 151 of file tc-v850.c.

#define SDATA_SECTION   0

Definition at line 143 of file tc-v850.c.

#define SEXT16 (   x)    ((((x) & 0xffff) ^ (~0x7fff)) + 0x8000)

Definition at line 29 of file tc-v850.c.

#define SYSREG_NAME_CNT   (sizeof (system_registers) / sizeof (struct reg_name))

Definition at line 604 of file tc-v850.c.

#define SYSREGLIST_NAME_CNT   (sizeof (system_list_registers) / sizeof (struct reg_name))

Definition at line 613 of file tc-v850.c.

#define TBSS_SECTION   4

Definition at line 147 of file tc-v850.c.

#define TCOMMON_SECTION   9

Definition at line 152 of file tc-v850.c.

#define TDATA_SECTION   1

Definition at line 144 of file tc-v850.c.

#define ZBSS_SECTION   5

Definition at line 148 of file tc-v850.c.

#define ZCOMMON_SECTION   10

Definition at line 153 of file tc-v850.c.

#define ZDATA_SECTION   2

Definition at line 145 of file tc-v850.c.


Function Documentation

static bfd_boolean cc_name ( expressionS expressionP) [static]

Definition at line 839 of file tc-v850.c.

{
  int reg_number;
  char *name;
  char *start;
  char c;

  /* Find the spelling of the operand.  */
  start = name = input_line_pointer;

  c = get_symbol_end ();
  reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE);

  /* Put back the delimiting char.  */
  *input_line_pointer = c;

  /* Look to see if it's in the register table.  */
  if (reg_number >= 0)
    {
      expressionP->X_op            = O_constant;
      expressionP->X_add_number = reg_number;

      /* Make the rest nice.  */
      expressionP->X_add_symbol = NULL;
      expressionP->X_op_symbol  = NULL;

      return TRUE;
    }
  else
    {
      /* Reset the line as if we had not done anything.  */
      input_line_pointer = start;

      return FALSE;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cons_fix_new_v850 ( fragS *  frag,
int  where,
int  size,
expressionS exp 
)

Definition at line 2412 of file tc-v850.c.

{
  if (hold_cons_reloc == BFD_RELOC_UNUSED)
    {
      if (size == 4)
       hold_cons_reloc = BFD_RELOC_32;
      if (size == 2)
       hold_cons_reloc = BFD_RELOC_16;
      if (size == 1)
       hold_cons_reloc = BFD_RELOC_8;
    }

  if (exp != NULL)
    fix_new_exp (frag, where, size, exp, 0, hold_cons_reloc);
  else
    fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc);

  hold_cons_reloc = BFD_RELOC_UNUSED;
}

Here is the call graph for this function:

static void do_v850_seg ( int  i,
subsegT  sub 
) [static]

Definition at line 159 of file tc-v850.c.

{
  struct v850_seg_entry *seg = v850_seg_table + i;

  obj_elf_section_change_hook ();

  if (seg->s != NULL)
    subseg_set (seg->s, sub);
  else
    {
      seg->s = subseg_new (seg->name, sub);
      bfd_set_section_flags (stdoutput, seg->s, seg->flags);
      if ((seg->flags & SEC_LOAD) == 0)
       seg_info (seg->s)->bss = 1;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1367 of file tc-v850.c.

{
  if (operand == NULL)
    return BFD_RELOC_V850_CALLT_16_16_OFFSET;

  if (operand->bits != 6
      || operand->shift != 0)
    {
      as_bad (_("ctoff() relocation used on an instruction which does not support it"));
      return BFD_RELOC_64;  /* Used to indicate an error condition.  */
    }

  return BFD_RELOC_V850_CALLT_6_7_OFFSET;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1348 of file tc-v850.c.

{
  if (operand != NULL)
    {
      if (operand->bits == -1)
       return BFD_RELOC_V850_LO16_SPLIT_OFFSET;

      if (!(operand->bits == 16 && operand->shift == 16)
         && !(operand->bits == 15 && operand->shift == 17))
       {
         as_bad (_("lo() relocation used on an instruction which does "
                  "not support it"));
         return BFD_RELOC_64;  /* Used to indicate an error condition.  */
       }
    }
  return BFD_RELOC_LO16;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1383 of file tc-v850.c.

{
  if (operand == NULL)
    return BFD_RELOC_V850_SDA_16_16_OFFSET;

  if (operand->bits == 15 && operand->shift == 17)
    return BFD_RELOC_V850_SDA_15_16_OFFSET;

  if (operand->bits == -1)
    return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET;

  if (operand->bits != 16
      || operand->shift != 16)
    {
      as_bad (_("sdaoff() relocation used on an instruction which does not support it"));
      return BFD_RELOC_64;  /* Used to indicate an error condition.  */
    }

  return BFD_RELOC_V850_SDA_16_16_OFFSET;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1428 of file tc-v850.c.

{
  if (operand == NULL)
    /* Data item, not an instruction.  */
    return BFD_RELOC_V850_TDA_7_7_OFFSET;

  if (operand->bits == 6 && operand->shift == 1)
    /* sld.w/sst.w, operand: D8_6.  */
    return BFD_RELOC_V850_TDA_6_8_OFFSET;

  if (operand->bits == 4 && operand->insert != NULL)
    /* sld.hu, operand: D5-4.  */
    return BFD_RELOC_V850_TDA_4_5_OFFSET;

  if (operand->bits == 4 && operand->insert == NULL)
    /* sld.bu, operand: D4.   */
    return BFD_RELOC_V850_TDA_4_4_OFFSET;

  if (operand->bits == 16 && operand->shift == 16)
    /* set1 & chums, operands: D16.  */
    return BFD_RELOC_V850_TDA_16_16_OFFSET;

  if (operand->bits != 7)
    {
      as_bad (_("tdaoff() relocation used on an instruction which does not support it"));
      /* Used to indicate an error condition.  */
      return BFD_RELOC_64;
    }

  return  operand->insert != NULL
    ? BFD_RELOC_V850_TDA_7_8_OFFSET     /* sld.h/sst.h, operand: D8_7.  */
    : BFD_RELOC_V850_TDA_7_7_OFFSET;    /* sld.b/sst.b, operand: D7.    */
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1405 of file tc-v850.c.

{
  if (operand == NULL)
    return BFD_RELOC_V850_ZDA_16_16_OFFSET;

  if (operand->bits == 15 && operand->shift == 17)
    return BFD_RELOC_V850_ZDA_15_16_OFFSET;

  if (operand->bits == -1)
    return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET;

  if (operand->bits != 16
      || operand->shift != 16)
    {
      as_bad (_("zdaoff() relocation used on an instruction which does not support it"));
      /* Used to indicate an error condition.  */
      return BFD_RELOC_64;
    }

  return BFD_RELOC_V850_ZDA_16_16_OFFSET;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void md_apply_fix ( fixS *  fixP,
valueT valueP,
segT seg  ATTRIBUTE_UNUSED 
)

Definition at line 2272 of file tc-v850.c.

{
  valueT value = * valueP;
  char *where;

  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
      || fixP->fx_r_type == BFD_RELOC_V850_LONGCALL
      || fixP->fx_r_type == BFD_RELOC_V850_LONGJUMP
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    {
      fixP->fx_done = 0;
      return;
    }

  if (fixP->fx_addsy == (symbolS *) NULL)
    fixP->fx_addnumber = value,
    fixP->fx_done = 1;

  else if (fixP->fx_pcrel)
    fixP->fx_addnumber = fixP->fx_offset;

  else
    {
      value = fixP->fx_offset;
      if (fixP->fx_subsy != (symbolS *) NULL)
       {
         if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
           value -= S_GET_VALUE (fixP->fx_subsy);
         else
           /* We don't actually support subtracting a symbol.  */
           as_bad_where (fixP->fx_file, fixP->fx_line,
                       _("expression too complex"));
       }
      fixP->fx_addnumber = value;
    }

  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    {
      int opindex;
      const struct v850_operand *operand;
      unsigned long insn;

      opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
      operand = &v850_operands[opindex];

      /* Fetch the instruction, insert the fully resolved operand
        value, and stuff the instruction back again.

        Note the instruction has been stored in little endian
        format!  */
      where = fixP->fx_frag->fr_literal + fixP->fx_where;

      insn = bfd_getl32 ((unsigned char *) where);
      insn = v850_insert_operand (insn, operand, (offsetT) value,
                              fixP->fx_file, fixP->fx_line, NULL);
      bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);

      if (fixP->fx_done)
       /* Nothing else to do here.  */
       return;

      /* Determine a BFD reloc value based on the operand information.
        We are only prepared to turn a few of the operands into relocs.  */

      if (operand->bits == 22)
       fixP->fx_r_type = BFD_RELOC_V850_22_PCREL;
      else if (operand->bits == 9)
       fixP->fx_r_type = BFD_RELOC_V850_9_PCREL;
      else
       {
         as_bad_where (fixP->fx_file, fixP->fx_line,
                     _("unresolved expression that must be resolved"));
         fixP->fx_done = 1;
         return;
       }
    }
  else if (fixP->fx_done)
    {
      /* We still have to insert the value into memory!  */
      where = fixP->fx_frag->fr_literal + fixP->fx_where;

      if (fixP->tc_fix_data != NULL
         && ((struct v850_operand *) fixP->tc_fix_data)->insert != NULL)
       {
         const char * message = NULL;
         struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data;
         unsigned long insn;

         /* The variable "where" currently points at the exact point inside
            the insn where we need to insert the value.  But we need to
            extract the entire insn so we probably need to move "where"
            back a few bytes.  */
         if (fixP->fx_size == 2)
           where -= 2;
         else if (fixP->fx_size == 1)
           where -= 3;

         insn = bfd_getl32 ((unsigned char *) where);

         /* Use the operand's insertion procedure, if present, in order to
            make sure that the value is correctly stored in the insn.  */
         insn = operand->insert (insn, (offsetT) value, & message);
         /* Ignore message even if it is set.  */

         bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
       }
      else
       {
         if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
           bfd_putl32 (((value << 16) & 0xfffe0000)
                     | ((value << 5) & 0x20)
                     | (bfd_getl32 (where) & ~0xfffe0020), where);
         else if (fixP->fx_size == 1)
           *where = value & 0xff;
         else if (fixP->fx_size == 2)
           bfd_putl16 (value & 0xffff, (unsigned char *) where);
         else if (fixP->fx_size == 4)
           bfd_putl32 (value, (unsigned char *) where);
       }
    }
}

Here is the call graph for this function:

void md_assemble ( char *  str)

Definition at line 1603 of file tc-v850.c.

{
  char *s;
  char *start_of_operands;
  struct v850_opcode *opcode;
  struct v850_opcode *next_opcode;
  const unsigned char *opindex_ptr;
  int next_opindex;
  int relaxable = 0;
  unsigned long insn;
  unsigned long insn_size;
  char *f;
  int i;
  int match;
  bfd_boolean extra_data_after_insn = FALSE;
  unsigned extra_data_len = 0;
  unsigned long extra_data = 0;
  char *saved_input_line_pointer;

  strncpy (copy_of_instruction, str, sizeof (copy_of_instruction) - 1);

  /* Get the opcode.  */
  for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
    continue;

  if (*s != '\0')
    *s++ = '\0';

  /* Find the first opcode with the proper name.  */
  opcode = (struct v850_opcode *) hash_find (v850_hash, str);
  if (opcode == NULL)
    {
      /* xgettext:c-format  */
      as_bad (_("Unrecognized opcode: `%s'"), str);
      ignore_rest_of_line ();
      return;
    }

  str = s;
  while (ISSPACE (*str))
    ++str;

  start_of_operands = str;

  saved_input_line_pointer = input_line_pointer;

  for (;;)
    {
      const char *errmsg = NULL;

      match = 0;

      if ((opcode->processors & processor_mask) == 0)
       {
         errmsg = _("Target processor does not support this instruction.");
         goto error;
       }

      relaxable = 0;
      fc = 0;
      next_opindex = 0;
      insn = opcode->opcode;
      extra_data_after_insn = FALSE;

      input_line_pointer = str = start_of_operands;

      for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
       {
         const struct v850_operand *operand;
         char *hold;
         expressionS ex;
         bfd_reloc_code_real_type reloc;

         if (next_opindex == 0)
           operand = &v850_operands[*opindex_ptr];
         else
           {
             operand = &v850_operands[next_opindex];
             next_opindex = 0;
           }

         errmsg = NULL;

         while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
           ++str;

         if (operand->flags & V850_OPERAND_RELAX)
           relaxable = 1;

         /* Gather the operand.  */
         hold = input_line_pointer;
         input_line_pointer = str;

         /* lo(), hi(), hi0(), etc...  */
         if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED)
           {
             /* This is a fake reloc, used to indicate an error condition.  */
             if (reloc == BFD_RELOC_64)
              {
                match = 1;
                goto error;
              }

             expression (&ex);

             if (ex.X_op == O_constant)
              {
                switch (reloc)
                  {
                  case BFD_RELOC_V850_ZDA_16_16_OFFSET:
                    /* To cope with "not1 7, zdaoff(0xfffff006)[r0]"
                      and the like.  */
                    /* Fall through.  */

                  case BFD_RELOC_LO16:
                  case BFD_RELOC_V850_LO16_SPLIT_OFFSET:
                    {
                     /* Truncate, then sign extend the value.  */
                     ex.X_add_number = SEXT16 (ex.X_add_number);
                     break;
                    }

                  case BFD_RELOC_HI16:
                    {
                     /* Truncate, then sign extend the value.  */
                     ex.X_add_number = SEXT16 (ex.X_add_number >> 16);
                     break;
                    }

                  case BFD_RELOC_HI16_S:
                    {
                     /* Truncate, then sign extend the value.  */
                     int temp = (ex.X_add_number >> 16) & 0xffff;

                     temp += (ex.X_add_number >> 15) & 1;

                     ex.X_add_number = SEXT16 (temp);
                     break;
                    }

                  case BFD_RELOC_32:
                    if ((operand->flags & V850E_IMMEDIATE32) == 0)
                     {
                       errmsg = _("immediate operand is too large");
                       goto error;
                     }

                    extra_data_after_insn = TRUE;
                    extra_data_len     = 4;
                    extra_data         = 0;
                    break;

                  default:
                    fprintf (stderr, "reloc: %d\n", reloc);
                    as_bad (_("AAARG -> unhandled constant reloc"));
                    break;
                  }

                if (fc > MAX_INSN_FIXUPS)
                  as_fatal (_("too many fixups"));

                fixups[fc].exp     = ex;
                fixups[fc].opindex = *opindex_ptr;
                fixups[fc].reloc   = reloc;
                fc++;
              }
             else
              {
                if (reloc == BFD_RELOC_32)
                  {
                    if ((operand->flags & V850E_IMMEDIATE32) == 0)
                     {
                       errmsg = _("immediate operand is too large");
                       goto error;
                     }

                    extra_data_after_insn = TRUE;
                    extra_data_len     = 4;
                    extra_data         = ex.X_add_number;
                  }

                if (fc > MAX_INSN_FIXUPS)
                  as_fatal (_("too many fixups"));

                fixups[fc].exp     = ex;
                fixups[fc].opindex = *opindex_ptr;
                fixups[fc].reloc   = reloc;
                fc++;
              }
           }
         else
           {
             errmsg = NULL;

             if ((operand->flags & V850_OPERAND_REG) != 0)
              {
                if (!register_name (&ex))
                  errmsg = _("invalid register name");
                else if ((operand->flags & V850_NOT_R0)
                        && ex.X_add_number == 0)
                  {
                    errmsg = _("register r0 cannot be used here");

                    /* Force an error message to be generated by
                      skipping over any following potential matches
                      for this opcode.  */
                    opcode += 3;
                  }
              }
             else if ((operand->flags & V850_OPERAND_SRG) != 0)
              {
                if (!system_register_name (&ex, TRUE, FALSE))
                  errmsg = _("invalid system register name");
              }
             else if ((operand->flags & V850_OPERAND_EP) != 0)
              {
                char *start = input_line_pointer;
                char c = get_symbol_end ();

                if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
                  {
                    /* Put things back the way we found them.  */
                    *input_line_pointer = c;
                    input_line_pointer = start;
                    errmsg = _("expected EP register");
                    goto error;
                  }

                *input_line_pointer = c;
                str = input_line_pointer;
                input_line_pointer = hold;

                while (*str == ' ' || *str == ','
                      || *str == '[' || *str == ']')
                  ++str;
                continue;
              }
             else if ((operand->flags & V850_OPERAND_CC) != 0)
              {
                if (!cc_name (&ex))
                  errmsg = _("invalid condition code name");
              }
             else if (operand->flags & V850E_PUSH_POP)
              {
                errmsg = parse_register_list (&insn, operand);

                /* The parse_register_list() function has already done
                   everything, so fake a dummy expression.  */
                ex.X_op       = O_constant;
                ex.X_add_number = 0;
              }
             else if (operand->flags & V850E_IMMEDIATE16)
              {
                expression (&ex);

                if (ex.X_op != O_constant)
                  errmsg = _("constant expression expected");
                else if (ex.X_add_number & 0xffff0000)
                  {
                    if (ex.X_add_number & 0xffff)
                     errmsg = _("constant too big to fit into instruction");
                    else if ((insn & 0x001fffc0) == 0x00130780)
                     ex.X_add_number >>= 16;
                    else
                     errmsg = _("constant too big to fit into instruction");
                  }

                extra_data_after_insn = TRUE;
                extra_data_len     = 2;
                extra_data         = ex.X_add_number;
                ex.X_add_number    = 0;
              }
             else if (operand->flags & V850E_IMMEDIATE32)
              {
                expression (&ex);

                if (ex.X_op != O_constant)
                  errmsg = _("constant expression expected");

                extra_data_after_insn = TRUE;
                extra_data_len     = 4;
                extra_data         = ex.X_add_number;
                ex.X_add_number    = 0;
              }
             else if (register_name (&ex)
                     && (operand->flags & V850_OPERAND_REG) == 0)
              {
                char c;
                int exists = 0;

                /* It is possible that an alias has been defined that
                   matches a register name.  For example the code may
                   include a ".set ZERO, 0" directive, which matches
                   the register name "zero".  Attempt to reparse the
                   field as an expression, and only complain if we
                   cannot generate a constant.  */

                input_line_pointer = str;

                c = get_symbol_end ();

                if (symbol_find (str) != NULL)
                  exists = 1;

                *input_line_pointer = c;
                input_line_pointer = str;

                expression (&ex);

                if (ex.X_op != O_constant)
                  {
                    /* If this register is actually occurring too early on
                      the parsing of the instruction, (because another
                      field is missing) then report this.  */
                    if (opindex_ptr[1] != 0
                       && (v850_operands[opindex_ptr[1]].flags
                           & V850_OPERAND_REG))
                     errmsg = _("syntax error: value is missing before the register name");
                    else
                     errmsg = _("syntax error: register not expected");

                    /* If we created a symbol in the process of this
                      test then delete it now, so that it will not
                      be output with the real symbols...  */
                    if (exists == 0
                       && ex.X_op == O_symbol)
                     symbol_remove (ex.X_add_symbol,
                                   &symbol_rootP, &symbol_lastP);
                  }
              }
             else if (system_register_name (&ex, FALSE, FALSE)
                     && (operand->flags & V850_OPERAND_SRG) == 0)
              errmsg = _("syntax error: system register not expected");

             else if (cc_name (&ex)
                     && (operand->flags & V850_OPERAND_CC) == 0)
              errmsg = _("syntax error: condition code not expected");

             else
              {
                expression (&ex);
                /* Special case:
                   If we are assembling a MOV instruction and the immediate
                   value does not fit into the bits available then create a
                   fake error so that the next MOV instruction will be
                   selected.  This one has a 32 bit immediate field.  */

                if (((insn & 0x07e0) == 0x0200)
                    && operand->bits == 5 /* Do not match the CALLT instruction.  */
                    && ex.X_op == O_constant
                    && (ex.X_add_number < (-(1 << (operand->bits - 1)))
                       || ex.X_add_number > ((1 << (operand->bits - 1)) - 1)))
                  errmsg = _("immediate operand is too large");
              }

             if (errmsg)
              goto error;

             switch (ex.X_op)
              {
              case O_illegal:
                errmsg = _("illegal operand");
                goto error;
              case O_absent:
                errmsg = _("missing operand");
                goto error;
              case O_register:
                if ((operand->flags
                     & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0)
                  {
                    errmsg = _("invalid operand");
                    goto error;
                  }
                insn = v850_insert_operand (insn, operand, ex.X_add_number,
                                         NULL, 0, copy_of_instruction);
                break;

              case O_constant:
                insn = v850_insert_operand (insn, operand, ex.X_add_number,
                                         NULL, 0, copy_of_instruction);
                break;

              default:
                /* We need to generate a fixup for this expression.  */
                if (fc >= MAX_INSN_FIXUPS)
                  as_fatal (_("too many fixups"));

                fixups[fc].exp     = ex;
                fixups[fc].opindex = *opindex_ptr;
                fixups[fc].reloc   = BFD_RELOC_UNUSED;
                ++fc;
                break;
              }
           }

         str = input_line_pointer;
         input_line_pointer = hold;

         while (*str == ' ' || *str == ',' || *str == '[' || *str == ']'
               || *str == ')')
           ++str;
       }
      match = 1;

    error:
      if (match == 0)
       {
         next_opcode = opcode + 1;
         if (next_opcode->name != NULL
             && strcmp (next_opcode->name, opcode->name) == 0)
           {
             opcode = next_opcode;

             /* Skip versions that are not supported by the target
               processor.  */
             if ((opcode->processors & processor_mask) == 0)
              goto error;

             continue;
           }

         as_bad ("%s: %s", copy_of_instruction, errmsg);

         if (*input_line_pointer == ']')
           ++input_line_pointer;

         ignore_rest_of_line ();
         input_line_pointer = saved_input_line_pointer;
         return;
       }
      break;
    }

  while (ISSPACE (*str))
    ++str;

  if (*str != '\0')
    /* xgettext:c-format  */
    as_bad (_("junk at end of line: `%s'"), str);

  input_line_pointer = str;

  /* Tie dwarf2 debug info to the address at the start of the insn.
     We can't do this after the insn has been output as the current
     frag may have been closed off.  eg. by frag_var.  */
  dwarf2_emit_insn (0);

  /* Write out the instruction.  */

  if (relaxable && fc > 0)
    {
      /* On a 64-bit host the size of an 'int' is not the same
        as the size of a pointer, so we need a union to convert
        the opindex field of the fr_cgen structure into a char *
        so that it can be stored in the frag.  We do not have
        to worry about loosing accuracy as we are not going to
        be even close to the 32bit limit of the int.  */
      union
      {
       int opindex;
       char * ptr;
      }
      opindex_converter;

      opindex_converter.opindex = fixups[0].opindex;
      insn_size = 2;
      fc = 0;

      if (!strcmp (opcode->name, "br"))
       {
         f = frag_var (rs_machine_dependent, 4, 2, 2,
                     fixups[0].exp.X_add_symbol,
                     fixups[0].exp.X_add_number,
                     opindex_converter.ptr);
         md_number_to_chars (f, insn, insn_size);
         md_number_to_chars (f + 2, 0, 2);
       }
      else
       {
         f = frag_var (rs_machine_dependent, 6, 4, 0,
                     fixups[0].exp.X_add_symbol,
                     fixups[0].exp.X_add_number,
                     opindex_converter.ptr);
         md_number_to_chars (f, insn, insn_size);
         md_number_to_chars (f + 2, 0, 4);
       }
    }
  else
    {
      /* Four byte insns have an opcode with the two high bits on.  */
      if ((insn & 0x0600) == 0x0600)
       insn_size = 4;
      else
       insn_size = 2;

      /* Special case: 32 bit MOV.  */
      if ((insn & 0xffe0) == 0x0620)
       insn_size = 2;

      f = frag_more (insn_size);
      md_number_to_chars (f, insn, insn_size);

      if (extra_data_after_insn)
       {
         f = frag_more (extra_data_len);
         md_number_to_chars (f, extra_data, extra_data_len);

         extra_data_after_insn = FALSE;
       }
    }

  /* Create any fixups.  At this point we do not use a
     bfd_reloc_code_real_type, but instead just use the
     BFD_RELOC_UNUSED plus the operand index.  This lets us easily
     handle fixups for any operand type, although that is admittedly
     not a very exciting feature.  We pick a BFD reloc type in
     md_apply_fix.  */
  for (i = 0; i < fc; i++)
    {
      const struct v850_operand *operand;
      bfd_reloc_code_real_type reloc;

      operand = &v850_operands[fixups[i].opindex];

      reloc = fixups[i].reloc;

      if (reloc != BFD_RELOC_UNUSED)
       {
         reloc_howto_type *reloc_howto =
           bfd_reloc_type_lookup (stdoutput, reloc);
         int size;
         int address;
         fixS *fixP;

         if (!reloc_howto)
           abort ();

         size = bfd_get_reloc_size (reloc_howto);

         /* XXX This will abort on an R_V850_8 reloc -
            is this reloc actually used?  */
         if (size != 2 && size != 4)
           abort ();

         address = (f - frag_now->fr_literal) + insn_size - size;

         if (reloc == BFD_RELOC_32)
           address += 2;

         fixP = fix_new_exp (frag_now, address, size,
                           &fixups[i].exp,
                           reloc_howto->pc_relative,
                           reloc);

         fixP->tc_fix_data = (void *) operand;

         switch (reloc)
           {
           case BFD_RELOC_LO16:
           case BFD_RELOC_V850_LO16_SPLIT_OFFSET:
           case BFD_RELOC_HI16:
           case BFD_RELOC_HI16_S:
             fixP->fx_no_overflow = 1;
             break;
           default:
             break;
           }
       }
      else
       {
         fix_new_exp (frag_now,
                     f - frag_now->fr_literal, 4,
                     & fixups[i].exp,
                     (operand->flags & V850_OPERAND_DISP) != 0,
                     (bfd_reloc_code_real_type) (fixups[i].opindex
                                             + (int) BFD_RELOC_UNUSED));
       }
    }

  input_line_pointer = saved_input_line_pointer;
}

Here is the call graph for this function:

char* md_atof ( int type  ,
char *  litp,
int sizep 
)

Definition at line 1179 of file tc-v850.c.

{
  int prec;
  LITTLENUM_TYPE words[4];
  char *t;
  int i;

  switch (type)
    {
    case 'f':
      prec = 2;
      break;

    case 'd':
      prec = 4;
      break;

    default:
      *sizep = 0;
      return _("bad call to md_atof");
    }

  t = atof_ieee (input_line_pointer, type, words);
  if (t)
    input_line_pointer = t;

  *sizep = prec * 2;

  for (i = prec - 1; i >= 0; i--)
    {
      md_number_to_chars (litp, (valueT) words[i], 2);
      litp += 2;
    }

  return NULL;
}

Here is the call graph for this function:

void md_begin ( void  )

Definition at line 1292 of file tc-v850.c.

{
  char *prev_name = "";
  const struct v850_opcode *op;

  if (strncmp (TARGET_CPU, "v850e1", 6) == 0)
    {
      if (machine == -1)
       machine = bfd_mach_v850e1;

      if (processor_mask == -1)
       processor_mask = PROCESSOR_V850E1;
    }
  else if (strncmp (TARGET_CPU, "v850e", 5) == 0)
    {
      if (machine == -1)
       machine = bfd_mach_v850e;

      if (processor_mask == -1)
       processor_mask = PROCESSOR_V850E;
    }
  else if (strncmp (TARGET_CPU, "v850", 4) == 0)
    {
      if (machine == -1)
       machine = 0;

      if (processor_mask == -1)
       processor_mask = PROCESSOR_V850;
    }
  else
    /* xgettext:c-format  */
    as_bad (_("Unable to determine default target processor from string: %s"),
           TARGET_CPU);

  v850_hash = hash_new ();

  /* Insert unique names into hash table.  The V850 instruction set
     has many identical opcode names that have different opcodes based
     on the operands.  This hash table then provides a quick index to
     the first opcode with a particular name in the opcode table.  */
  op = v850_opcodes;
  while (op->name)
    {
      if (strcmp (prev_name, op->name))
       {
         prev_name = (char *) op->name;
         hash_insert (v850_hash, op->name, (char *) op);
       }
      op++;
    }

  v850_seg_table[BSS_SECTION].s = bss_section;
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
}

Here is the call graph for this function:

void md_convert_frag ( bfd *abfd  ATTRIBUTE_UNUSED,
asection * sec  ,
fragS *  fragP 
)

Definition at line 1219 of file tc-v850.c.

{
  /* This code performs some nasty type punning between the
     fr_opcode field of the frag structure (a char *) and the
     fx_r_type field of the fix structure (a bfd_reloc_code_real_type)
     On a 64bit host this causes problems because these two fields
     are not the same size, but since we know that we are only
     ever storing small integers in the fields, it is safe to use
     a union to convert between them.  */
  union u
  {
    bfd_reloc_code_real_type fx_r_type;
    char * fr_opcode;
  }
  opcode_converter;
  subseg_change (sec, 0);

  opcode_converter.fr_opcode = fragP->fr_opcode;
      
  /* In range conditional or unconditional branch.  */
  if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2)
    {
      fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
              fragP->fr_offset, 1,
              BFD_RELOC_UNUSED + opcode_converter.fx_r_type);
      fragP->fr_fix += 2;
    }
  /* Out of range conditional branch.  Emit a branch around a jump.  */
  else if (fragP->fr_subtype == 1)
    {
      unsigned char *buffer =
       (unsigned char *) (fragP->fr_fix + fragP->fr_literal);

      /* Reverse the condition of the first branch.  */
      buffer[0] ^= 0x08;
      /* Mask off all the displacement bits.  */
      buffer[0] &= 0x8f;
      buffer[1] &= 0x07;
      /* Now set the displacement bits so that we branch
        around the unconditional branch.  */
      buffer[0] |= 0x30;

      /* Now create the unconditional branch + fixup to the final
        target.  */
      md_number_to_chars ((char *) buffer + 2, 0x00000780, 4);
      fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
              fragP->fr_offset, 1,
              BFD_RELOC_UNUSED + opcode_converter.fx_r_type + 1);
      fragP->fr_fix += 6;
    }
  /* Out of range unconditional branch.  Emit a jump.  */
  else if (fragP->fr_subtype == 3)
    {
      md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4);
      fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
              fragP->fr_offset, 1,
              BFD_RELOC_UNUSED + opcode_converter.fx_r_type + 1);
      fragP->fr_fix += 4;
    }
  else
    abort ();
}

Here is the call graph for this function:

int md_estimate_size_before_relax ( fragS *  fragp,
asection *seg  ATTRIBUTE_UNUSED 
)

Definition at line 2248 of file tc-v850.c.

{
  if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
    abort ();

  return md_relax_table[fragp->fr_subtype].rlx_length;
}
int md_parse_option ( int c  ,
char *  arg 
)

Definition at line 1129 of file tc-v850.c.

{
  if (c != 'm')
    return 0;

  if (strcmp (arg, "warn-signed-overflow") == 0)
    warn_signed_overflows = TRUE;

  else if (strcmp (arg, "warn-unsigned-overflow") == 0)
    warn_unsigned_overflows = TRUE;

  else if (strcmp (arg, "v850") == 0)
    {
      machine = 0;
      processor_mask = PROCESSOR_V850;
    }
  else if (strcmp (arg, "v850e") == 0)
    {
      machine = bfd_mach_v850e;
      processor_mask = PROCESSOR_V850E;
    }
  else if (strcmp (arg, "v850e1") == 0)
    {
      machine = bfd_mach_v850e1;
      processor_mask = PROCESSOR_V850E1;
    }
  else if (strcmp (arg, "v850any") == 0)
    {
      /* Tell the world that this is for any v850 chip.  */
      machine = 0;

      /* But support instructions for the extended versions.  */
      processor_mask = PROCESSOR_V850E;
      processor_mask |= PROCESSOR_V850E1;
    }
  else if (strcmp (arg, "relax") == 0)
    v850_relax = 1;
  else
    return 0;

  return 1;
}

Here is the call graph for this function:

Definition at line 1285 of file tc-v850.c.

{
  int align = bfd_get_section_alignment (stdoutput, seg);
  return ((addr + (1 << align) - 1) & (-1 << align));
}

Here is the call graph for this function:

void md_show_usage ( FILE *  stream)

Definition at line 1116 of file tc-v850.c.

{
  fprintf (stream, _(" V850 options:\n"));
  fprintf (stream, _("  -mwarn-signed-overflow    Warn if signed immediate values overflow\n"));
  fprintf (stream, _("  -mwarn-unsigned-overflow  Warn if unsigned immediate values overflow\n"));
  fprintf (stream, _("  -mv850                    The code is targeted at the v850\n"));
  fprintf (stream, _("  -mv850e                   The code is targeted at the v850e\n"));
  fprintf (stream, _("  -mv850e1                  The code is targeted at the v850e1\n"));
  fprintf (stream, _("  -mv850any                 The code is generic, despite any processor specific instructions\n"));
  fprintf (stream, _("  -mrelax                   Enable relaxation\n"));
}

Here is the call graph for this function:

symbolS* md_undefined_symbol ( char *name  ATTRIBUTE_UNUSED)

Definition at line 1173 of file tc-v850.c.

{
  return 0;
}

Definition at line 2398 of file tc-v850.c.

{
  /* See if there's a reloc prefix like hi() we have to handle.  */
  hold_cons_reloc = v850_reloc_prefix (NULL);

  /* Do normal expression parsing.  */
  expression (exp);
}

Here is the call graph for this function:

static char* parse_register_list ( unsigned long insn,
const struct v850_operand operand 
) [static]

Definition at line 910 of file tc-v850.c.

{
  static int type1_regs[32] =
  {
    30,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24
  };
  static int type2_regs[32] =
  {
    19, 18, 17, 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24
  };
  static int type3_regs[32] =
  {
     3,  2,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0, 14, 15, 13, 12,  7,  6,  5,  4, 11, 10,  9,  8
  };
  int *regs;
  expressionS exp;

  /* Select a register array to parse.  */
  switch (operand->shift)
    {
    case 0xffe00001: regs = type1_regs; break;
    case 0xfff8000f: regs = type2_regs; break;
    case 0xfff8001f: regs = type3_regs; break;
    default:
      as_bad (_("unknown operand shift: %x\n"), operand->shift);
      return _("internal failure in parse_register_list");
    }

  skip_white_space ();

  /* If the expression starts with a curly brace it is a register list.
     Otherwise it is a constant expression, whoes bits indicate which
     registers are to be included in the list.  */
  if (*input_line_pointer != '{')
    {
      int reg;
      int i;

      expression (&exp);

      if (exp.X_op != O_constant)
       return _("constant expression or register list expected");

      if (regs == type1_regs)
       {
         if (exp.X_add_number & 0xFFFFF000)
           return _("high bits set in register list expression");

         for (reg = 20; reg < 32; reg++)
           if (exp.X_add_number & (1 << (reg - 20)))
             {
              for (i = 0; i < 32; i++)
                if (regs[i] == reg)
                  *insn |= (1 << i);
             }
       }
      else if (regs == type2_regs)
       {
         if (exp.X_add_number & 0xFFFE0000)
           return _("high bits set in register list expression");

         for (reg = 1; reg < 16; reg++)
           if (exp.X_add_number & (1 << (reg - 1)))
             {
              for (i = 0; i < 32; i++)
                if (regs[i] == reg)
                  *insn |= (1 << i);
             }

         if (exp.X_add_number & (1 << 15))
           *insn |= (1 << 3);

         if (exp.X_add_number & (1 << 16))
           *insn |= (1 << 19);
       }
      else /* regs == type3_regs  */
       {
         if (exp.X_add_number & 0xFFFE0000)
           return _("high bits set in register list expression");

         for (reg = 16; reg < 32; reg++)
           if (exp.X_add_number & (1 << (reg - 16)))
             {
              for (i = 0; i < 32; i++)
                if (regs[i] == reg)
                  *insn |= (1 << i);
             }

         if (exp.X_add_number & (1 << 16))
           *insn |= (1 << 19);
       }

      return NULL;
    }

  input_line_pointer++;

  /* Parse the register list until a terminator (closing curly brace or
     new-line) is found.  */
  for (;;)
    {
      if (register_name (&exp))
       {
         int i;

         /* Locate the given register in the list, and if it is there,
            insert the corresponding bit into the instruction.  */
         for (i = 0; i < 32; i++)
           {
             if (regs[i] == exp.X_add_number)
              {
                *insn |= (1 << i);
                break;
              }
           }

         if (i == 32)
           return _("illegal register included in list");
       }
      else if (system_register_name (&exp, TRUE, TRUE))
       {
         if (regs == type1_regs)
           {
             return _("system registers cannot be included in list");
           }
         else if (exp.X_add_number == 5)
           {
             if (regs == type2_regs)
              return _("PSW cannot be included in list");
             else
              *insn |= 0x8;
           }
         else if (exp.X_add_number < 4)
           *insn |= 0x80000;
         else
           return _("High value system registers cannot be included in list");
       }
      else if (*input_line_pointer == '}')
       {
         input_line_pointer++;
         break;
       }
      else if (*input_line_pointer == ',')
       {
         input_line_pointer++;
         continue;
       }
      else if (*input_line_pointer == '-')
       {
         /* We have encountered a range of registers: rX - rY.  */
         int j;
         expressionS exp2;

         /* Skip the dash.  */
         ++input_line_pointer;

         /* Get the second register in the range.  */
         if (! register_name (&exp2))
           {
             return _("second register should follow dash in register list");
             exp2.X_add_number = exp.X_add_number;
           }

         /* Add the rest of the registers in the range.  */
         for (j = exp.X_add_number + 1; j <= exp2.X_add_number; j++)
           {
             int i;

             /* Locate the given register in the list, and if it is there,
               insert the corresponding bit into the instruction.  */
             for (i = 0; i < 32; i++)
              {
                if (regs[i] == j)
                  {
                    *insn |= (1 << i);
                    break;
                  }
              }

             if (i == 32)
              return _("illegal register included in list");
           }
       }
      else
       break;

      skip_white_space ();
    }

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int reg_name_search ( const struct reg_name regs,
int  regcount,
const char *  name,
bfd_boolean  accept_numbers 
) [static]

Definition at line 650 of file tc-v850.c.

{
  int middle, low, high;
  int cmp;
  symbolS *symbolP;

  /* If the register name is a symbol, then evaluate it.  */
  if ((symbolP = symbol_find (name)) != NULL)
    {
      /* If the symbol is an alias for another name then use that.
        If the symbol is an alias for a number, then return the number.  */
      if (symbol_equated_p (symbolP))
       name
         = S_GET_NAME (symbol_get_value_expression (symbolP)->X_add_symbol);
      else if (accept_numbers)
       {
         int reg = S_GET_VALUE (symbolP);

         if (reg >= 0 && reg <= 31)
           return reg;
       }

      /* Otherwise drop through and try parsing name normally.  */
    }

  low = 0;
  high = regcount - 1;

  do
    {
      middle = (low + high) / 2;
      cmp = strcasecmp (name, regs[middle].name);
      if (cmp < 0)
       high = middle - 1;
      else if (cmp > 0)
       low = middle + 1;
      else
       return regs[middle].value;
    }
  while (low <= high);
  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean register_name ( expressionS expressionP) [static]

Definition at line 707 of file tc-v850.c.

{
  int reg_number;
  char *name;
  char *start;
  char c;

  /* Find the spelling of the operand.  */
  start = name = input_line_pointer;

  c = get_symbol_end ();

  reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT,
                            name, FALSE);

  /* Put back the delimiting char.  */
  *input_line_pointer = c;

  /* Look to see if it's in the register table.  */
  if (reg_number >= 0)
    {
      expressionP->X_op            = O_register;
      expressionP->X_add_number = reg_number;

      /* Make the rest nice.  */
      expressionP->X_add_symbol = NULL;
      expressionP->X_op_symbol  = NULL;

      return TRUE;
    }
  else
    {
      /* Reset the line as if we had not done anything.  */
      input_line_pointer = start;

      return FALSE;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void set_machine ( int  number) [static]

Definition at line 459 of file tc-v850.c.

static void skip_white_space ( void  ) [static]

Definition at line 877 of file tc-v850.c.

{
  while (*input_line_pointer == ' '
        || *input_line_pointer == '\t')
    ++input_line_pointer;
}

Here is the caller graph for this function:

static bfd_boolean system_register_name ( expressionS expressionP,
bfd_boolean  accept_numbers,
bfd_boolean  accept_list_names 
) [static]

Definition at line 761 of file tc-v850.c.

{
  int reg_number;
  char *name;
  char *start;
  char c;

  /* Find the spelling of the operand.  */
  start = name = input_line_pointer;

  c = get_symbol_end ();
  reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name,
                            accept_numbers);

  /* Put back the delimiting char.  */
  *input_line_pointer = c;

  if (reg_number < 0
      && accept_numbers)
    {
      /* Reset input_line pointer.  */
      input_line_pointer = start;

      if (ISDIGIT (*input_line_pointer))
       {
         reg_number = strtol (input_line_pointer, &input_line_pointer, 10);

         /* Make sure that the register number is allowable.  */
         if (reg_number < 0
             || (reg_number > 5 && reg_number < 16)
             || reg_number > 27)
           reg_number = -1;
       }
      else if (accept_list_names)
       {
         c = get_symbol_end ();
         reg_number = reg_name_search (system_list_registers,
                                   SYSREGLIST_NAME_CNT, name, FALSE);

         /* Put back the delimiting char.  */
         *input_line_pointer = c;
       }
    }

  /* Look to see if it's in the register table.  */
  if (reg_number >= 0)
    {
      expressionP->X_op            = O_register;
      expressionP->X_add_number = reg_number;

      /* Make the rest nice.  */
      expressionP->X_add_symbol = NULL;
      expressionP->X_op_symbol  = NULL;

      return TRUE;
    }
  else
    {
      /* Reset the line as if we had not done anything.  */
      input_line_pointer = start;

      return FALSE;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

arelent* tc_gen_reloc ( asection *seg  ATTRIBUTE_UNUSED,
fixS *  fixp 
)

Definition at line 2189 of file tc-v850.c.

{
  arelent *reloc;

  reloc                    = xmalloc (sizeof (arelent));
  reloc->sym_ptr_ptr  = xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;

  if (   fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
      || fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
      || fixp->fx_r_type == BFD_RELOC_V850_LONGCALL
      || fixp->fx_r_type == BFD_RELOC_V850_LONGJUMP
      || fixp->fx_r_type == BFD_RELOC_V850_ALIGN)
    reloc->addend = fixp->fx_offset;
  else
    {
      if (fixp->fx_r_type == BFD_RELOC_32
         && fixp->fx_pcrel)
       fixp->fx_r_type = BFD_RELOC_32_PCREL;

      reloc->addend = fixp->fx_addnumber;
    }

  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);

  if (reloc->howto == NULL)
    {
      as_bad_where (fixp->fx_file, fixp->fx_line,
                  /* xgettext:c-format  */
                  _("reloc %d not supported by object file format"),
                  (int) fixp->fx_r_type);

      xfree (reloc);

      return NULL;
    }

  return reloc;
}

Here is the call graph for this function:

static void v850_comm ( int  area) [static]

Definition at line 201 of file tc-v850.c.

{
  char *name;
  char c;
  char *p;
  int temp;
  unsigned int size;
  symbolS *symbolP;
  int have_align;

  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"));
      ignore_rest_of_line ();
      return;
    }

  /* Skip ','.  */
  input_line_pointer++;

  if ((temp = get_absolute_expression ()) < 0)
    {
      /* xgettext:c-format  */
      as_bad (_(".COMMon length (%d.) < 0! Ignored."), temp);
      ignore_rest_of_line ();
      return;
    }

  size = temp;
  *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"));
      ignore_rest_of_line ();
      return;
    }

  if (S_GET_VALUE (symbolP) != 0)
    {
      if (S_GET_VALUE (symbolP) != size)
       /* xgettext:c-format  */
       as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
               S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
    }

  know (symbol_get_frag (symbolP) == &zero_address_frag);

  if (*input_line_pointer != ',')
    have_align = 0;
  else
    {
      have_align = 1;
      input_line_pointer++;
      SKIP_WHITESPACE ();
    }

  if (! have_align || *input_line_pointer != '"')
    {
      if (! have_align)
       temp = 0;
      else
       {
         temp = get_absolute_expression ();

         if (temp < 0)
           {
             temp = 0;
             as_warn (_("Common alignment negative; 0 assumed"));
           }
       }

      if (symbol_get_obj (symbolP)->local)
       {
         segT old_sec;
         int old_subsec;
         char *pfrag;
         int align;
         flagword applicable;

         old_sec = now_seg;
         old_subsec = now_subseg;

         applicable = bfd_applicable_section_flags (stdoutput);

         applicable &= SEC_ALLOC;

         switch (area)
           {
           case SCOMMON_SECTION:
             do_v850_seg (SBSS_SECTION, 0);
             break;

           case ZCOMMON_SECTION:
             do_v850_seg (ZBSS_SECTION, 0);
             break;

           case TCOMMON_SECTION:
             do_v850_seg (TBSS_SECTION, 0);
             break;
           }

         if (temp)
           {
             /* Convert to a power of 2 alignment.  */
             for (align = 0; (temp & 1) == 0; temp >>= 1, ++align)
              ;

             if (temp != 1)
              {
                as_bad (_("Common alignment not a power of 2"));
                ignore_rest_of_line ();
                return;
              }
           }
         else
           align = 0;

         record_alignment (now_seg, align);

         if (align)
           frag_align (align, 0, 0);

         switch (area)
           {
           case SCOMMON_SECTION:
             if (S_GET_SEGMENT (symbolP) == v850_seg_table[SBSS_SECTION].s)
              symbol_get_frag (symbolP)->fr_symbol = 0;
             break;

           case ZCOMMON_SECTION:
             if (S_GET_SEGMENT (symbolP) == v850_seg_table[ZBSS_SECTION].s)
              symbol_get_frag (symbolP)->fr_symbol = 0;
             break;

           case TCOMMON_SECTION:
             if (S_GET_SEGMENT (symbolP) == v850_seg_table[TBSS_SECTION].s)
              symbol_get_frag (symbolP)->fr_symbol = 0;
             break;

           default:
             abort ();
           }

         symbol_set_frag (symbolP, frag_now);
         pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
                         (offsetT) size, (char *) 0);
         *pfrag = 0;
         S_SET_SIZE (symbolP, size);

         switch (area)
           {
           case SCOMMON_SECTION:
             S_SET_SEGMENT (symbolP, v850_seg_table[SBSS_SECTION].s);
             break;

           case ZCOMMON_SECTION:
             S_SET_SEGMENT (symbolP, v850_seg_table[ZBSS_SECTION].s);
             break;

           case TCOMMON_SECTION:
             S_SET_SEGMENT (symbolP, v850_seg_table[TBSS_SECTION].s);
             break;

           default:
             abort ();
           }

         S_CLEAR_EXTERNAL (symbolP);
         obj_elf_section_change_hook ();
         subseg_set (old_sec, old_subsec);
       }
      else
       {
         segT   old_sec;
         int    old_subsec;

       allocate_common:
         old_sec = now_seg;
         old_subsec = now_subseg;

         S_SET_VALUE (symbolP, (valueT) size);
         S_SET_ALIGN (symbolP, temp);
         S_SET_EXTERNAL (symbolP);

         switch (area)
           {
           case SCOMMON_SECTION:
           case ZCOMMON_SECTION:
           case TCOMMON_SECTION:
             do_v850_seg (area, 0);
             S_SET_SEGMENT (symbolP, v850_seg_table[area].s);
             break;

           default:
             abort ();
           }

         obj_elf_section_change_hook ();
         subseg_set (old_sec, old_subsec);
       }
    }
  else
    {
      input_line_pointer++;

      /* @@ Some use the dot, some don't.  Can we get some consistency??  */
      if (*input_line_pointer == '.')
       input_line_pointer++;

      /* @@ Some say data, some say bss.  */
      if (strncmp (input_line_pointer, "bss\"", 4)
         && strncmp (input_line_pointer, "data\"", 5))
       {
         while (*--input_line_pointer != '"')
           ;
         input_line_pointer--;
         goto bad_common_segment;
       }

      while (*input_line_pointer++ != '"')
       ;

      goto allocate_common;
    }

  symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;

  demand_empty_rest_of_line ();
  return;

  {
  bad_common_segment:
    p = input_line_pointer;
    while (*p && *p != '\n')
      p++;
    c = *p;
    *p = '\0';
    as_bad (_("bad .common segment %s"), input_line_pointer + 1);
    *p = c;
    input_line_pointer = p;
    ignore_rest_of_line ();
    return;
  }
}

Here is the call graph for this function:

bfd_boolean v850_fix_adjustable ( fixS *  fixP)

Definition at line 2436 of file tc-v850.c.

{
  if (fixP->fx_addsy == NULL)
    return 1;

  /* Don't adjust function names.  */
  if (S_IS_FUNCTION (fixP->fx_addsy))
    return 0;

  /* We need the symbol name for the VTABLE entries.  */
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    return 0;

  return 1;
}

Here is the call graph for this function:

Definition at line 2454 of file tc-v850.c.

Here is the call graph for this function:

void v850_handle_align ( fragS *  frag)

Definition at line 2231 of file tc-v850.c.

{
  if (v850_relax
      && frag->fr_type == rs_align
      && frag->fr_address + frag->fr_fix > 0
      && frag->fr_offset > 1
      && now_seg != bss_section
      && now_seg != v850_seg_table[SBSS_SECTION].s
      && now_seg != v850_seg_table[TBSS_SECTION].s
      && now_seg != v850_seg_table[ZBSS_SECTION].s)
    fix_new (frag, frag->fr_fix, 2, & abs_symbol, frag->fr_offset, 0,
            BFD_RELOC_V850_ALIGN);
}

Here is the call graph for this function:

static unsigned long v850_insert_operand ( unsigned long  insn,
const struct v850_operand operand,
offsetT  val,
char *  file,
unsigned int  line,
char *  str 
) [static]

Definition at line 1504 of file tc-v850.c.

{
  if (operand->insert)
    {
      const char *message = NULL;

      insn = operand->insert (insn, val, &message);
      if (message != NULL)
       {
         if ((operand->flags & V850_OPERAND_SIGNED)
             && ! warn_signed_overflows
             && strstr (message, "out of range") != NULL)
           {
             /* Skip warning...  */
           }
         else if ((operand->flags & V850_OPERAND_SIGNED) == 0
                 && ! warn_unsigned_overflows
                 && strstr (message, "out of range") != NULL)
           {
             /* Skip warning...  */
           }
         else if (str)
           {
             if (file == (char *) NULL)
              as_warn ("%s: %s", str, message);
             else
              as_warn_where (file, line, "%s: %s", str, message);
           }
         else
           {
             if (file == (char *) NULL)
              as_warn (message);
             else
              as_warn_where (file, line, message);
           }
       }
    }
  else
    {
      if (operand->bits != 32)
       {
         long min, max;

         if ((operand->flags & V850_OPERAND_SIGNED) != 0)
           {
             if (! warn_signed_overflows)
              max = (1 << operand->bits) - 1;
             else
              max = (1 << (operand->bits - 1)) - 1;

             min = -(1 << (operand->bits - 1));
           }
         else
           {
             max = (1 << operand->bits) - 1;

             if (! warn_unsigned_overflows)
              min = -(1 << (operand->bits - 1));
             else
              min = 0;
           }

         if (val < (offsetT) min || val > (offsetT) max)
           {
             char buf [128];

             /* Restore min and mix to expected values for decimal ranges.  */
             if ((operand->flags & V850_OPERAND_SIGNED)
                && ! warn_signed_overflows)
              max = (1 << (operand->bits - 1)) - 1;

             if (! (operand->flags & V850_OPERAND_SIGNED)
                && ! warn_unsigned_overflows)
              min = 0;

             if (str)
              sprintf (buf, "%s: ", str);
             else
              buf[0] = 0;
             strcat (buf, _("operand"));

             as_bad_value_out_of_range (buf, val, (offsetT) min, (offsetT) max, file, line);
           }
       }

      insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
    }

  return insn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void v850_longcode ( int  type) [static]

Definition at line 473 of file tc-v850.c.

{
  expressionS ex;

  if (! v850_relax)
    {
      if (type == 1)
       as_warn (".longcall pseudo-op seen when not relaxing");
      else
       as_warn (".longjump pseudo-op seen when not relaxing");
    }

  expression (&ex);

  if (ex.X_op != O_symbol || ex.X_add_number != 0)
    {
      as_bad ("bad .longcall format");
      ignore_rest_of_line ();

      return;
    }

  if (type == 1)
    fix_new_exp (frag_now, frag_now_fix (), 4, & ex, 1,
               BFD_RELOC_V850_LONGCALL);
  else
    fix_new_exp (frag_now, frag_now_fix (), 4, & ex, 1,
               BFD_RELOC_V850_LONGJUMP);

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

static void v850_offset ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 186 of file tc-v850.c.

{
  char *pfrag;
  int temp = get_absolute_expression ();

  pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, (symbolS *)0,
                  (offsetT) temp, (char *) 0);
  *pfrag = 0;

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

long v850_pcrel_from_section ( fixS *  fixp,
segT  section 
)

Definition at line 2257 of file tc-v850.c.

{
  /* If the symbol is undefined, or in a section other than our own,
     or it is weak (in which case it may well be in another section,
     then let the linker figure it out.  */
  if (fixp->fx_addsy != (symbolS *) NULL
      && (! S_IS_DEFINED (fixp->fx_addsy)
         || S_IS_WEAK (fixp->fx_addsy)
         || (S_GET_SEGMENT (fixp->fx_addsy) != section)))
    return 0;

  return fixp->fx_frag->fr_address + fixp->fx_where;
}

Here is the call graph for this function:

Definition at line 1467 of file tc-v850.c.

{
  bfd_boolean paren_skipped = FALSE;

  /* Skip leading opening parenthesis.  */
  if (*input_line_pointer == '(')
    {
      ++input_line_pointer;
      paren_skipped = TRUE;
    }

#define CHECK_(name, reloc)                                           \
  if (strncmp (input_line_pointer, name "(", strlen (name) + 1) == 0) \
    {                                                          \
      input_line_pointer += strlen (name);                            \
      return reloc;                                            \
    }

  CHECK_ ("hi0",    BFD_RELOC_HI16    );
  CHECK_ ("hi",          BFD_RELOC_HI16_S    );
  CHECK_ ("lo",          handle_lo16 (operand)  );
  CHECK_ ("sdaoff", handle_sdaoff (operand));
  CHECK_ ("zdaoff", handle_zdaoff (operand));
  CHECK_ ("tdaoff", handle_tdaoff (operand));
  CHECK_ ("hilo",   BFD_RELOC_32      );
  CHECK_ ("ctoff",  handle_ctoff (operand) );

  /* Restore skipped parenthesis.  */
  if (paren_skipped)
    --input_line_pointer;

  return BFD_RELOC_UNUSED;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void v850_seg ( int  i) [static]

Definition at line 177 of file tc-v850.c.

Here is the call graph for this function:


Variable Documentation

const char comment_chars[] = "#"

Definition at line 55 of file tc-v850.c.

char copy_of_instruction[128] [static]

Definition at line 1600 of file tc-v850.c.

const char EXP_CHARS[] = "eE"

Definition at line 66 of file tc-v850.c.

int fc [static]

Definition at line 95 of file tc-v850.c.

const char FLT_CHARS[] = "dD"

Definition at line 70 of file tc-v850.c.

Definition at line 32 of file tc-v850.c.

const char line_comment_chars[] = ";#"

Definition at line 58 of file tc-v850.c.

Definition at line 62 of file tc-v850.c.

int machine = -1 [static]

Definition at line 39 of file tc-v850.c.

size_t md_longopts_size = sizeof (md_longopts)

Definition at line 1113 of file tc-v850.c.

const pseudo_typeS md_pseudo_table[]
Initial value:
{
  { "sdata",         v850_seg,            SDATA_SECTION        },
  { "tdata",         v850_seg,            TDATA_SECTION        },
  { "zdata",         v850_seg,            ZDATA_SECTION        },
  { "sbss",          v850_seg,            SBSS_SECTION         },
  { "tbss",          v850_seg,            TBSS_SECTION         },
  { "zbss",          v850_seg,            ZBSS_SECTION         },
  { "rosdata",              v850_seg,            ROSDATA_SECTION      },
  { "rozdata",              v850_seg,            ROZDATA_SECTION      },
  { "bss",           v850_seg,            BSS_SECTION          },
  { "offset",        v850_offset,         0                    },
  { "word",          cons,                4                    },
  { "zcomm",         v850_comm,           ZCOMMON_SECTION      },
  { "scomm",         v850_comm,           SCOMMON_SECTION      },
  { "tcomm",         v850_comm,           TCOMMON_SECTION      },
  { "v850",          set_machine,         0                    },
  { "call_table_data",      v850_seg,            CALL_TABLE_DATA_SECTION     },
  { "call_table_text",      v850_seg,            CALL_TABLE_TEXT_SECTION     },
  { "v850e",         set_machine,         bfd_mach_v850e              },
  { "v850e1",        set_machine,         bfd_mach_v850e1      },
  { "longcall",             v850_longcode,              1                    },
  { "longjump",             v850_longcode,              2                    },
  { NULL,            NULL,                0                    }
}

Definition at line 506 of file tc-v850.c.

const relax_typeS md_relax_table[]
Initial value:
{
  
  {0xff,     -0x100,    2, 1},
  {0x1fffff, -0x200000, 6, 0},
  
  {0xff,     -0x100,    2, 3},
  {0x1fffff, -0x200000, 4, 0},
}

Definition at line 72 of file tc-v850.c.

const char* md_shortopts = "m:"

Definition at line 1106 of file tc-v850.c.

int processor_mask = -1 [static]

Definition at line 42 of file tc-v850.c.

static struct reg_name [static]

Definition at line 536 of file tc-v850.c.

Definition at line 533 of file tc-v850.c.

int v850_relax = 0 [static]

Definition at line 82 of file tc-v850.c.

Definition at line 35 of file tc-v850.c.

Definition at line 36 of file tc-v850.c.