* config/tc-alpha.c: More use of symbol accessor functions.
[binutils-gdb.git] / gas / config / tc-v850.c
index f4a9ea9efb84baa9e87be66546d7cf8342aca5b0..7d4a91f122704415c1d1ac0424be36bb787a88de 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-v850.c -- Assembler code for the NEC V850
-   Copyright (C) 1996, 1997 Free Software Foundation.
+   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -95,17 +95,8 @@ static segT rozdata_section = NULL;
 static segT scommon_section = NULL;
 static segT tcommon_section = NULL;
 static segT zcommon_section = NULL;
-/* start-sanitize-v850e */
 static segT call_table_data_section = NULL;
 static segT call_table_text_section = NULL;
-/* end-sanitize-v850e */
-
-
-/* local functions */
-static unsigned long v850_insert_operand
-  PARAMS ((unsigned long insn, const struct v850_operand *operand,
-          offsetT val, char *file, unsigned int line));
-
 
 /* fixups */
 #define MAX_INSN_FIXUPS (5)
@@ -115,8 +106,10 @@ struct v850_fixup
   int                      opindex;
   bfd_reloc_code_real_type reloc;
 };
-struct v850_fixup fixups[MAX_INSN_FIXUPS];
+
+struct v850_fixup fixups [MAX_INSN_FIXUPS];
 static int fc;
+
 \f
 void
 v850_sdata (int ignore)
@@ -198,7 +191,6 @@ v850_rozdata (int ignore)
   demand_empty_rest_of_line ();
 }
 
-/* start-sanitize-v850e */
 void
 v850_call_table_data (int ignore)
 {
@@ -218,7 +210,6 @@ v850_call_table_text (int ignore)
   
   demand_empty_rest_of_line ();
 }
-/* end-sanitize-v850e */
 
 void
 v850_bss (int ignore)
@@ -260,42 +251,54 @@ v850_comm (area)
 
   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");
+      as_bad (_("Expected comma after symbol-name"));
       ignore_rest_of_line ();
       return;
     }
-  input_line_pointer++;                /* skip ',' */
+  
+  input_line_pointer ++;               /* skip ',' */
+  
   if ((temp = get_absolute_expression ()) < 0)
     {
-      as_bad (".COMMon length (%d.) <0! Ignored.", temp);
+      /* 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");
+      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)
        {
-         as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
+         /* 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 (symbolP->sy_frag == &zero_address_frag);
+  
+  know (symbol_get_frag (symbolP) == & zero_address_frag);
+  
   if (*input_line_pointer != ',')
     have_align = 0;
   else
@@ -304,6 +307,7 @@ v850_comm (area)
       input_line_pointer++;
       SKIP_WHITESPACE ();
     }
+  
   if (! have_align || *input_line_pointer != '"')
     {
       if (! have_align)
@@ -311,35 +315,81 @@ v850_comm (area)
       else
        {
          temp = get_absolute_expression ();
+         
          if (temp < 0)
            {
              temp = 0;
-             as_warn ("Common alignment negative; 0 assumed");
+             as_warn (_("Common alignment negative; 0 assumed"));
            }
        }
+      
       if (symbolP->local)
        {
          segT   old_sec;
          int    old_subsec;
          char * pfrag;
          int    align;
+         flagword      applicable;
 
-       /* allocate_bss: */
          old_sec = now_seg;
          old_subsec = now_subseg;
+      
+         applicable = bfd_applicable_section_flags (stdoutput);
+                 
+         applicable &= SEC_ALLOC;
+         
+         switch (area)
+           {
+           case AREA_SDA:
+             if (sbss_section == NULL)
+               {
+                 sbss_section = subseg_new (".sbss", 0);
+             
+                 bfd_set_section_flags (stdoutput, sbss_section, applicable);
+             
+                 seg_info (sbss_section)->bss = 1;
+               }
+             break;
+         
+           case AREA_ZDA:
+             if (zbss_section == NULL)
+               {
+                 zbss_section = subseg_new (".zbss", 0);
+                 
+                 bfd_set_section_flags (stdoutput, sbss_section, applicable);
+             
+                 seg_info (zbss_section)->bss = 1;
+               }
+             break;
+         
+           case AREA_TDA:
+             if (tbss_section == NULL)
+               {
+                 tbss_section = subseg_new (".tbss", 0);
+                 
+                 bfd_set_section_flags (stdoutput, tbss_section, applicable);
+                 
+                 seg_info (tbss_section)->bss = 1;
+               }
+             break;
+           }
+
          if (temp)
            {
              /* convert to a power of 2 alignment */
-             for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
+             for (align = 0; (temp & 1) == 0; temp >>= 1, ++align)
+               ;
+             
              if (temp != 1)
                {
-                 as_bad ("Common alignment not a power of 2");
+                 as_bad (_("Common alignment not a power of 2"));
                  ignore_rest_of_line ();
                  return;
                }
            }
          else
            align = 0;
+         
          switch (area)
            {
            case AREA_SDA:
@@ -371,24 +421,24 @@ v850_comm (area)
            {
            case AREA_SDA:
              if (S_GET_SEGMENT (symbolP) == sbss_section)
-               symbolP->sy_frag->fr_symbol = 0;
+               symbol_get_frag (symbolP)->fr_symbol = 0;
              break;
 
            case AREA_ZDA:
              if (S_GET_SEGMENT (symbolP) == zbss_section)
-               symbolP->sy_frag->fr_symbol = 0;
+               symbol_get_frag (symbolP)->fr_symbol = 0;
              break;
 
            case AREA_TDA:
              if (S_GET_SEGMENT (symbolP) == tbss_section)
-               symbolP->sy_frag->fr_symbol = 0;
+               symbol_get_frag (symbolP)->fr_symbol = 0;
              break;
 
            default:
              abort();
            }
          
-         symbolP->sy_frag = frag_now;
+         symbol_set_frag (symbolP, frag_now);
          pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
                            (offsetT) size, (char *) 0);
          *pfrag = 0;
@@ -396,9 +446,18 @@ v850_comm (area)
          
          switch (area)
            {
-           case AREA_SDA: S_SET_SEGMENT (symbolP, sbss_section); break;
-           case AREA_ZDA: S_SET_SEGMENT (symbolP, zbss_section); break;
-           case AREA_TDA: S_SET_SEGMENT (symbolP, tbss_section); break;
+           case AREA_SDA:
+             S_SET_SEGMENT (symbolP, sbss_section);
+             break;
+             
+           case AREA_ZDA:
+             S_SET_SEGMENT (symbolP, zbss_section);
+             break;
+             
+           case AREA_TDA:
+             S_SET_SEGMENT (symbolP, tbss_section);
+             break;
+             
            default:
              abort();
            }
@@ -416,9 +475,54 @@ v850_comm (area)
          
          switch (area)
            {
-           case AREA_SDA: S_SET_SEGMENT (symbolP, scommon_section); break;
-           case AREA_ZDA: S_SET_SEGMENT (symbolP, zcommon_section); break;
-           case AREA_TDA: S_SET_SEGMENT (symbolP, tcommon_section); break;
+           case AREA_SDA:
+             if (scommon_section == NULL)
+               {
+                 flagword      applicable;
+                 
+                 applicable = bfd_applicable_section_flags (stdoutput);
+                 
+                 scommon_section = subseg_new (".scommon", 0);
+                 
+                 bfd_set_section_flags (stdoutput, scommon_section, applicable
+                    & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+                       | SEC_HAS_CONTENTS) | SEC_IS_COMMON);
+               }
+             S_SET_SEGMENT (symbolP, scommon_section);
+             break;
+             
+           case AREA_ZDA:
+             if (zcommon_section == NULL)
+               {
+                 flagword      applicable;
+                 
+                 applicable = bfd_applicable_section_flags (stdoutput);
+                 
+                 zcommon_section = subseg_new (".zcommon", 0);
+                 
+                 bfd_set_section_flags (stdoutput, zcommon_section, applicable
+                    & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+                       | SEC_HAS_CONTENTS) | SEC_IS_COMMON);
+               }
+             S_SET_SEGMENT (symbolP, zcommon_section);
+             break;
+             
+           case AREA_TDA:
+             if (tcommon_section == NULL)
+               {
+                 flagword      applicable;
+                 
+                 applicable = bfd_applicable_section_flags (stdoutput);
+                 
+                 tcommon_section = subseg_new (".tcommon", 0);
+                 
+                 bfd_set_section_flags (stdoutput, tcommon_section, applicable
+                    & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+                       | SEC_HAS_CONTENTS) | SEC_IS_COMMON);
+               }
+             S_SET_SEGMENT (symbolP, tcommon_section);
+             break;
+             
            default:
              abort();
            }
@@ -444,7 +548,7 @@ v850_comm (area)
       goto allocate_common;
     }
 
-  symbolP->bsym->flags |= BSF_OBJECT;
+  symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
 
   demand_empty_rest_of_line ();
   return;
@@ -456,7 +560,7 @@ v850_comm (area)
       p++;
     c = *p;
     *p = '\0';
-    as_bad ("bad .common segment %s", input_line_pointer + 1);
+    as_bad (_("bad .common segment %s"), input_line_pointer + 1);
     *p = c;
     input_line_pointer = p;
     ignore_rest_of_line ();
@@ -473,10 +577,8 @@ set_machine (int number)
   switch (machine)
     {
     case 0: processor_mask = PROCESSOR_V850; break;
-/* start-sanitize-v850e */
     case bfd_mach_v850e:  processor_mask = PROCESSOR_V850E; break;
-    case bfd_mach_v850eq: processor_mask = PROCESSOR_V850EQ; break;
-/* end-sanitize-v850e */
+    case bfd_mach_v850ea: processor_mask = PROCESSOR_V850EA; break;
     }
 }
 
@@ -498,12 +600,10 @@ const pseudo_typeS md_pseudo_table[] =
   {"scomm",   v850_comm,    AREA_SDA},
   {"tcomm",   v850_comm,    AREA_TDA},
   {"v850",    set_machine,  0},
-/* start-sanitize-v850e */
   {"call_table_data", v850_call_table_data, 0},
   {"call_table_text", v850_call_table_text, 0},
   {"v850e",           set_machine,          bfd_mach_v850e},
-  {"v850eq",          set_machine,          bfd_mach_v850eq},
-/* end-sanitize-v850e */
+  {"v850ea",          set_machine,          bfd_mach_v850ea},
   { NULL,     NULL,         0}
 };
 
@@ -558,14 +658,11 @@ static const struct reg_name pre_defined_registers[] =
 
 static const struct reg_name system_registers[] = 
 {
-/* start-sanitize-v850e */
-
   { "ctbp",  20 },
   { "ctpc",  16 },
   { "ctpsw", 17 },
   { "dbpc",  18 },
   { "dbpsw", 19 },
-/* end-sanitize-v850e */
   { "ecr",    4 },
   { "eipc",   0 },
   { "eipsw",  1 },
@@ -575,6 +672,13 @@ static const struct reg_name system_registers[] =
 };
 #define SYSREG_NAME_CNT        (sizeof (system_registers) / sizeof (struct reg_name))
 
+static const struct reg_name system_list_registers[] =
+{
+  {"PS",      5 },
+  {"SR",      0 + 1}
+};
+#define SYSREGLIST_NAME_CNT    (sizeof (system_list_registers) / sizeof (struct reg_name))
+
 static const struct reg_name cc_names[] =
 {
   { "c",  0x1 },
@@ -607,14 +711,36 @@ static const struct reg_name cc_names[] =
    number from the array on success, or -1 on failure. */
 
 static int
-reg_name_search (regs, regcount, name)
+reg_name_search (regs, regcount, name, accept_numbers)
      const struct reg_name * regs;
      int                     regcount;
      const char *            name;
+     boolean                 accept_numbers;
 {
   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;
 
@@ -658,7 +784,8 @@ register_name (expressionP)
 
   c = get_symbol_end ();
 
-  reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
+  reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT,
+                               name, FALSE);
 
   * input_line_pointer = c;    /* put back the delimiting char */
   
@@ -685,18 +812,23 @@ register_name (expressionP)
 
 /* Summary of system_register_name().
  *
- * in: Input_line_pointer points to 1st char of operand.
+ * in:  Input_line_pointer points to 1st char of operand.
+ *      expressionP points to an expression structure to be filled in.
+ *      accept_numbers is true iff numerical register names may be used.
+ *      accept_list_names is true iff the special names PS and SR may be 
+ *      accepted.
  *
- * out: A expressionS.
+ * out: A expressionS structure in expressionP.
  *     The operand may have been a register: in this case, X_op == O_register,
  *     X_add_number is set to the register number, and truth is returned.
  *     Input_line_pointer->(next non-blank) char after operand, or is in
  *     its original state.
  */
 static boolean
-system_register_name (expressionP, accept_numbers)
+system_register_name (expressionP, accept_numbers, accept_list_names)
      expressionS * expressionP;
      boolean       accept_numbers;
+     boolean       accept_list_names;
 {
   int    reg_number;
   char * name;
@@ -707,7 +839,8 @@ system_register_name (expressionP, accept_numbers)
   start = name = input_line_pointer;
 
   c = get_symbol_end ();
-  reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name);
+  reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name,
+                               accept_numbers);
 
   * input_line_pointer = c;   /* put back the delimiting char */
   
@@ -717,21 +850,29 @@ system_register_name (expressionP, accept_numbers)
       input_line_pointer   = start; /* reset input_line pointer */
 
       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
-/* start-sanitize-v850e */
-         && reg_number < 16
-         || reg_number > 20
-/* end-sanitize-v850e */
-            )
        {
-         reg_number = -1;
+         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 > 20
+                )
+           {
+             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);
+
+         * input_line_pointer = c;   /* put back the delimiting char */
        }
     }
-      
+  
   /* look to see if it's in the register table */
   if (reg_number >= 0) 
     {
@@ -776,7 +917,7 @@ cc_name (expressionP)
   start = name = input_line_pointer;
 
   c = get_symbol_end ();
-  reg_number = reg_name_search (cc_names, CC_NAME_CNT, name);
+  reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE);
 
   * input_line_pointer = c;   /* put back the delimiting char */
   
@@ -809,7 +950,6 @@ skip_white_space (void)
     ++ input_line_pointer;
 }
 
-/* start-sanitize-v850e */
 /* Summary of parse_register_list ().
  *
  * in: Input_line_pointer  points to 1st char of a list of registers.
@@ -857,11 +997,11 @@ parse_register_list
     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";
+      as_bad (_("unknown operand shift: %x\n"), operand->shift);
+      return _("internal failure in parse_register_list");
     }
 
-  skip_white_space();
+  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
@@ -876,12 +1016,12 @@ parse_register_list
       expression (& exp);
       
       if (exp.X_op != O_constant)
-       return "constant expression or register list expected";
+       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";
+           return _("high bits set in register list expression");
          
          for (reg = 20; reg < 32; reg ++)
            if (exp.X_add_number & (1 << (reg - 20)))
@@ -894,7 +1034,7 @@ parse_register_list
       else if (regs == type2_regs)
        {
          if (exp.X_add_number & 0xFFFE0000)
-           return "high bits set in register list expression";
+           return _("high bits set in register list expression");
          
          for (reg = 1; reg < 16; reg ++)
            if (exp.X_add_number & (1 << (reg - 1)))
@@ -913,7 +1053,7 @@ parse_register_list
       else /* regs == type3_regs */
        {
          if (exp.X_add_number & 0xFFFE0000)
-           return "high bits set in register list expression";
+           return _("high bits set in register list expression");
          
          for (reg = 16; reg < 32; reg ++)
            if (exp.X_add_number & (1 << (reg - 16)))
@@ -932,14 +1072,16 @@ parse_register_list
 
   input_line_pointer ++;
 
-  /* Parse the register list until a terminator (closing curly brace or new-line) is found.  */
+  /* 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.  */
+         /* 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)
@@ -951,24 +1093,26 @@ parse_register_list
 
          if (i == 32)
            {
-             return "illegal register included in list";
+             return _("illegal register included in list");
            }
        }
-      else if (system_register_name (& exp, true))
+      else if (system_register_name (& exp, true, true))
        {
          if (regs == type1_regs)
            {
-             return "system registers cannot be included in list";
+             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";
+               return _("PSW cannot be included in list");
              else
                * insn |= 0x8;
            }
-         else
+         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 == '}')
        {
@@ -992,7 +1136,7 @@ parse_register_list
          /* Get the second register in the range.  */
          if (! register_name (& exp2))
            {
-             return "second register should follow dash in register list";
+             return _("second register should follow dash in register list");
              exp2.X_add_number = exp.X_add_number;
            }
 
@@ -1001,7 +1145,8 @@ parse_register_list
            {
              int  i;
          
-             /* Locate the given register in the list, and if it is there, insert the corresponding bit into the instruction.  */
+             /* 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)
@@ -1012,9 +1157,7 @@ parse_register_list
                }
 
              if (i == 32)
-               {
-                 return "illegal register included in list";
-               }
+               return _("illegal register included in list");
            }
        }
       else
@@ -1022,12 +1165,11 @@ parse_register_list
          break;
        }
 
-      skip_white_space();
+      skip_white_space ();
     }
 
   return NULL;
 }
-/* end-sanitize-v850e */
 
 CONST char * md_shortopts = "m:";
 
@@ -1042,61 +1184,63 @@ void
 md_show_usage (stream)
   FILE * stream;
 {
-  fprintf (stream, "V850 options:\n");
-  fprintf (stream, "\t-wsigned_overflow    Warn if signed immediate values overflow\n");
-  fprintf (stream, "\t-wunsigned_overflow  Warn if unsigned immediate values overflow\n");
-  fprintf (stream, "\t-mv850               The code is targeted at the v850\n");
-/* start-sanitize-v850e */
-  fprintf (stream, "\t-mv850e              The code is targeted at the v850e\n");
-  fprintf (stream, "\t-mv850eq             The code is targeted at the v850eq\n");
-/* end-sanitize-v850e */
-} 
+  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, _("  -mv850ea                  The code is targeted at the v850ea\n"));
+  fprintf (stream, _("  -mv850any                 The code is generic, despite any processor specific instructions\n"));
+}
 
 int
 md_parse_option (c, arg)
      int    c;
      char * arg;
 {
-  switch (c)
+  if (c != 'm')
     {
-    case 'w':
-      if (strcmp (arg, "signed_overflow") == 0)
-       {
-         warn_signed_overflows = TRUE;
-         return 1;
-       }
-      else if (strcmp (arg, "unsigned_overflow") == 0)
-       {
-         warn_unsigned_overflows = TRUE;
-         return 1;
-       }
-      break;
+      /* xgettext:c-format */
+      fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg);
+      return 0;
+    }
 
-    case 'm':
-      if (strcmp (arg, "v850") == 0)
-       {
-         machine = 0;
-         processor_mask = PROCESSOR_V850;
-         return 1;
-       }
-/* start-sanitize-v850e */
-      else if (strcmp (arg, "v850e") == 0)
-       {
-         machine = bfd_mach_v850e;
-         processor_mask = PROCESSOR_V850E;
-         return 1;
-       }
-      else if (strcmp (arg, "v850eq") == 0)
-       {
-         machine = bfd_mach_v850eq;
-         processor_mask = PROCESSOR_V850EQ;
-         return 1;
-       }
-/* end-sanitize-v850e */
-      break;
+  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, "v850ea") == 0)
+    {
+      machine = bfd_mach_v850ea;
+      processor_mask = PROCESSOR_V850EA;
+    }
+  else if (strcmp (arg, "v850any") == 0)
+    {
+      machine = 0;                       /* Tell the world that this is for any v850 chip.  */
+      processor_mask = PROCESSOR_V850EA; /* But support instructions for the extended versions.  */
+    }
+  else
+    {
+      /* xgettext:c-format */
+      fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg);
+      return 0;
     }
   
-  return 0;
+  return 1;
 }
 
 symbolS *
@@ -1129,7 +1273,7 @@ md_atof (type, litp, sizep)
 
     default:
       *sizep = 0;
-      return "bad call to md_atof";
+      return _("bad call to md_atof");
     }
   
   t = atof_ieee (input_line_pointer, type, words);
@@ -1184,7 +1328,8 @@ md_convert_frag (abfd, sec, fragP)
         target.  */
       md_number_to_chars (buffer + 2, 0x00000780, 4);
       fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
-              fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode + 1);
+              fragP->fr_offset, 1, BFD_RELOC_UNUSED +
+              (int) fragP->fr_opcode + 1);
       fragP->fr_var = 0;
       fragP->fr_fix += 6;
     }
@@ -1193,7 +1338,8 @@ md_convert_frag (abfd, sec, fragP)
     {
       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 + (int)fragP->fr_opcode + 1);
+              fragP->fr_offset, 1, BFD_RELOC_UNUSED +
+              (int) fragP->fr_opcode + 1);
       fragP->fr_var = 0;
       fragP->fr_fix += 4;
     }
@@ -1217,14 +1363,13 @@ md_begin ()
   register const struct v850_opcode * op;
   flagword                            applicable;
 
-/* start-sanitize-v850e */
-  if (strncmp (TARGET_CPU, "v850eq", 6) == 0)
+  if (strncmp (TARGET_CPU, "v850ea", 6) == 0)
     {
       if (machine == -1)
-       machine = bfd_mach_v850eq;
+       machine = bfd_mach_v850ea;
       
       if (processor_mask == -1)
-       processor_mask = PROCESSOR_V850EQ;
+       processor_mask = PROCESSOR_V850EA;
     }
   else if (strncmp (TARGET_CPU, "v850e", 5) == 0)
     {
@@ -1235,7 +1380,6 @@ md_begin ()
        processor_mask = PROCESSOR_V850E;
     }
   else
-/* end-sanitize-v850e */
   if (strncmp (TARGET_CPU, "v850", 4) == 0)
     {
       if (machine == -1)
@@ -1245,7 +1389,8 @@ md_begin ()
        processor_mask = PROCESSOR_V850;
     }
   else
-    as_bad ("Unable to determine default target processor from string: %s", 
+    /* xgettext:c-format */
+    as_bad (_("Unable to determine default target processor from string: %s"), 
             TARGET_CPU);
 
   v850_hash = hash_new();
@@ -1269,51 +1414,22 @@ md_begin ()
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
 
   applicable = bfd_applicable_section_flags (stdoutput);
-
-  sdata_section = subseg_new (".sdata", 0);
-  bfd_set_section_flags (stdoutput, sdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
-  
-  tdata_section = subseg_new (".tdata", 0);
-  bfd_set_section_flags (stdoutput, tdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
   
-  zdata_section = subseg_new (".zdata", 0);
-  bfd_set_section_flags (stdoutput, zdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
-  
-  sbss_section = subseg_new (".sbss", 0);
-  bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC);
-  seg_info (sbss_section)->bss = 1;
-  
-  tbss_section = subseg_new (".tbss", 0);
-  bfd_set_section_flags (stdoutput, tbss_section, applicable & SEC_ALLOC);
-  seg_info (tbss_section)->bss = 1;
-  
-  zbss_section = subseg_new (".zbss", 0);
-  bfd_set_section_flags (stdoutput, zbss_section, applicable & SEC_ALLOC);
-  seg_info (zbss_section)->bss = 1;
-  
-  rosdata_section = subseg_new (".rosdata", 0);
-  bfd_set_section_flags (stdoutput, rosdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY));
-                        
-  rozdata_section = subseg_new (".rozdata", 0);
-  bfd_set_section_flags (stdoutput, rozdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY));
-
-  scommon_section = subseg_new (".scommon", 0);
-  bfd_set_section_flags (stdoutput, scommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON));
-
-  zcommon_section = subseg_new (".zcommon", 0);
-  bfd_set_section_flags (stdoutput, zcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON));
-
-/* start-sanitize-v850e */
   call_table_data_section = subseg_new (".call_table_data", 0);
-  bfd_set_section_flags (stdoutput, call_table_data_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
+  bfd_set_section_flags (stdoutput, call_table_data_section,
+                        applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+                                      | SEC_DATA | SEC_HAS_CONTENTS));
   
   call_table_text_section = subseg_new (".call_table_text", 0);
-  bfd_set_section_flags (stdoutput, call_table_text_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE));
-/* end-sanitize-v850e */
+  bfd_set_section_flags (stdoutput, call_table_text_section,
+                        applicable & (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+                                      | SEC_CODE));
+  
+  /* Restore text section as the current default.  */
+  subseg_set (text_section, 0);
 }
 
 
-/* start-sanitize-v850e */
 static bfd_reloc_code_real_type
 handle_ctoff (const struct v850_operand * operand)
 {
@@ -1323,27 +1439,24 @@ handle_ctoff (const struct v850_operand * operand)
   if (   operand->bits  != 6
       || operand->shift != 0)
     {
-      as_bad ("ctoff() relocation used on an instruction which does not support it");
+      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;
 }
-/* end-sanitize-v850e */
 
 static bfd_reloc_code_real_type
 handle_sdaoff (const struct v850_operand * operand)
 {
   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;
-  /* start-sanitize-v850e */
   if (operand->bits == -1)                         return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET;
-  /* end-sanitize-v850e */
   
   if (   operand->bits  != 16
       || operand->shift != 16)
     {
-      as_bad ("sdaoff() relocation used on an instruction which does not support it");
+      as_bad (_("sdaoff() relocation used on an instruction which does not support it"));
       return BFD_RELOC_64;  /* Used to indicate an error condition.  */
     }
   
@@ -1355,14 +1468,12 @@ handle_zdaoff (const struct v850_operand * operand)
 {
   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;
-  /* start-sanitize-v850e */
   if (operand->bits == -1)                         return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET;
-  /* end-sanitize-v850e */
 
   if (   operand->bits  != 16
       || operand->shift != 16)
     {
-      as_bad ("zdaoff() relocation used on an instruction which does not support it");
+      as_bad (_("zdaoff() relocation used on an instruction which does not support it"));
       return BFD_RELOC_64;  /* Used to indicate an error condition.  */
     }
   
@@ -1374,15 +1485,13 @@ handle_tdaoff (const struct v850_operand * operand)
 {
   if (operand == NULL)                               return BFD_RELOC_V850_TDA_7_7_OFFSET;  /* data item, not an instruction.  */
   if (operand->bits == 6 && operand->shift == 1)     return BFD_RELOC_V850_TDA_6_8_OFFSET;  /* sld.w/sst.w, operand: D8_6  */
-  /* start-sanitize-v850e */
   if (operand->bits == 4 && operand->insert != NULL) return BFD_RELOC_V850_TDA_4_5_OFFSET;  /* sld.hu, operand: D5-4 */
   if (operand->bits == 4 && operand->insert == NULL) return BFD_RELOC_V850_TDA_4_4_OFFSET;  /* sld.bu, operand: D4   */
-  /* end-sanitize-v850e */
   if (operand->bits == 16 && operand->shift == 16)   return BFD_RELOC_V850_TDA_16_16_OFFSET; /* set1 & chums, operands: D16 */
   
   if (operand->bits != 7)
     {
-      as_bad ("tdaoff() relocation used on an instruction which does not support it");
+      as_bad (_("tdaoff() relocation used on an instruction which does not support it"));
       return BFD_RELOC_64;  /* Used to indicate an error condition.  */
     }
   
@@ -1421,11 +1530,8 @@ v850_reloc_prefix (const struct v850_operand * operand)
   CHECK_ ("sdaoff", handle_sdaoff (operand));
   CHECK_ ("zdaoff", handle_zdaoff (operand));
   CHECK_ ("tdaoff", handle_tdaoff (operand));
-
-/* start-sanitize-v850e */
   CHECK_ ("hilo",   BFD_RELOC_32);
   CHECK_ ("ctoff",  handle_ctoff (operand));
-/* end-sanitize-v850e */
   
   /* Restore skipped parenthesis.  */
   if (paren_skipped)
@@ -1434,6 +1540,118 @@ v850_reloc_prefix (const struct v850_operand * operand)
   return BFD_RELOC_UNUSED;
 }
 
+/* Insert an operand value into an instruction.  */
+
+static unsigned long
+v850_insert_operand (insn, operand, val, file, line, str)
+     unsigned long               insn;
+     const struct v850_operand * operand;
+     offsetT                     val;
+     char *                      file;
+     unsigned int                line;
+     char *                      str;
+{
+  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;
+         offsetT test;
+
+         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)
+           {
+             /* xgettext:c-format */
+             const char * err = _("operand out of range (%s not between %ld and %ld)");
+             char         buf[100];
+             
+             /* 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);
+                 
+                 sprint_value (buf + strlen (buf), val);
+               }
+             else
+               sprint_value (buf, val);
+             
+             if (file == (char *) NULL)
+               as_warn (err, buf, min, max);
+             else
+               as_warn_where (file, line, err, buf, min, max);
+           }
+       }
+
+      insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
+    }
+  
+  return insn;
+}
+
+\f
+static char                 copy_of_instruction [128];
+
 void
 md_assemble (str) 
      char * str;
@@ -1455,6 +1673,9 @@ md_assemble (str)
   unsigned long             extra_data;
   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;
@@ -1463,10 +1684,11 @@ md_assemble (str)
     *s++ = '\0';
 
   /* find the first opcode with the proper name */
-  opcode = (struct v850_opcode *)hash_find (v850_hash, str);
+  opcode = (struct v850_opcode *) hash_find (v850_hash, str);
   if (opcode == NULL)
     {
-      as_bad ("Unrecognized opcode: `%s'", str);
+      /* xgettext:c-format */
+      as_bad (_("Unrecognized opcode: `%s'"), str);
       ignore_rest_of_line ();
       return;
     }
@@ -1487,7 +1709,7 @@ md_assemble (str)
       
       if ((opcode->processors & processor_mask) == 0)
        {
-         errmsg = "Target processor does not support this instruction.";
+         errmsg = _("Target processor does not support this instruction.");
          goto error;
        }
       
@@ -1499,7 +1721,7 @@ md_assemble (str)
 
       input_line_pointer = str = start_of_operands;
 
-      for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
+      for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr ++)
        {
          const struct v850_operand * operand;
          char *                      hold;
@@ -1519,7 +1741,7 @@ md_assemble (str)
          errmsg = NULL;
 
          while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
-           ++str;
+           ++ str;
 
          if (operand->flags & V850_OPERAND_RELAX)
            relaxable = 1;
@@ -1531,7 +1753,8 @@ md_assemble (str)
          /* lo(), hi(), hi0(), etc... */
          if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED)
            {
-             if (reloc == BFD_RELOC_64) /* This is a fake reloc, used to indicate an error condition.  */
+             /* This is a fake reloc, used to indicate an error condition.  */
+             if (reloc == BFD_RELOC_64)
                {
                  match = 1;
                  goto error;
@@ -1544,7 +1767,8 @@ md_assemble (str)
                  switch (reloc)
                    {
                    case BFD_RELOC_V850_ZDA_16_16_OFFSET:
-                     /* To cope with "not1 7, zdaoff(0xfffff006)[r0]"  and the like.  */
+                     /* To cope with "not1 7, zdaoff(0xfffff006)[r0]"
+                        and the like.  */
                      /* Fall through.  */
                      
                    case BFD_RELOC_LO16:
@@ -1572,11 +1796,10 @@ md_assemble (str)
                        break;
                      }
                    
-/* start-sanitize-v850e */
                    case BFD_RELOC_32:
                      if ((operand->flags & V850E_IMMEDIATE32) == 0)
                        {
-                         errmsg = "use bigger instruction";
+                         errmsg = _("immediate operand is too large");
                          goto error;
                        }
                      
@@ -1585,16 +1808,20 @@ md_assemble (str)
                      extra_data            = ex.X_add_number;
                      ex.X_add_number       = 0;
                      break;
-/* end-sanitize-v850e */
                      
                    default:
                      fprintf (stderr, "reloc: %d\n", reloc);
-                     as_bad ("AAARG -> unhandled constant reloc");
+                     as_bad (_("AAARG -> unhandled constant reloc"));
                      break;
                    }
 
-                 insn = v850_insert_operand (insn, operand, ex.X_add_number,
-                                             (char *) NULL, 0);
+                 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
                {
@@ -1602,18 +1829,17 @@ md_assemble (str)
                    {
                      if ((operand->flags & V850E_IMMEDIATE32) == 0)
                        {
-                         errmsg = "use bigger instruction";
+                         errmsg = _("immediate operand is too large");
                          goto error;
                        }
                      
                      extra_data_after_insn = true;
                      extra_data_len        = 4;
                      extra_data            = ex.X_add_number;
-                     ex.X_add_number       = 0;
                    }
                      
                  if (fc > MAX_INSN_FIXUPS)
-                   as_fatal ("too many fixups");
+                   as_fatal (_("too many fixups"));
 
                  fixups[ fc ].exp     = ex;
                  fixups[ fc ].opindex = * opindex_ptr;
@@ -1629,20 +1855,24 @@ md_assemble (str)
                {
                  if (!register_name (& ex))
                    {
-                     errmsg = "invalid register name";
+                     errmsg = _("invalid register name");
                    }
-
-                 if ((operand->flags & V850_NOT_R0)
+                 else if ((operand->flags & V850_NOT_R0)
                      && ex.X_add_number == 0)
                    {
-                     errmsg = "register r0 cannot be used here";
+                     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))
+                 if (!system_register_name (& ex, true, false))
                    {
-                     errmsg = "invalid system register name";
+                     errmsg = _("invalid system register name");
                    }
                }
              else if ((operand->flags & V850_OPERAND_EP) != 0)
@@ -1655,7 +1885,7 @@ md_assemble (str)
                      /* Put things back the way we found them.  */
                      *input_line_pointer = c;
                      input_line_pointer = start;
-                     errmsg = "expected EP register";
+                     errmsg = _("expected EP register");
                      goto error;
                    }
                  
@@ -1664,22 +1894,22 @@ md_assemble (str)
                  input_line_pointer = hold;
              
                  while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
-                   ++str;
+                   ++ str;
                  continue;
                }
              else if ((operand->flags & V850_OPERAND_CC) != 0) 
                {
                  if (!cc_name (& ex))
                    {
-                     errmsg = "invalid condition code name";
+                     errmsg = _("invalid condition code name");
                    }
                }
-/* start-sanitize-v850e */
              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.  */
+                 /* The parse_register_list() function has already done
+                    everything, so fake a dummy expression.  */
                  ex.X_op         = O_constant;
                  ex.X_add_number = 0;
                }
@@ -1688,15 +1918,15 @@ md_assemble (str)
                  expression (& ex);
 
                  if (ex.X_op != O_constant)
-                   errmsg = "constant expression expected";
+                   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";
+                       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";
+                       errmsg = _("constant too big to fit into instruction");
                    }
                  
                  extra_data_after_insn = true;
@@ -1709,78 +1939,120 @@ md_assemble (str)
                  expression (& ex);
                  
                  if (ex.X_op != O_constant)
-                   errmsg = "constant expression expected";
+                   errmsg = _("constant expression expected");
                  
                  extra_data_after_insn = true;
                  extra_data_len        = 4;
                  extra_data            = ex.X_add_number;
                  ex.X_add_number       = 0;
                }
-/* end-sanitize-v850e */
-             else if (register_name (&ex)
+             else if (register_name (& ex)
                       && (operand->flags & V850_OPERAND_REG) == 0)
                {
-                 errmsg = "syntax error: register not expected";
+                 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 occuring 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)
+             else if (system_register_name (& ex, false, false)
                       && (operand->flags & V850_OPERAND_SRG) == 0)
                {
-                 errmsg = "syntax error: system register not expected";
+                 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";
+                 errmsg = _("syntax error: condition code not expected");
                }
              else
                {
                  expression (& ex);
-/* start-sanitize-v850e */
                  /* Special case:
                     If we are assembling a MOV instruction (or a CALLT.... :-)
-                    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.  */
+                    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)
                      && ex.X_op == O_constant
-                     && (ex.X_add_number < (- (1 << (operand->bits - 1))) || ex.X_add_number > ((1 << operand->bits) - 1)))
-                   errmsg = "use bigger instruction";
-/* end-sanitize-v850e */
+                     && (ex.X_add_number < (- (1 << (operand->bits - 1)))
+                         || ex.X_add_number > ((1 << operand->bits) - 1)))
+                   errmsg = _("immediate operand is too large");
                }
 
              if (errmsg)
                goto error;
              
-/* fprintf (stderr, " insn: %x, operand %d, op: %d, add_number: %d\n", insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number); */
+/* fprintf (stderr, " insn: %x, operand %d, op: %d, add_number: %d\n",
+   insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number); */
 
              switch (ex.X_op) 
                {
                case O_illegal:
-                 errmsg = "illegal operand";
+                 errmsg = _("illegal operand");
                  goto error;
                case O_absent:
-                 errmsg = "missing operand";
+                 errmsg = _("missing operand");
                  goto error;
                case O_register:
                  if ((operand->flags & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0)
                    {
-                     errmsg = "invalid operand";
+                     errmsg = _("invalid operand");
                      goto error;
                    }
                  insn = v850_insert_operand (insn, operand, ex.X_add_number,
-                                             (char *) NULL, 0);
+                                             (char *) NULL, 0,
+                                             copy_of_instruction);
                  break;
 
                case O_constant:
                  insn = v850_insert_operand (insn, operand, ex.X_add_number,
-                                             (char *) NULL, 0);
+                                             (char *) 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");
+                   as_fatal (_("too many fixups"));
 
                  fixups[ fc ].exp     = ex;
                  fixups[ fc ].opindex = * opindex_ptr;
@@ -1803,13 +2075,24 @@ md_assemble (str)
       if (match == 0)
         {
          next_opcode = opcode + 1;
-         if (next_opcode->name != NULL && strcmp (next_opcode->name, opcode->name) == 0)
+         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 (errmsg);
+         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;
@@ -1821,7 +2104,8 @@ md_assemble (str)
     ++str;
 
   if (*str != '\0')
-    as_bad ("junk at end of line: `%s'", str);
+    /* xgettext:c-format */
+    as_bad (_("junk at end of line: `%s'"), str);
 
   input_line_pointer = str;
 
@@ -1859,11 +2143,9 @@ md_assemble (str)
       else
        insn_size = 2;
 
-/* start-sanitize-v850e */
       /* Special case: 32 bit MOV */
       if ((insn & 0xffe0) == 0x0620)
        insn_size = 2;
-/* end-sanitize-v850e */
       
       f = frag_more (insn_size);
       
@@ -1896,7 +2178,8 @@ md_assemble (str)
       
       if (reloc != BFD_RELOC_UNUSED)
        {
-         reloc_howto_type * reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
+         reloc_howto_type * reloc_howto = bfd_reloc_type_lookup (stdoutput,
+                                                                 reloc);
          int                size;
          int                address;
          fixS *             fixP;
@@ -1906,8 +2189,10 @@ md_assemble (str)
          
          size = bfd_get_reloc_size (reloc_howto);
 
-         if (size != 2 && size != 4) /* XXX this will abort on an R_V850_8 reloc - is this reloc actually used ? */
-           abort();
+         /* 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;
 
@@ -1937,7 +2222,8 @@ md_assemble (str)
                       f - frag_now->fr_literal, 4,
                       & fixups[i].exp,
                       1 /* FIXME: V850_OPERAND_RELATIVE ??? */,
-                      (bfd_reloc_code_real_type) (fixups[i].opindex + (int) BFD_RELOC_UNUSED)
+                      (bfd_reloc_code_real_type) (fixups[i].opindex
+                                                  + (int) BFD_RELOC_UNUSED)
                       );
        }
     }
@@ -1957,21 +2243,28 @@ tc_gen_reloc (seg, fixp)
   arelent * reloc;
   
   reloc              = (arelent *) xmalloc (sizeof (arelent));
-  reloc->sym_ptr_ptr = & fixp->fx_addsy->bsym;
+  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  *reloc->sym_ptr_ptr= symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address     = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto       = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
 
   if (reloc->howto == (reloc_howto_type *) NULL)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
-                    "reloc %d not supported by object file format", (int)fixp->fx_r_type);
+                   /* xgettext:c-format */
+                    _("reloc %d not supported by object file format"),
+                   (int) fixp->fx_r_type);
 
       xfree (reloc);
       
       return NULL;
     }
   
-  reloc->addend = fixp->fx_addnumber;
+  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+      || fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
+    reloc->addend = fixp->fx_offset;
+  else
+    reloc->addend = fixp->fx_addnumber;
   
   return reloc;
 }
@@ -1992,16 +2285,21 @@ md_estimate_size_before_relax (fragp, seg)
 } 
 
 long
-md_pcrel_from (fixp)
+v850_pcrel_from_section (fixp, section)
      fixS * fixp;
+     segT   section;
 {
   /* If the symbol is undefined, or in a section other than our own,
      then let the linker figure it out.  */
-  if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
+  if (fixp->fx_addsy != (symbolS *) NULL
+      && (! S_IS_DEFINED (fixp->fx_addsy)
+         || (S_GET_SEGMENT (fixp->fx_addsy) != section)))
     {
-      /* The symbol is undefined.  Let the linker figure it out.  */
+      /* The symbol is undefined/not in our section.
+        Let the linker figure it out.  */
       return 0;
     }
+
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
 
@@ -2014,6 +2312,13 @@ md_apply_fix3 (fixp, valuep, seg)
   valueT value;
   char * where;
 
+  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+    {
+      fixp->fx_done = 0;
+      return 1;
+    }
+
   if (fixp->fx_addsy == (symbolS *) NULL)
     {
       value = * valuep;
@@ -2032,7 +2337,7 @@ md_apply_fix3 (fixp, valuep, seg)
            {
              /* We don't actually support subtracting a symbol.  */
              as_bad_where (fixp->fx_file, fixp->fx_line,
-                           "expression too complex");
+                           _("expression too complex"));
            }
        }
     }
@@ -2055,7 +2360,7 @@ md_apply_fix3 (fixp, valuep, seg)
 
       insn = bfd_getl32 ((unsigned char *) where);
       insn = v850_insert_operand (insn, operand, (offsetT) value,
-                                 fixp->fx_file, fixp->fx_line);
+                                 fixp->fx_file, fixp->fx_line, NULL);
       bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
 
       if (fixp->fx_done)
@@ -2075,8 +2380,8 @@ md_apply_fix3 (fixp, valuep, seg)
        {
          /* fprintf (stderr, "bits: %d, insn: %x\n", operand->bits, insn); */
          
-         as_bad_where(fixp->fx_file, fixp->fx_line,
-                      "unresolved expression that must be resolved");
+         as_bad_where (fixp->fx_file, fixp->fx_line,
+                      _("unresolved expression that must be resolved"));
          fixp->fx_done = 1;
          return 1;
        }
@@ -2087,7 +2392,7 @@ md_apply_fix3 (fixp, valuep, seg)
       where = fixp->fx_frag->fr_literal + fixp->fx_where;
 
       if (fixp->fx_size == 1)
-       *where = value & 0xff;
+       * where = value & 0xff;
       else if (fixp->fx_size == 2)
        bfd_putl16 (value & 0xffff, (unsigned char *) where);
       else if (fixp->fx_size == 4)
@@ -2099,76 +2404,6 @@ md_apply_fix3 (fixp, valuep, seg)
 }
 
 \f
-/* Insert an operand value into an instruction.  */
-
-static unsigned long
-v850_insert_operand (insn, operand, val, file, line)
-     unsigned long insn;
-     const struct v850_operand * operand;
-     offsetT val;
-     char *file;
-     unsigned int line;
-{
-  if (operand->insert)
-    {
-      const char * message = NULL;
-      
-      insn = (*operand->insert) (insn, val, & message);
-      if (message != NULL)
-       {
-         if (file == (char *) NULL)
-           as_warn (message);
-         else
-           as_warn_where (file, line, message);
-       }
-    }
-  else
-    {
-      if (operand->bits != 32)
-       {
-         long    min, max;
-         offsetT test;
-
-         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;
-           }
-         
-         test = val;
-         
-         if (test < (offsetT) min || test > (offsetT) max)
-           {
-             const char * err = "operand out of range (%s not between %ld and %ld)";
-             char         buf[100];
-             
-             sprint_value (buf, test);
-             if (file == (char *) NULL)
-               as_warn (err, buf, min, max);
-             else
-               as_warn_where (file, line, err, buf, min, max);
-           }
-       }
-
-      insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
-    }
-  
-  return insn;
-}
-
 /* Parse a cons expression.  We have to handle hi(), lo(), etc
    on the v850.  */
 void
@@ -2207,3 +2442,38 @@ cons_fix_new_v850 (frag, where, size, exp)
   else
     fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc);
 }
+boolean
+v850_fix_adjustable (fixP)
+    fixS *fixP;
+{
+  if (fixP->fx_addsy == NULL)
+    return 1;
+  /* Prevent all adjustments to global symbols. */
+  if (S_IS_EXTERN (fixP->fx_addsy))
+    return 0;
+  if (S_IS_WEAK (fixP->fx_addsy))
+    return 0;
+  /* 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;
+}
+int
+v850_force_relocation (fixp)
+      struct fix *fixp;
+{
+  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+    return 1;
+  return 0;
+}