* ppc-dis.c (struct dis_private): New.
[deliverable/binutils-gdb.git] / gas / config / tc-vax.c
index 3d76647c5b933047f24022c0ebb87a94f4b53948..24256634a9cad64ff12b40d6dbeb06dc07d15bf5 100644 (file)
@@ -1,5 +1,6 @@
 /* tc-vax.c - vax-specific -
-   Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+   Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2001, 2002
+   Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/* JF I moved almost all the vax specific stuff into this one file 'cuz RMS
-   seems to think its a good idea.  I hope I managed to get all the VAX-isms */
-
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "as.h"
 
 #include "vax-inst.h"
 #include "obstack.h"           /* For FRAG_APPEND_1_CHAR macro in "frags.h" */
+#include "subsegs.h"
+
+#ifdef OBJ_ELF
+#include "elf/vax.h"
+#endif
 
 /* These chars start a comment anywhere in a source file (except inside
    another comment */
 const char comment_chars[] = "#";
 
-/* These chars only start a comment at the beginning of a line. */
-/* Note that for the VAX the are the same as comment_chars above. */
+/* These chars only start a comment at the beginning of a line.  */
+/* Note that for the VAX the are the same as comment_chars above.  */
 const char line_comment_chars[] = "#";
 
-const char line_separator_chars[] = "";
+const char line_separator_chars[] = ";";
 
 /* Chars that can be used to separate mant from exp in floating point nums */
 const char EXP_CHARS[] = "eE";
@@ -46,20 +49,34 @@ const char FLT_CHARS[] = "dDfFgGhH";
 
 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
    changed in read.c .  Ideally it shouldn't have to know about it at all,
-   but nothing is ideal around here.
-   */
+   but nothing is ideal around here.  */
 
-static expressionS             /* Hold details of an operand expression */
-  exp_of_operand[VIT_MAX_OPERANDS];
+/* Hold details of an operand expression */
+static expressionS exp_of_operand[VIT_MAX_OPERANDS];
+static segT seg_of_operand[VIT_MAX_OPERANDS];
 
-static struct vit
-  v;                           /* A vax instruction after decoding. */
+/* A vax instruction after decoding.  */
+static struct vit v;
 
+/* Hold details of big operands.  */
 LITTLENUM_TYPE big_operand_bits[VIT_MAX_OPERANDS][SIZE_OF_LARGE_NUMBER];
-/* Hold details of big operands. */
 FLONUM_TYPE float_operand[VIT_MAX_OPERANDS];
-/* Above is made to point into */
-/* big_operand_bits by md_begin(). */
+/* Above is made to point into big_operand_bits by md_begin().  */
+
+#ifdef OBJ_ELF
+#define GLOBAL_OFFSET_TABLE_NAME       "_GLOBAL_OFFSET_TABLE_"
+#define PROCEDURE_LINKAGE_TABLE_NAME   "_PROCEDURE_LINKAGE_TABLE_"
+symbolS *GOT_symbol;           /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
+symbolS *PLT_symbol;           /* Pre-defined "_PROCEDURE_LINKAGE_TABLE_" */
+#endif
+
+int flag_hash_long_names;      /* -+ */
+int flag_one;                  /* -1 */
+int flag_show_after_trunc;     /* -H */
+int flag_no_hash_mixed_case;   /* -h NUM */
+#ifdef OBJ_ELF
+int flag_want_pic;             /* -k */
+#endif
 \f
 /*
  * For VAX, relative addresses of "just the right length" are easy.
@@ -111,8 +128,6 @@ FLONUM_TYPE float_operand[VIT_MAX_OPERANDS];
  bbcs          e3
  bbsc          e4
  bbcc          e5
- bbssi         e6
- bbcci         e7
  Always, you complement 0th bit to reverse condition.
  Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement
 
@@ -169,48 +184,52 @@ FLONUM_TYPE float_operand[VIT_MAX_OPERANDS];
  after relax() what the original addressing mode was.
  */
 \f
-/* These displacements are relative to */
-/* the start address of the displacement. */
-/* The first letter is Byte, Word. */
-/* 2nd letter is Forward, Backward. */
+/* These displacements are relative to the start address of the
+   displacement.  The first letter is Byte, Word.  2nd letter is
+   Forward, Backward.  */
 #define BF (1+ 127)
 #define BB (1+-128)
 #define WF (2+ 32767)
 #define WB (2+-32768)
-/* Dont need LF, LB because they always */
-/* reach. [They are coded as 0.] */
-
+/* Dont need LF, LB because they always reach. [They are coded as 0.] */
 
 #define C(a,b) ENCODE_RELAX(a,b)
-/* This macro has no side-effects. */
+/* This macro has no side-effects.  */
 #define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+#define RELAX_STATE(s) ((s) >> 2)
+#define RELAX_LENGTH(s) ((s) & 3)
 
-const relax_typeS
-  md_relax_table[] =
+const relax_typeS md_relax_table[] =
 {
   {1, 1, 0, 0},                        /* error sentinel   0,0 */
   {1, 1, 0, 0},                        /* unused           0,1 */
   {1, 1, 0, 0},                        /* unused           0,2 */
   {1, 1, 0, 0},                        /* unused           0,3 */
+
   {BF + 1, BB + 1, 2, C (1, 1)},/* B^"foo"         1,0 */
   {WF + 1, WB + 1, 3, C (1, 2)},/* W^"foo"         1,1 */
   {0, 0, 5, 0},                        /* L^"foo"          1,2 */
   {1, 1, 0, 0},                        /* unused           1,3 */
+
   {BF, BB, 1, C (2, 1)},       /* b<cond> B^"foo"  2,0 */
   {WF + 2, WB + 2, 4, C (2, 2)},/* br.+? brw X     2,1 */
   {0, 0, 7, 0},                        /* br.+? jmp X      2,2 */
   {1, 1, 0, 0},                        /* unused           2,3 */
+
   {BF, BB, 1, C (3, 1)},       /* brb B^foo        3,0 */
   {WF, WB, 2, C (3, 2)},       /* brw W^foo        3,1 */
   {0, 0, 5, 0},                        /* Jmp L^foo        3,2 */
   {1, 1, 0, 0},                        /* unused           3,3 */
+
   {1, 1, 0, 0},                        /* unused           4,0 */
   {WF, WB, 2, C (4, 2)},       /* acb_ ^Wfoo       4,1 */
   {0, 0, 10, 0},               /* acb_,br,jmp L^foo4,2 */
   {1, 1, 0, 0},                        /* unused           4,3 */
+
   {BF, BB, 1, C (5, 1)},       /* Xob___,,foo      5,0 */
   {WF + 4, WB + 4, 6, C (5, 2)},/* Xob.+2,brb.+3,brw5,1 */
   {0, 0, 9, 0},                        /* Xob.+2,brb.+6,jmp5,2 */
+  {1, 1, 0, 0},                        /* unused           5,3 */
 };
 
 #undef C
@@ -219,7 +238,7 @@ const relax_typeS
 #undef WF
 #undef WB
 
-void float_cons ();
+void float_cons PARAMS ((int));
 
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -227,12 +246,12 @@ const pseudo_typeS md_pseudo_table[] =
   {"ffloat", float_cons, 'f'},
   {"gfloat", float_cons, 'g'},
   {"hfloat", float_cons, 'h'},
-  {0},
+  {NULL, NULL, 0},
 };
 
 #define STATE_PC_RELATIVE              (1)
 #define STATE_CONDITIONAL_BRANCH       (2)
-#define STATE_ALWAYS_BRANCH            (3)     /* includes BSB... */
+#define STATE_ALWAYS_BRANCH            (3)     /* includes BSB...  */
 #define STATE_COMPLEX_BRANCH           (4)
 #define STATE_COMPLEX_HOP              (5)
 
@@ -241,34 +260,29 @@ const pseudo_typeS md_pseudo_table[] =
 #define STATE_LONG                     (2)
 #define STATE_UNDF                     (3)     /* Symbol undefined in pass1 */
 
-
 #define min(a, b)      ((a) < (b) ? (a) : (b))
 
-#if __STDC__ == 1
-
-int flonum_gen2vax (char format_letter, FLONUM_TYPE * f, LITTLENUM_TYPE * words);
-static void vip_end (void);
-static void vip_op_defaults (char *immediate, char *indirect, char *displen);
+int flonum_gen2vax PARAMS ((char format_letter, FLONUM_TYPE * f,
+                           LITTLENUM_TYPE * words));
+static const char *vip_begin PARAMS ((int, const char *, const char *,
+                                     const char *));
+static void vip_op_1 PARAMS ((int, const char *));
+static void vip_op_defaults PARAMS ((const char *, const char *, const char *));
+static void vip_op PARAMS ((char *, struct vop *));
+static void vip PARAMS ((struct vit *, char *));
 
-#else /* not __STDC__ */
-
-int flonum_gen2vax ();
-static void vip_end ();
-static void vip_op_defaults ();
-
-#endif /* not __STDC__ */
+static int vax_reg_parse PARAMS ((char, char, char, char));
 
 void
 md_begin ()
 {
-  char *vip_begin ();
-  char *errtxt;
+  const char *errtxt;
   FLONUM_TYPE *fP;
   int i;
 
-  if (*(errtxt = vip_begin (1, "$", "*", "`")))
+  if ((errtxt = vip_begin (1, "$", "*", "`")) != 0)
     {
-      as_fatal ("VIP_BEGIN error:%s", errtxt);
+      as_fatal (_("VIP_BEGIN error:%s"), errtxt);
     }
 
   for (i = 0, fP = float_operand;
@@ -279,57 +293,43 @@ md_begin ()
       fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];
     }
 }
-
-void
-md_end ()
-{
-  vip_end ();
-}
 \f
-void                           /* Knows about order of bytes in address. */
+void
 md_number_to_chars (con, value, nbytes)
-     char con[];               /* Return 'nbytes' of chars here. */
-     long value;               /* The value of the bits. */
-     int nbytes;               /* Number of bytes in the output. */
+     char con[];
+     valueT value;
+     int nbytes;
 {
-  int n;
-  long v;
-
-  n = nbytes;
-  v = value;
-  while (nbytes--)
-    {
-      *con++ = value;          /* Lint wants & MASK_CHAR. */
-      value >>= BITS_PER_CHAR;
-    }
-  /* XXX line number probably botched for this warning message. */
-  if (value != 0 && value != -1)
-    as_bad ("Displacement (%ld) long for instruction field length (%d).", v, n);
+  number_to_chars_littleendian (con, value, nbytes);
 }
 
 /* Fix up some data or instructions after we find out the value of a symbol
    that they reference.  */
 
-void                           /* Knows about order of bytes in address. */
-md_apply_fix (fixP, value)
-     fixS *fixP;               /* Fixup struct pointer */
-     long value;               /* The value of the bits. */
+void                           /* Knows about order of bytes in address.  */
+md_apply_fix3 (fixP, valueP, seg)
+     fixS *fixP;
+     valueT *valueP;
+     segT seg ATTRIBUTE_UNUSED;
 {
-  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
-  int nbytes;                  /* Number of bytes in the output. */
+  valueT value = * valueP;
+#ifdef BFD_ASSEMBLER
+  if (((fixP->fx_addsy == NULL && fixP->fx_subsy == NULL)
+       && fixP->fx_r_type != BFD_RELOC_32_PLT_PCREL
+       && fixP->fx_r_type != BFD_RELOC_32_GOT_PCREL)
+      || fixP->fx_r_type == NO_RELOC)
+#endif
+    number_to_chars_littleendian (fixP->fx_where + fixP->fx_frag->fr_literal,
+                                 value, fixP->fx_size);
 
-  nbytes = fixP->fx_size;
-  while (nbytes--)
-    {
-      *buf++ = value;          /* Lint wants & MASK_CHAR. */
-      value >>= BITS_PER_CHAR;
-    }
+  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+    fixP->fx_done = 1;
 }
 
-long                           /* Knows about the byte order in a word. */
+long
 md_chars_to_number (con, nbytes)
-     unsigned char con[];      /* Low order byte 1st. */
-     int nbytes;               /* Number of bytes in the input. */
+     unsigned char con[];      /* Low order byte 1st.  */
+     int nbytes;               /* Number of bytes in the input.  */
 {
   long retval;
   for (retval = 0, con += nbytes - 1; nbytes--; con--)
@@ -344,48 +344,53 @@ md_chars_to_number (con, nbytes)
 
 void
 md_assemble (instruction_string)
-     char *instruction_string; /* A string: assemble 1 instruction. */
+     char *instruction_string; /* A string: assemble 1 instruction.  */
 {
-  /* We saw no errors in any operands - try to make frag(s) */
-  int is_undefined;            /* 1 if operand expression's */
-  /* segment not known yet. */
-  int length_code;
+  /* Non-zero if operand expression's segment is not known yet.  */
+  int is_undefined;
+  /* Non-zero if operand expression's segment is absolute.  */
+  int is_absolute;
 
+  int length_code;
   char *p;
-  register struct vop *operandP;/* An operand. Scans all operands. */
+  /* An operand. Scans all operands.  */
+  struct vop *operandP;
   char *save_input_line_pointer;
-  char c_save;                 /* What used to live after an expression. */
-  /* fixme: unused? */
-  /*   struct frag *fragP; *//* Fragment of code we just made. */
-  register int goofed;         /* 1: instruction_string bad for all passes. */
-  register struct vop *end_operandP;   /* -> slot just after last operand */
-  /* Limit of the for (each operand). */
-  register expressionS *expP;  /* -> expression values for this operand */
-
-  /* These refer to an instruction operand expression. */
-  segT to_seg;                 /* Target segment of the address.        */
-  register valueT this_add_number;
-  register struct symbol *this_add_symbol;     /* +ve (minuend) symbol. */
-  register struct symbol *this_subtract_symbol;        /* -ve(subtrahend) symbol. */
-
-  long opcode_as_number;       /* As a number. */
-  char *opcode_as_chars;       /* Least significant byte 1st. */
-  /* As an array of characters. */
-  char *opcode_low_byteP;      /* Least significant byte 1st */
-  /* richfix: unused? */
-  /*   struct details *detP; *//* The details of an ADxxx frag. */
-  int length;                  /* length (bytes) meant by vop_short. */
-  int at;                      /* 0, or 1 if '@' is in addressing mode. */
-  int nbytes;                  /* From vop_nbytes: vax_operand_width (in bytes) */
+                       /* What used to live after an expression.  */
+  char c_save;
+  /* 1: instruction_string bad for all passes.  */
+  int goofed;
+  /* Points to slot just after last operand.  */
+  struct vop *end_operandP;
+  /* Points to expression values for this operand.  */
+  expressionS *expP;
+  segT *segP;
+
+  /* These refer to an instruction operand expression.  */
+  /* Target segment of the address.     */
+  segT to_seg;
+  valueT this_add_number;
+  /* Positive (minuend) symbol.  */
+  symbolS *this_add_symbol;
+  /* As a number.  */
+  long opcode_as_number;
+  /* Least significant byte 1st.  */
+  char *opcode_as_chars;
+  /* As an array of characters.  */
+  /* Least significant byte 1st */
+  char *opcode_low_byteP;
+  /* length (bytes) meant by vop_short.  */
+  int length;
+  /* 0, or 1 if '@' is in addressing mode.  */
+  int at;
+  /* From vop_nbytes: vax_operand_width (in bytes) */
+  int nbytes;
   FLONUM_TYPE *floatP;
-  char *vip ();
   LITTLENUM_TYPE literal_float[8];
-  /* Big enough for any floating point literal. */
+  /* Big enough for any floating point literal.  */
+
+  vip (&v, instruction_string);
 
-  if (*(p = vip (&v, instruction_string)))
-    {
-      as_fatal ("vax_assemble\"%s\" in=\"%s\"", p, instruction_string);
-    }
   /*
    * Now we try to find as many as_warn()s as we can. If we do any as_warn()s
    * then goofed=1. Notice that we don't make any frags yet.
@@ -393,9 +398,9 @@ md_assemble (instruction_string)
    * and we can safely flush it, without causing interpass symbol phase
    * errors. That is, without changing label values in different passes.
    */
-  if (goofed = (*v.vit_error))
+  if ((goofed = (*v.vit_error)) != 0)
     {
-      as_warn ("Ignoring statement due to \"%s\"", v.vit_error);
+      as_fatal (_("Ignoring statement due to \"%s\""), v.vit_error);
     }
   /*
    * We need to use expression() and friends, which require us to diddle
@@ -404,68 +409,68 @@ md_assemble (instruction_string)
   save_input_line_pointer = input_line_pointer;
   for (operandP = v.vit_operand,
        expP = exp_of_operand,
+       segP = seg_of_operand,
        floatP = float_operand,
        end_operandP = v.vit_operand + v.vit_operands;
 
        operandP < end_operandP;
 
-       operandP++, expP++, floatP++)
+       operandP++, expP++, segP++, floatP++)
     {                          /* for each operand */
-      if (*(operandP->vop_error))
+      if (operandP->vop_error)
        {
-         as_warn ("Ignoring statement because \"%s\"", (operandP->vop_error));
+         as_fatal (_("Aborting because statement has \"%s\""), operandP->vop_error);
          goofed = 1;
        }
       else
        {
-         /* statement has no syntax goofs: lets sniff the expression */
-         int can_be_short = 0; /* 1 if a bignum can be reduced to a short literal. */
+         /* Statement has no syntax goofs: let's sniff the expression.  */
+         int can_be_short = 0; /* 1 if a bignum can be reduced to a short literal.  */
 
          input_line_pointer = operandP->vop_expr_begin;
          c_save = operandP->vop_expr_end[1];
          operandP->vop_expr_end[1] = '\0';
-         /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = 1. */
-         switch (to_seg = expression (expP))
+         /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = 1.  */
+         *segP = expression (expP);
+         switch (expP->X_op)
            {
-           case SEG_ABSENT:
+           case O_absent:
              /* for BSD4.2 compatibility, missing expression is absolute 0 */
-             to_seg = expP->X_seg = SEG_ABSOLUTE;
+             expP->X_op = O_constant;
              expP->X_add_number = 0;
-             /* For SEG_ABSOLUTE, we shouldn't need to set X_subtract_symbol,
+             /* For SEG_ABSOLUTE, we shouldn't need to set X_op_symbol,
                 X_add_symbol to any particular value.  But, we will program
                 defensively. Since this situation occurs rarely so it costs
                 us little to do, and stops Dean worrying about the origin of
                 random bits in expressionS's.  */
              expP->X_add_symbol = NULL;
-             expP->X_subtract_symbol = NULL;
-           case SEG_TEXT:
-           case SEG_DATA:
-           case SEG_BSS:
-           case SEG_ABSOLUTE:
-           case SEG_UNKNOWN:
+             expP->X_op_symbol = NULL;
              break;
 
-           case SEG_DIFFERENCE:
-           case SEG_PASS1:
+           case O_symbol:
+           case O_constant:
+             break;
+
+           default:
              /*
               * Major bug. We can't handle the case of a
-              * SEG_DIFFERENCE expression in a VIT_OPCODE_SYNTHETIC
+              * SEG_OP expression in a VIT_OPCODE_SYNTHETIC
               * variable-length instruction.
               * We don't have a frag type that is smart enough to
-              * relax a SEG_DIFFERENCE, and so we just force all
-              * SEG_DIFFERENCEs to behave like SEG_PASS1s.
+              * relax a SEG_OP, and so we just force all
+              * SEG_OPs to behave like SEG_PASS1s.
               * Clearly, if there is a demand we can invent a new or
               * modified frag type and then coding up a frag for this
-              * case will be easy. SEG_DIFFERENCE was invented for the
+              * case will be easy. SEG_OP was invented for the
               * .words after a CASE opcode, and was never intended for
               * instruction operands.
               */
              need_pass_2 = 1;
-             as_warn ("Can't relocate expression");
+             as_fatal (_("Can't relocate expression"));
              break;
 
-           case SEG_BIG:
-             /* Preserve the bits. */
+           case O_big:
+             /* Preserve the bits.  */
              if (expP->X_add_number > 0)
                {
                  bignum_copy (generic_bignum, expP->X_add_number,
@@ -477,7 +482,8 @@ md_assemble (instruction_string)
                  flonum_copy (&generic_floating_point_number,
                               floatP);
                  if (strchr ("s i", operandP->vop_short))
-                   {           /* Could possibly become S^# */
+                   {
+                     /* Could possibly become S^# */
                      flonum_gen2vax (-expP->X_add_number, floatP, literal_float);
                      switch (-expP->X_add_number)
                        {
@@ -527,25 +533,27 @@ md_assemble (instruction_string)
                      && operandP->vop_reg == 0xF
                      && (operandP->vop_mode & 0xE) == 0x8))
                {
-                 /* Saw a '#'. */
+                 /* Saw a '#'.  */
                  if (operandP->vop_short == ' ')
-                   {           /* We must chose S^ or I^. */
+                   {
+                     /* We must chose S^ or I^.  */
                      if (expP->X_add_number > 0)
-                       {       /* Bignum: Short literal impossible. */
+                       {
+                         /* Bignum: Short literal impossible.  */
                          operandP->vop_short = 'i';
                          operandP->vop_mode = 8;
-                         operandP->vop_reg = 0xF;      /* VAX PC. */
+                         operandP->vop_reg = 0xF;      /* VAX PC.  */
                        }
                      else
-                       {       /* Flonum: Try to do it. */
+                       {
+                         /* Flonum: Try to do it.  */
                          if (can_be_short)
                            {
                              operandP->vop_short = 's';
                              operandP->vop_mode = 0;
                              operandP->vop_ndx = -1;
                              operandP->vop_reg = -1;
-                             /* JF hope this is the right thing */
-                             expP->X_seg = SEG_ABSOLUTE;
+                             expP->X_op = O_constant;
                            }
                          else
                            {
@@ -554,29 +562,29 @@ md_assemble (instruction_string)
                              operandP->vop_reg = 0xF;  /* VAX PC */
                            }
                        }       /* bignum or flonum ? */
-                   }           /*  if #, but no S^ or I^ seen. */
-                 /* No more ' ' case: either 's' or 'i'. */
+                   }           /*  if #, but no S^ or I^ seen.  */
+                 /* No more ' ' case: either 's' or 'i'.  */
                  if (operandP->vop_short == 's')
                    {
-                     /* Wants to be a short literal. */
+                     /* Wants to be a short literal.  */
                      if (expP->X_add_number > 0)
                        {
-                         as_warn ("Bignum not permitted in short literal. Immediate mode assumed.");
+                         as_warn (_("Bignum not permitted in short literal. Immediate mode assumed."));
                          operandP->vop_short = 'i';
                          operandP->vop_mode = 8;
-                         operandP->vop_reg = 0xF;      /* VAX PC. */
+                         operandP->vop_reg = 0xF;      /* VAX PC.  */
                        }
                      else
                        {
                          if (!can_be_short)
                            {
-                             as_warn ("Can't do flonum short literal: immediate mode used.");
+                             as_warn (_("Can't do flonum short literal: immediate mode used."));
                              operandP->vop_short = 'i';
                              operandP->vop_mode = 8;
-                             operandP->vop_reg = 0xF;  /* VAX PC. */
+                             operandP->vop_reg = 0xF;  /* VAX PC.  */
                            }
                          else
-                           {   /* Encode short literal now. */
+                           {   /* Encode short literal now.  */
                              int temp = 0;
 
                              switch (-expP->X_add_number)
@@ -606,41 +614,37 @@ md_assemble (instruction_string)
                        }       /* flonum or bignum ? */
                    }
                  else
-                   {           /* I^# seen: set it up if float. */
+                   {           /* I^# seen: set it up if float.  */
                      if (expP->X_add_number < 0)
                        {
                          memcpy (floatP->low, literal_float, sizeof (literal_float));
                        }
-                   }           /* if S^# seen. */
+                   }           /* if S^# seen.  */
                }
              else
                {
-                 as_warn ("A bignum/flonum may not be a displacement: 0x%x used",
-                          expP->X_add_number = 0x80000000);
-                 /* Chosen so luser gets the most offset bits to patch later. */
+                 as_warn (_("A bignum/flonum may not be a displacement: 0x%lx used"),
+                          (expP->X_add_number = 0x80000000L));
+                 /* Chosen so luser gets the most offset bits to patch later.  */
                }
              expP->X_add_number = floatP->low[0]
                | ((LITTLENUM_MASK & (floatP->low[1])) << LITTLENUM_NUMBER_OF_BITS);
              /*
-                                * For the SEG_BIG case we have:
-                                * If vop_short == 's' then a short floating literal is in the
-                                *      lowest 6 bits of floatP -> low [0], which is
-                                *      big_operand_bits [---] [0].
-                                * If vop_short == 'i' then the appropriate number of elements
-                                *      of big_operand_bits [---] [...] are set up with the correct
-                                *      bits.
-                                * Also, just in case width is byte word or long, we copy the lowest
-                                * 32 bits of the number to X_add_number.
-                                */
-             break;
-
-           default:
-             BAD_CASE (to_seg);
+              * For the O_big case we have:
+              * If vop_short == 's' then a short floating literal is in the
+              *        lowest 6 bits of floatP -> low [0], which is
+              *        big_operand_bits [---] [0].
+              * If vop_short == 'i' then the appropriate number of elements
+              *        of big_operand_bits [---] [...] are set up with the correct
+              *        bits.
+              * Also, just in case width is byte word or long, we copy the lowest
+              * 32 bits of the number to X_add_number.
+              */
              break;
            }
          if (input_line_pointer != operandP->vop_expr_end + 1)
            {
-             as_warn ("Junk at end of expression \"%s\"", input_line_pointer);
+             as_fatal ("Junk at end of expression \"%s\"", input_line_pointer);
              goofed = 1;
            }
          operandP->vop_expr_end[1] = c_save;
@@ -654,14 +658,14 @@ md_assemble (instruction_string)
       return;
     }
 
-
-  /* Emit op-code. */
-  /* Remember where it is, in case we want to modify the op-code later. */
+  /* Emit op-code.  */
+  /* Remember where it is, in case we want to modify the op-code later.  */
   opcode_low_byteP = frag_more (v.vit_opcode_nbytes);
   memcpy (opcode_low_byteP, v.vit_opcode, v.vit_opcode_nbytes);
   opcode_as_number = md_chars_to_number (opcode_as_chars = v.vit_opcode, 4);
   for (operandP = v.vit_operand,
        expP = exp_of_operand,
+       segP = seg_of_operand,
        floatP = float_operand,
        end_operandP = v.vit_operand + v.vit_operands;
 
@@ -669,8 +673,9 @@ md_assemble (instruction_string)
 
        operandP++,
        floatP++,
+       segP++,
        expP++)
-    {                          /* for each operand */
+    {
       if (operandP->vop_ndx >= 0)
        {
          /* indexed addressing byte */
@@ -678,18 +683,17 @@ md_assemble (instruction_string)
          FRAG_APPEND_1_CHAR (0x40 + operandP->vop_ndx);
        }                       /* if(vop_ndx>=0) */
 
-      /* Here to make main operand frag(s). */
+      /* Here to make main operand frag(s).  */
       this_add_number = expP->X_add_number;
       this_add_symbol = expP->X_add_symbol;
-      this_subtract_symbol = expP->X_subtract_symbol;
-      to_seg = expP->X_seg;
+      to_seg = *segP;
+#ifdef BFD_ASSEMBLER
+      is_undefined = (to_seg == undefined_section);
+      is_absolute = (to_seg == absolute_section);
+#else
       is_undefined = (to_seg == SEG_UNKNOWN);
-      know (to_seg == SEG_UNKNOWN
-           || to_seg == SEG_ABSOLUTE
-           || to_seg == SEG_DATA
-           || to_seg == SEG_TEXT
-           || to_seg == SEG_BSS
-           || to_seg == SEG_BIG);
+      is_absolute = (to_seg == SEG_ABSOLUTE);
+#endif
       at = operandP->vop_mode & 1;
       length = (operandP->vop_short == 'b'
                ? 1 : (operandP->vop_short == 'w'
@@ -700,12 +704,12 @@ md_assemble (instruction_string)
        {
          if (to_seg == now_seg || is_undefined)
            {
-             /* If is_undefined, then it might BECOME now_seg. */
+             /* If is_undefined, then it might BECOME now_seg.  */
              if (nbytes)
                {
                  p = frag_more (nbytes);
                  fix_new (frag_now, p - frag_now->fr_literal, nbytes,
-                          this_add_symbol, 0, this_add_number, 1, NO_RELOC);
+                          this_add_symbol, this_add_number, 1, NO_RELOC);
                }
              else
                {               /* to_seg==now_seg || to_seg == SEG_UNKNOWN */
@@ -753,19 +757,25 @@ md_assemble (instruction_string)
                }
            }
          else
-           {                   /* to_seg != now_seg && to_seg != SEG_UNKNOWN */
+           {
+             /* to_seg != now_seg && to_seg != SEG_UNKNOWN */
              /*
-                                * --- SEG FLOAT MAY APPEAR HERE ----
-                                */
-             if (to_seg == SEG_ABSOLUTE)
+              * --- SEG FLOAT MAY APPEAR HERE ----
+              */
+             if (is_absolute)
                {
                  if (nbytes)
                    {
                      know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
                      p = frag_more (nbytes);
-                     /* Conventional relocation. */
-                     fix_new (frag_now, p - frag_now->fr_literal,
-                     nbytes, &abs_symbol, 0, this_add_number, 1, NO_RELOC);
+                     /* Conventional relocation.  */
+                     fix_new (frag_now, p - frag_now->fr_literal, nbytes,
+#ifdef BFD_ASSEMBLER
+                              section_symbol (absolute_section),
+#else
+                              &abs_symbol,
+#endif
+                              this_add_number, 1, NO_RELOC);
                    }
                  else
                    {
@@ -778,9 +788,9 @@ md_assemble (instruction_string)
                              *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG;
                              know (opcode_as_chars[1] == 0);
                              p = frag_more (5);
-                             p[0] = VAX_ABSOLUTE_MODE; /* @#... */
+                             p[0] = VAX_ABSOLUTE_MODE; /* @#...  */
                              md_number_to_chars (p + 1, this_add_number, 4);
-                             /* Now (eg) JMP @#foo or JSB @#foo. */
+                             /* Now (eg) JMP @#foo or JSB @#foo.  */
                            }
                          else
                            {
@@ -792,14 +802,14 @@ md_assemble (instruction_string)
                                  p[2] = VAX_BRB;
                                  p[3] = 6;
                                  p[4] = VAX_JMP;
-                                 p[5] = VAX_ABSOLUTE_MODE;     /* @#... */
+                                 p[5] = VAX_ABSOLUTE_MODE;     /* @#...  */
                                  md_number_to_chars (p + 6, this_add_number, 4);
                                  /*
-                                                                        * Now (eg)     ACBx    1f
-                                                                        *              BRB     2f
-                                                                        *      1:      JMP     @#foo
-                                                                        *      2:
-                                                                        */
+                                  * Now (eg)   ACBx    1f
+                                  *            BRB     2f
+                                  *    1:      JMP     @#foo
+                                  *    2:
+                                  */
                                }
                              else
                                {
@@ -809,14 +819,14 @@ md_assemble (instruction_string)
                                  p[1] = VAX_BRB;
                                  p[2] = 6;
                                  p[3] = VAX_JMP;
-                                 p[4] = VAX_PC_RELATIVE_MODE + 1;      /* @#... */
+                                  p[4] = VAX_ABSOLUTE_MODE;     /* @#...  */
                                  md_number_to_chars (p + 5, this_add_number, 4);
                                  /*
-                                                                        * Now (eg)     xOBxxx  1f
-                                                                        *              BRB     2f
-                                                                        *      1:      JMP     @#foo
-                                                                        *      2:
-                                                                        */
+                                  * Now (eg)   xOBxxx  1f
+                                  *            BRB     2f
+                                  *    1:      JMP     @#foo
+                                  *    2:
+                                  */
                                }
                            }
                        }
@@ -824,30 +834,36 @@ md_assemble (instruction_string)
                        {
                          /* b<cond> */
                          *opcode_low_byteP ^= 1;
-                         /* To reverse the condition in a VAX branch, complement the lowest order
-                                                          bit. */
+                         /* To reverse the condition in a VAX branch,
+                            complement the lowest order bit.  */
                          p = frag_more (7);
                          p[0] = 6;
                          p[1] = VAX_JMP;
-                         p[2] = VAX_ABSOLUTE_MODE;     /* @#... */
+                         p[2] = VAX_ABSOLUTE_MODE;     /* @#...  */
                          md_number_to_chars (p + 3, this_add_number, 4);
                          /*
-                                                        * Now (eg)     BLEQ    1f
-                                                        *              JMP     @#foo
-                                                        *      1:
-                                                        */
+                          * Now (eg)   BLEQ    1f
+                          *            JMP     @#foo
+                          *    1:
+                          */
                        }
                    }
                }
              else
-               {               /* to_seg != now_seg && to_seg != SEG_UNKNOWN && to_Seg != SEG_ABSOLUTE */
+               {
+                 /* to_seg != now_seg && !is_undefinfed && !is_absolute */
                  if (nbytes > 0)
                    {
-                     /* Pc-relative. Conventional relocation. */
+                     /* Pc-relative. Conventional relocation.  */
                      know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
                      p = frag_more (nbytes);
-                     fix_new (frag_now, p - frag_now->fr_literal,
-                     nbytes, &abs_symbol, 0, this_add_number, 1, NO_RELOC);
+                     fix_new (frag_now, p - frag_now->fr_literal, nbytes,
+#ifdef BFD_ASSEMBLER
+                              section_symbol (absolute_section),
+#else
+                              &abs_symbol,
+#endif
+                              this_add_number, 1, NO_RELOC);
                    }
                  else
                    {
@@ -863,9 +879,9 @@ md_assemble (instruction_string)
                              p[0] = VAX_PC_RELATIVE_MODE;
                              fix_new (frag_now,
                                       p + 1 - frag_now->fr_literal, 4,
-                                      this_add_symbol, 0,
+                                      this_add_symbol,
                                       this_add_number, 1, NO_RELOC);
-                             /* Now eg JMP foo or JSB foo. */
+                             /* Now eg JMP foo or JSB foo.  */
                            }
                          else
                            {
@@ -880,14 +896,14 @@ md_assemble (instruction_string)
                                  p[5] = VAX_PC_RELATIVE_MODE;
                                  fix_new (frag_now,
                                           p + 6 - frag_now->fr_literal, 4,
-                                          this_add_symbol, 0,
+                                          this_add_symbol,
                                           this_add_number, 1, NO_RELOC);
                                  /*
-                                                                        * Now (eg)     ACBx    1f
-                                                                        *              BRB     2f
-                                                                        *      1:      JMP     foo
-                                                                        *      2:
-                                                                        */
+                                  * Now (eg)   ACBx    1f
+                                  *            BRB     2f
+                                  *    1:      JMP     foo
+                                  *    2:
+                                  */
                                }
                              else
                                {
@@ -900,27 +916,27 @@ md_assemble (instruction_string)
                                  p[4] = VAX_PC_RELATIVE_MODE;
                                  fix_new (frag_now,
                                           p + 5 - frag_now->fr_literal,
-                                          4, this_add_symbol, 0,
+                                          4, this_add_symbol,
                                           this_add_number, 1, NO_RELOC);
                                  /*
-                                                                        * Now (eg)     xOBxxx  1f
-                                                                        *              BRB     2f
-                                                                        *      1:      JMP     foo
-                                                                        *      2:
-                                                                        */
+                                  * Now (eg)   xOBxxx  1f
+                                  *            BRB     2f
+                                  *    1:      JMP     foo
+                                  *    2:
+                                  */
                                }
                            }
                        }
                      else
                        {
                          know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP);
-                         *opcode_low_byteP ^= 1;       /* Reverse branch condition. */
+                         *opcode_low_byteP ^= 1;       /* Reverse branch condition.  */
                          p = frag_more (7);
                          p[0] = 6;
                          p[1] = VAX_JMP;
                          p[2] = VAX_PC_RELATIVE_MODE;
                          fix_new (frag_now, p + 3 - frag_now->fr_literal,
-                                  4, this_add_symbol, 0,
+                                  4, this_add_symbol,
                                   this_add_number, 1, NO_RELOC);
                        }
                    }
@@ -929,8 +945,8 @@ md_assemble (instruction_string)
        }
       else
        {
-         know (operandP->vop_access != 'b');   /* So it is ordinary operand. */
-         know (operandP->vop_access != ' ');   /* ' ' target-independent: elsewhere. */
+         know (operandP->vop_access != 'b');   /* So it is ordinary operand.  */
+         know (operandP->vop_access != ' ');   /* ' ' target-independent: elsewhere.  */
          know (operandP->vop_access == 'a'
                || operandP->vop_access == 'm'
                || operandP->vop_access == 'r'
@@ -938,11 +954,12 @@ md_assemble (instruction_string)
                || operandP->vop_access == 'w');
          if (operandP->vop_short == 's')
            {
-             if (to_seg == SEG_ABSOLUTE)
+             if (is_absolute)
                {
-                 if (this_add_number < 0 || this_add_number >= 64)
+                 if (this_add_number >= 64)
                    {
-                     as_warn ("Short literal overflow(%d.), immediate mode assumed.", this_add_number);
+                     as_warn (_("Short literal overflow(%ld.), immediate mode assumed."),
+                              (long) this_add_number);
                      operandP->vop_short = 'i';
                      operandP->vop_mode = 8;
                      operandP->vop_reg = 0xF;
@@ -950,7 +967,7 @@ md_assemble (instruction_string)
                }
              else
                {
-                 as_warn ("Forced short literal to immediate mode. now_seg=%s to_seg=%s",
+                 as_warn (_("Forced short literal to immediate mode. now_seg=%s to_seg=%s"),
                           segment_name (now_seg), segment_name (to_seg));
                  operandP->vop_short = 'i';
                  operandP->vop_mode = 8;
@@ -960,13 +977,14 @@ md_assemble (instruction_string)
          if (operandP->vop_reg >= 0 && (operandP->vop_mode < 8
                  || (operandP->vop_reg != 0xF && operandP->vop_mode < 10)))
            {
-             /* One byte operand. */
+             /* One byte operand.  */
              know (operandP->vop_mode > 3);
              FRAG_APPEND_1_CHAR (operandP->vop_mode << 4 | operandP->vop_reg);
-             /* All 1-bytes except S^# happen here. */
+             /* All 1-bytes except S^# happen here.  */
            }
          else
-           {                   /* {@}{q^}foo{(Rn)} or S^#foo */
+           {
+             /* {@}{q^}foo{(Rn)} or S^#foo */
              if (operandP->vop_reg == -1 && operandP->vop_short != 's')
                {
                  /* "{@}{q^}foo" */
@@ -975,26 +993,31 @@ md_assemble (instruction_string)
                      if (length == 0)
                        {
                          know (operandP->vop_short == ' ');
+                         length_code = STATE_BYTE;
+#ifdef OBJ_ELF
+                         if (S_IS_EXTERNAL (this_add_symbol)
+                             || S_IS_WEAK (this_add_symbol))
+                           length_code = STATE_UNDF;
+#endif
                          p = frag_var (rs_machine_dependent, 10, 2,
-                              ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE),
+                              ENCODE_RELAX (STATE_PC_RELATIVE, length_code),
                                        this_add_symbol, this_add_number,
                                        opcode_low_byteP);
                          know (operandP->vop_mode == 10 + at);
                          *p = at << 4;
-                         /* At is the only context we need to carry to */
-                         /* other side of relax() process. */
-                         /* Must be in the correct bit position of VAX */
-                         /* operand spec. byte. */
+                         /* At is the only context we need to carry
+                            to other side of relax() process.  Must
+                            be in the correct bit position of VAX
+                            operand spec. byte.  */
                        }
                      else
                        {
                          know (length);
                          know (operandP->vop_short != ' ');
                          p = frag_more (length + 1);
-                         /* JF is this array stuff really going to work? */
                          p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
                          fix_new (frag_now, p + 1 - frag_now->fr_literal,
-                                  length, this_add_symbol, 0,
+                                  length, this_add_symbol,
                                   this_add_number, 1, NO_RELOC);
                        }
                    }
@@ -1002,14 +1025,14 @@ md_assemble (instruction_string)
                    {           /* to_seg != now_seg */
                      if (this_add_symbol == NULL)
                        {
-                         know (to_seg == SEG_ABSOLUTE);
-                         /* Do @#foo: simpler relocation than foo-.(pc) anyway. */
+                         know (is_absolute);
+                         /* Do @#foo: simpler relocation than foo-.(pc) anyway.  */
                          p = frag_more (5);
-                         p[0] = VAX_ABSOLUTE_MODE;     /* @#... */
+                         p[0] = VAX_ABSOLUTE_MODE;     /* @#...  */
                          md_number_to_chars (p + 1, this_add_number, 4);
                          if (length && length != 4)
                            {
-                             as_warn ("Length specification ignored. Address mode 9F used");
+                             as_warn (_("Length specification ignored. Address mode 9F used"));
                            }
                        }
                      else
@@ -1017,17 +1040,29 @@ md_assemble (instruction_string)
                          /* {@}{q^}other_seg */
                          know ((length == 0 && operandP->vop_short == ' ')
                             || (length > 0 && operandP->vop_short != ' '));
-                         if (is_undefined)
+                         if (is_undefined
+#ifdef OBJ_ELF
+                             || S_IS_WEAK(this_add_symbol)
+                             || S_IS_EXTERNAL(this_add_symbol)
+#endif
+                             )
                            {
+                             switch (length)
+                               {
+                               default: length_code = STATE_UNDF; break;
+                               case 1: length_code = STATE_BYTE; break;
+                               case 2: length_code = STATE_WORD; break;
+                               case 4: length_code = STATE_LONG; break;
+                               }
                              /*
-                                                                * We have a SEG_UNKNOWN symbol. It might
-                                                                * turn out to be in the same segment as
-                                                                * the instruction, permitting relaxation.
-                                                                */
+                              * We have a SEG_UNKNOWN symbol. It might
+                              * turn out to be in the same segment as
+                              * the instruction, permitting relaxation.
+                              */
                              p = frag_var (rs_machine_dependent, 5, 2,
-                              ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),
+                              ENCODE_RELAX (STATE_PC_RELATIVE, length_code),
                                            this_add_symbol, this_add_number,
-                                           0);
+                                           opcode_low_byteP);
                              p[0] = at << 4;
                            }
                          else
@@ -1035,30 +1070,39 @@ md_assemble (instruction_string)
                              if (length == 0)
                                {
                                  know (operandP->vop_short == ' ');
-                                 length = 4;   /* Longest possible. */
+                                 length = 4;   /* Longest possible.  */
                                }
                              p = frag_more (length + 1);
                              p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
                              md_number_to_chars (p + 1, this_add_number, length);
                              fix_new (frag_now,
                                       p + 1 - frag_now->fr_literal,
-                                      length, this_add_symbol, 0,
+                                      length, this_add_symbol,
                                       this_add_number, 1, NO_RELOC);
                            }
                        }
                    }
                }
              else
-               {               /* {@}{q^}foo(Rn) or S^# or I^# or # */
+               {
+                 /* {@}{q^}foo(Rn) or S^# or I^# or # */
                  if (operandP->vop_mode < 0xA)
-                   {           /* # or S^# or I^# */
-                     /* know(   (length == 0 && operandP->vop_short == ' ')
-                                                  || (length >  0 && operandP->vop_short != ' ')); */
+                   {
+                     /* # or S^# or I^# */
+                     if (operandP->vop_access == 'v'
+                         || operandP->vop_access == 'a')
+                       {
+                         if (operandP->vop_access == 'v')
+                           as_warn (_("Invalid operand:  immediate value used as base address."));
+                         else
+                           as_warn (_("Invalid operand:  immediate value used as address."));
+                         /* gcc 2.6.3 is known to generate these in at least
+                            one case.  */
+                       }
                      if (length == 0
-                         && to_seg == SEG_ABSOLUTE
-                         && operandP->vop_mode == 8    /* No '@'. */
-                         && this_add_number < 64
-                         && this_add_number >= 0)
+                         && is_absolute && (expP->X_op != O_big)
+                         && operandP->vop_mode == 8    /* No '@'.  */
+                         && this_add_number < 64)
                        {
                          operandP->vop_short = 's';
                        }
@@ -1067,20 +1111,28 @@ md_assemble (instruction_string)
                          FRAG_APPEND_1_CHAR (this_add_number);
                        }
                      else
-                       {       /* I^#... */
+                       {
+                         /* I^#...  */
                          know (nbytes);
                          p = frag_more (nbytes + 1);
                          know (operandP->vop_reg == 0xF);
+#ifdef OBJ_ELF
+                         if (flag_want_pic && operandP->vop_mode == 8
+                               && this_add_symbol != NULL)
+                           {
+                             as_warn (_("Symbol used as immediate operand in PIC mode."));
+                           }
+#endif
                          p[0] = (operandP->vop_mode << 4) | 0xF;
-                         if (to_seg == SEG_ABSOLUTE)
+                         if ((is_absolute) && (expP->X_op != O_big))
                            {
                              /*
-                                                                * If nbytes > 4, then we are scrod. We don't know if the
-                                                                * high order bytes are to be 0xFF or 0x00.
-                                                                * BSD4.2 & RMS say use 0x00. OK --- but this
-                                                                * assembler needs ANOTHER rewrite to
-                                                                * cope properly with this bug.
-                                                                */
+                              * If nbytes > 4, then we are scrod. We
+                              * don't know if the high order bytes
+                              * are to be 0xFF or 0x00.  BSD4.2 & RMS
+                              * say use 0x00. OK --- but this
+                              * assembler needs ANOTHER rewrite to
+                              * cope properly with this bug.  */
                              md_number_to_chars (p + 1, this_add_number, min (4, nbytes));
                              if (nbytes > 4)
                                {
@@ -1089,12 +1141,13 @@ md_assemble (instruction_string)
                            }
                          else
                            {
-                             if (to_seg == SEG_BIG)
+                             if (expP->X_op == O_big)
                                {
                                  /*
-                                                                        * Problem here is to get the bytes in the right order.
-                                                                        * We stored our constant as LITTLENUMs, not bytes.
-                                                                        */
+                                  * Problem here is to get the bytes
+                                  * in the right order.  We stored
+                                  * our constant as LITTLENUMs, not
+                                  * bytes.  */
                                  LITTLENUM_TYPE *lP;
 
                                  lP = floatP->low;
@@ -1114,7 +1167,7 @@ md_assemble (instruction_string)
                              else
                                {
                                  fix_new (frag_now, p + 1 - frag_now->fr_literal,
-                                          nbytes, this_add_symbol, 0,
+                                          nbytes, this_add_symbol,
                                           this_add_number, 0, NO_RELOC);
                                }
                            }
@@ -1126,9 +1179,9 @@ md_assemble (instruction_string)
                            || (length > 0 && operandP->vop_short != ' '));
                      if (length == 0)
                        {
-                         if (to_seg == SEG_ABSOLUTE)
+                         if (is_absolute)
                            {
-                             register long test;
+                             long test;
 
                              test = this_add_number;
 
@@ -1148,14 +1201,14 @@ md_assemble (instruction_string)
                      know (operandP->vop_reg >= 0);
                      p[0] = operandP->vop_reg
                        | ((at | "?\12\14?\16"[length]) << 4);
-                     if (to_seg == SEG_ABSOLUTE)
+                     if (is_absolute)
                        {
                          md_number_to_chars (p + 1, this_add_number, length);
                        }
                      else
                        {
                          fix_new (frag_now, p + 1 - frag_now->fr_literal,
-                                  length, this_add_symbol, 0,
+                                  length, this_add_symbol,
                                   this_add_number, 0, NO_RELOC);
                        }
                    }
@@ -1165,127 +1218,155 @@ md_assemble (instruction_string)
     }                          /* for(operandP) */
 }                              /* vax_assemble() */
 \f
-/*
- *                     md_estimate_size_before_relax()
- *
- * Called just before relax().
- * Any symbol that is now undefined will not become defined.
- * Return the correct fr_subtype in the frag.
- * Return the initial "guess for fr_var" to caller.
- * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
- * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
- * Although it may not be explicit in the frag, pretend fr_var starts with a
- * 0 value.
- */
+/* md_estimate_size_before_relax(), called just before relax().
+   Any symbol that is now undefined will not become defined.
+   Return the correct fr_subtype in the frag and the growth beyond
+   fr_fix.  */
 int
 md_estimate_size_before_relax (fragP, segment)
-     register fragS *fragP;
-     register segT segment;
+     fragS *fragP;
+     segT segment;
 {
-  register char *p;
-  register int old_fr_fix;
-
-  old_fr_fix = fragP->fr_fix;
-  switch (fragP->fr_subtype)
+  if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF)
     {
-    case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF):
-      if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
-       {                       /* A relaxable case. */
-         fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
-       }
-      else
+      if (S_GET_SEGMENT (fragP->fr_symbol) != segment
+#ifdef OBJ_ELF
+         || S_IS_WEAK (fragP->fr_symbol)
+         || S_IS_EXTERNAL (fragP->fr_symbol)
+#endif
+         )
        {
-         p = fragP->fr_literal + old_fr_fix;
-         p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */
-         fragP->fr_fix += 1 + 4;
-         fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
-                  fragP->fr_offset, 1, NO_RELOC);
-         frag_wane (fragP);
-       }
-      break;
+         /* Non-relaxable cases.  */
+         int reloc_type = NO_RELOC;
+         char *p;
+         int old_fr_fix;
 
-    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):
-      if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
-       {
-         fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
-       }
-      else
-       {
+         old_fr_fix = fragP->fr_fix;
          p = fragP->fr_literal + old_fr_fix;
-         *fragP->fr_opcode ^= 1;       /* Reverse sense of branch. */
-         p[0] = 6;
-         p[1] = VAX_JMP;
-         p[2] = VAX_PC_RELATIVE_MODE;  /* ...(PC) */
-         fragP->fr_fix += 1 + 1 + 1 + 4;
-         fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol, 0,
-                  fragP->fr_offset, 1, NO_RELOC);
-         frag_wane (fragP);
-       }
-      break;
+#ifdef OBJ_ELF
+         /* If this is to an undefined symbol, then if it's an indirect
+            reference indicate that is can mutated into a GLOB_DAT or
+            JUMP_SLOT by the loader.  We restrict ourselves to no offset
+            due to a limitation in the NetBSD linker.  */
+
+         if (GOT_symbol == NULL)
+           GOT_symbol = symbol_find (GLOBAL_OFFSET_TABLE_NAME);
+         if (PLT_symbol == NULL)
+           PLT_symbol = symbol_find (PROCEDURE_LINKAGE_TABLE_NAME);
+         if ((GOT_symbol == NULL || fragP->fr_symbol != GOT_symbol)
+             && (PLT_symbol == NULL || fragP->fr_symbol != PLT_symbol)
+             && fragP->fr_symbol != NULL
+             && flag_want_pic
+             && (!S_IS_DEFINED (fragP->fr_symbol)
+                 || S_IS_WEAK (fragP->fr_symbol)
+                 || S_IS_EXTERNAL (fragP->fr_symbol)))
+           {
+             if (p[0] & 0x10)
+               {
+                 if (flag_want_pic)
+                   as_fatal ("PIC reference to %s is indirect.\n",
+                             S_GET_NAME (fragP->fr_symbol));
+               }
+             else
+               {
+                 if (((unsigned char *) fragP->fr_opcode)[0] == VAX_CALLS
+                     || ((unsigned char *) fragP->fr_opcode)[0] == VAX_CALLG
+                     || ((unsigned char *) fragP->fr_opcode)[0] == VAX_JSB
+                     || ((unsigned char *) fragP->fr_opcode)[0] == VAX_JMP
+                     || S_IS_FUNCTION (fragP->fr_symbol))
+                   reloc_type = BFD_RELOC_32_PLT_PCREL;
+                 else
+                   reloc_type = BFD_RELOC_32_GOT_PCREL;
+               }
+           }
+#endif
+         switch (RELAX_STATE (fragP->fr_subtype))
+           {
+           case STATE_PC_RELATIVE:
+             p[0] |= VAX_PC_RELATIVE_MODE;     /* Preserve @ bit.  */
+             fragP->fr_fix += 1 + 4;
+             fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol,
+                      fragP->fr_offset, 1, reloc_type);
+             break;
 
-    case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_UNDF):
-      if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
-       {
-         fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD);
-       }
-      else
-       {
-         p = fragP->fr_literal + old_fr_fix;
-         p[0] = 2;
-         p[1] = 0;
-         p[2] = VAX_BRB;
-         p[3] = 6;
-         p[4] = VAX_JMP;
-         p[5] = VAX_PC_RELATIVE_MODE;  /* ...(pc) */
-         fragP->fr_fix += 2 + 2 + 1 + 1 + 4;
-         fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol, 0,
-                  fragP->fr_offset, 1, NO_RELOC);
-         frag_wane (fragP);
-       }
-      break;
+           case STATE_CONDITIONAL_BRANCH:
+             *fragP->fr_opcode ^= 1;           /* Reverse sense of branch.  */
+             p[0] = 6;
+             p[1] = VAX_JMP;
+             p[2] = VAX_PC_RELATIVE_MODE;      /* ...(PC) */
+             fragP->fr_fix += 1 + 1 + 1 + 4;
+             fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol,
+                      fragP->fr_offset, 1, NO_RELOC);
+             break;
 
-    case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_UNDF):
-      if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
-       {
-         fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE);
-       }
-      else
-       {
-         p = fragP->fr_literal + old_fr_fix;
-         p[0] = 2;
-         p[1] = VAX_BRB;
-         p[2] = 6;
-         p[3] = VAX_JMP;
-         p[4] = VAX_PC_RELATIVE_MODE;  /* ...(pc) */
-         fragP->fr_fix += 1 + 2 + 1 + 1 + 4;
-         fix_new (fragP, old_fr_fix + 5, 4, fragP->fr_symbol, 0,
-                  fragP->fr_offset, 1, NO_RELOC);
+           case STATE_COMPLEX_BRANCH:
+             p[0] = 2;
+             p[1] = 0;
+             p[2] = VAX_BRB;
+             p[3] = 6;
+             p[4] = VAX_JMP;
+             p[5] = VAX_PC_RELATIVE_MODE;      /* ...(pc) */
+             fragP->fr_fix += 2 + 2 + 1 + 1 + 4;
+             fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol,
+                      fragP->fr_offset, 1, NO_RELOC);
+             break;
+
+           case STATE_COMPLEX_HOP:
+             p[0] = 2;
+             p[1] = VAX_BRB;
+             p[2] = 6;
+             p[3] = VAX_JMP;
+             p[4] = VAX_PC_RELATIVE_MODE;      /* ...(pc) */
+             fragP->fr_fix += 1 + 2 + 1 + 1 + 4;
+             fix_new (fragP, old_fr_fix + 5, 4, fragP->fr_symbol,
+                      fragP->fr_offset, 1, NO_RELOC);
+             break;
+
+           case STATE_ALWAYS_BRANCH:
+             *fragP->fr_opcode += VAX_WIDEN_LONG;
+             p[0] = VAX_PC_RELATIVE_MODE;      /* ...(PC) */
+             fragP->fr_fix += 1 + 4;
+             fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol,
+                      fragP->fr_offset, 1, NO_RELOC);
+             break;
+
+           default:
+             abort ();
+           }
          frag_wane (fragP);
+
+         /* Return the growth in the fixed part of the frag.  */
+         return fragP->fr_fix - old_fr_fix;
        }
-      break;
 
-    case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF):
-      if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+      /* Relaxable cases.  Set up the initial guess for the variable
+        part of the frag.  */
+      switch (RELAX_STATE (fragP->fr_subtype))
        {
+       case STATE_PC_RELATIVE:
+         fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
+         break;
+       case STATE_CONDITIONAL_BRANCH:
+         fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
+         break;
+       case STATE_COMPLEX_BRANCH:
+         fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD);
+         break;
+       case STATE_COMPLEX_HOP:
+         fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE);
+         break;
+       case STATE_ALWAYS_BRANCH:
          fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE);
+         break;
        }
-      else
-       {
-         p = fragP->fr_literal + old_fr_fix;
-         *fragP->fr_opcode += VAX_WIDEN_LONG;
-         p[0] = VAX_PC_RELATIVE_MODE;  /* ...(PC) */
-         fragP->fr_fix += 1 + 4;
-         fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
-                  fragP->fr_offset, 1, NO_RELOC);
-         frag_wane (fragP);
-       }
-      break;
-
-    default:
-      break;
     }
-  return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
-}                              /* md_estimate_size_before_relax() */
+
+  if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
+    abort ();
+
+  /* Return the size of the variable part of the frag.  */
+  return md_relax_table[fragP->fr_subtype].rlx_length;
+}
 \f
 /*
  *                     md_convert_frag();
@@ -1298,100 +1379,110 @@ md_estimate_size_before_relax (fragP, segment)
  * Out:        Any fixSs and constants are set up.
  *     Caller will turn frag into a ".space 0".
  */
+#ifdef BFD_ASSEMBLER
 void
-md_convert_frag (headers, fragP)
-     object_headers *headers;
-     register fragS *fragP;
+md_convert_frag (headers, seg, fragP)
+     bfd *headers ATTRIBUTE_UNUSED;
+     segT seg ATTRIBUTE_UNUSED;
+     fragS *fragP;
+#else
+void
+md_convert_frag (headers, seg, fragP)
+     object_headers *headers ATTRIBUTE_UNUSED;
+     segT seg ATTRIBUTE_UNUSED;
+     fragS *fragP;
+#endif
 {
-  char *addressP;              /* -> _var to change. */
-  char *opcodeP;               /* -> opcode char(s) to change. */
-  short int length_code;       /* 2=long 1=word 0=byte */
-  short int extension = 0;     /* Size of relaxed address. */
-  /* Added to fr_fix: incl. ALL var chars. */
+  char *addressP;              /* -> _var to change.  */
+  char *opcodeP;               /* -> opcode char(s) to change.  */
+  short int extension = 0;     /* Size of relaxed address.  */
+  /* Added to fr_fix: incl. ALL var chars.  */
   symbolS *symbolP;
   long where;
-  long address_of_var;
-  /* Where, in file space, is _var of *fragP? */
-  long target_address = 0;
-  /* Where, in file space, does addr point? */
 
   know (fragP->fr_type == rs_machine_dependent);
-  length_code = fragP->fr_subtype & 3; /* depends on ENCODE_RELAX() */
-  know (length_code >= 0 && length_code < 3);
   where = fragP->fr_fix;
   addressP = fragP->fr_literal + where;
   opcodeP = fragP->fr_opcode;
   symbolP = fragP->fr_symbol;
   know (symbolP);
-  target_address = S_GET_VALUE (symbolP) + fragP->fr_offset;
-  address_of_var = fragP->fr_address + where;
 
   switch (fragP->fr_subtype)
     {
 
     case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE):
-      know (*addressP == 0 || *addressP == 0x10);      /* '@' bit. */
+      know (*addressP == 0 || *addressP == 0x10);      /* '@' bit.  */
       addressP[0] |= 0xAF;     /* Byte displacement. */
-      addressP[1] = target_address - (address_of_var + 2);
+      fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 2;
       break;
 
     case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD):
-      know (*addressP == 0 || *addressP == 0x10);      /* '@' bit. */
+      know (*addressP == 0 || *addressP == 0x10);      /* '@' bit.  */
       addressP[0] |= 0xCF;     /* Word displacement. */
-      md_number_to_chars (addressP + 1, target_address - (address_of_var + 3), 2);
+      fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 3;
       break;
 
     case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG):
-      know (*addressP == 0 || *addressP == 0x10);      /* '@' bit. */
+      know (*addressP == 0 || *addressP == 0x10);      /* '@' bit.  */
       addressP[0] |= 0xEF;     /* Long word displacement. */
-      md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4);
+      fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 5;
       break;
 
     case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):
-      addressP[0] = target_address - (address_of_var + 1);
+      fix_new (fragP, fragP->fr_fix, 1, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 1;
       break;
 
     case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
-      opcodeP[0] ^= 1;         /* Reverse sense of test. */
+      opcodeP[0] ^= 1;         /* Reverse sense of test.  */
       addressP[0] = 3;
-      addressP[1] = VAX_BRB + VAX_WIDEN_WORD;
-      md_number_to_chars (addressP + 2, target_address - (address_of_var + 4), 2);
+      addressP[1] = VAX_BRW;
+      fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 4;
       break;
 
     case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG):
-      opcodeP[0] ^= 1;         /* Reverse sense of test. */
+      opcodeP[0] ^= 1;         /* Reverse sense of test.  */
       addressP[0] = 6;
       addressP[1] = VAX_JMP;
       addressP[2] = VAX_PC_RELATIVE_MODE;
-      md_number_to_chars (addressP + 3, target_address, 4);
+      fix_new (fragP, fragP->fr_fix + 3, 4, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 7;
       break;
 
     case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE):
-      addressP[0] = target_address - (address_of_var + 1);
+      fix_new (fragP, fragP->fr_fix, 1, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 1;
       break;
 
     case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD):
       opcodeP[0] += VAX_WIDEN_WORD;    /* brb -> brw, bsbb -> bsbw */
-      md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+      fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
+              1, NO_RELOC);
       extension = 2;
       break;
 
     case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG):
       opcodeP[0] += VAX_WIDEN_LONG;    /* brb -> jmp, bsbb -> jsb */
       addressP[0] = VAX_PC_RELATIVE_MODE;
-      md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4);
+      fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 5;
       break;
 
     case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD):
-      md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+      fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 2;
       break;
 
@@ -1402,12 +1493,14 @@ md_convert_frag (headers, fragP)
       addressP[3] = 6;
       addressP[4] = VAX_JMP;
       addressP[5] = VAX_PC_RELATIVE_MODE;
-      md_number_to_chars (addressP + 6, target_address, 4);
+      fix_new (fragP, fragP->fr_fix + 6, 4, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 10;
       break;
 
     case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE):
-      addressP[0] = target_address - (address_of_var + 1);
+      fix_new (fragP, fragP->fr_fix, 1, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 1;
       break;
 
@@ -1416,7 +1509,8 @@ md_convert_frag (headers, fragP)
       addressP[1] = VAX_BRB;
       addressP[2] = 3;
       addressP[3] = VAX_BRW;
-      md_number_to_chars (addressP + 4, target_address - (address_of_var + 6), 2);
+      fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 6;
       break;
 
@@ -1426,7 +1520,8 @@ md_convert_frag (headers, fragP)
       addressP[2] = 6;
       addressP[3] = VAX_JMP;
       addressP[4] = VAX_PC_RELATIVE_MODE;
-      md_number_to_chars (addressP + 5, target_address, 4);
+      fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
+              fragP->fr_offset, 1, NO_RELOC);
       extension = 9;
       break;
 
@@ -1442,7 +1537,7 @@ md_convert_frag (headers, fragP)
    On vax: first 4 bytes are normal unsigned long, next three bytes
    are symbolnum, least sig. byte first.  Last byte is broken up with
    the upper nibble as nuthin, bit 3 as extern, bits 2 & 1 as length, and
-   bit 0 as pcrel. */
+   bit 0 as pcrel.  */
 #ifdef comment
 void
 md_ri_to_chars (the_bytes, ri)
@@ -1461,19 +1556,20 @@ md_ri_to_chars (the_bytes, ri)
 
 #endif /* comment */
 
-void 
+#ifdef OBJ_AOUT
+#ifndef BFD_ASSEMBLER
+void
 tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
      char *where;
      fixS *fixP;
      relax_addressT segment_address_in_file;
 {
   /*
-        * In: length of relocation (or of address) in chars: 1, 2 or 4.
-        * Out: GNU LD relocation length code: 0, 1, or 2.
-        */
+   * In: length of relocation (or of address) in chars: 1, 2 or 4.
+   * Out: GNU LD relocation length code: 0, 1, or 2.
+   */
 
-  static unsigned char nbytes_r_length[] =
-  {42, 0, 1, 42, 2};
+  static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
   long r_symbolnum;
 
   know (fixP->fx_addsy != NULL);
@@ -1492,9 +1588,9 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
   where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08)
              | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
              | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));
-
-  return;
-}                              /* tc_aout_fix_to_chars() */
+}
+#endif /* !BFD_ASSEMBLER */
+#endif /* OBJ_AOUT */
 
 /*
  *       BUGS, GRIPES,  APOLOGIA, etc.
@@ -1503,10 +1599,9 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
  * That is, AFTER we hash it with hash_...(), we want most-used opcodes
  * to come out of the hash table faster.
  *
- * I am sorry to inflict
- * yet another VAX assembler on the world, but RMS says we must
- * do everything from scratch, to prevent pin-heads restricting
- * this software.
+ * I am sorry to inflict yet another VAX assembler on the world, but
+ * RMS says we must do everything from scratch, to prevent pin-heads
+ * restricting this software.
  */
 
 /*
@@ -1562,9 +1657,8 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
  *     source file, and changed the makefile.
  */
 
-static struct hash_control *op_hash = NULL;    /* handle of the OPCODE hash table */
-/* NULL means any use before vip_begin() */
-/* will crash */
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash;
 
 /*
  * In: 1 character, from "bdfghloqpw" being the data-type of an operand
@@ -1576,25 +1670,23 @@ static struct hash_control *op_hash = NULL;     /* handle of the OPCODE hash table *
 
 static const short int vax_operand_width_size[256] =
 {
-
-#define _ 0
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16,    /* ..b.d.fgh...l..o */
-  _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _,      /* .q.....w........ */
-  _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16,    /* ..b.d.fgh...l..o */
-  _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _,      /* .q.....w........ */
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _};
-#undef _
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16,     /* ..b.d.fgh...l..o  */
+  0, 8, 0, 0, 0, 0, 0, 2,  0, 0, 0, 0, 0, 0, 0, 0,     /* .q.....w........  */
+  0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16,     /* ..b.d.fgh...l..o  */
+  0, 8, 0, 0, 0, 0, 0, 2,  0, 0, 0, 0, 0, 0, 0, 0,     /* .q.....w........  */
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+};
 \f
 /*
  * This perversion encodes all the vax opcodes as a bunch of strings.
@@ -1692,20 +1784,18 @@ static const struct vot
   {"jbcs",     {"rlvbb?", 0x800000e3}},
   {"jbsc",     {"rlvbb?", 0x800000e4}},
   {"jbcc",     {"rlvbb?", 0x800000e5}},
-  {"jbssi",    {"rlvbb?", 0x800000e6}},
-  {"jbcci",    {"rlvbb?", 0x800000e7}},
-  {"jlbs",     {"rlb?", 0x800000e8}},  /* JF changed from rlvbb? */
-  {"jlbc",     {"rlb?", 0x800000e9}},  /* JF changed from rlvbb? */
+  {"jlbs",     {"rlb?", 0x800000e8}},
+  {"jlbc",     {"rlb?", 0x800000e9}},
 
   {"jaoblss",  {"rlmlb:", 0xC00000f2}},
   {"jaobleq",  {"rlmlb:", 0xC00000f3}},
-  {"jsobgeq",  {"mlb:", 0xC00000f4}},  /* JF was rlmlb: */
-  {"jsobgtr",  {"mlb:", 0xC00000f5}},  /* JF was rlmlb: */
+  {"jsobgeq",  {"mlb:", 0xC00000f4}},
+  {"jsobgtr",  {"mlb:", 0xC00000f5}},
 
-/* CASEx has no branch addresses in our conception of it. */
-/* You should use ".word ..." statements after the "case ...". */
+/* CASEx has no branch addresses in our conception of it.  */
+/* You should use ".word ..." statements after the "case ...".  */
 
-  {"", ""}                     /* empty is end sentinel */
+  {"", {"", 0}}                        /* empty is end sentinel */
 
 };                             /* synthetic_votstrs */
 \f
@@ -1714,59 +1804,34 @@ static const struct vot
  *
  * Call me once before you decode any lines.
  * I decode votstrs into a hash table at op_hash (which I create).
- * I return an error text: hopefully "".
+ * I return an error text or null.
  * If you want, I will include the 'synthetic' jXXX instructions in the
  * instruction table.
  * You must nominate metacharacters for eg DEC's "#", "@", "^".
  */
 
-char *
+static const char *
 vip_begin (synthetic_too, immediate, indirect, displen)
-     int synthetic_too;                /* 1 means include jXXX op-codes. */
-     char *immediate, *indirect, *displen;
+     int synthetic_too;                /* 1 means include jXXX op-codes.  */
+     const char *immediate, *indirect, *displen;
 {
   const struct vot *vP;                /* scan votstrs */
-  char *retval;                        /* error text */
+  const char *retval = 0;      /* error text */
+
+  op_hash = hash_new ();
+
+  for (vP = votstrs; *vP->vot_name && !retval; vP++)
+    retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+
+  if (synthetic_too)
+    for (vP = synthetic_votstrs; *vP->vot_name && !retval; vP++)
+      retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
 
-  if ((op_hash = hash_new ()))
-    {
-      retval = "";             /* OK so far */
-      for (vP = votstrs; *vP->vot_name && !*retval; vP++)
-       {
-         retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail);
-       }
-      if (synthetic_too)
-       {
-         for (vP = synthetic_votstrs; *vP->vot_name && !*retval; vP++)
-           {
-             retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail);
-           }
-       }
-    }
-  else
-    {
-      retval = "virtual memory exceeded";
-    }
 #ifndef CONST_TABLE
   vip_op_defaults (immediate, indirect, displen);
 #endif
 
-  return (retval);
-}
-
-
-/*
- *                  v i p _ e n d ( )
- *
- * Call me once after you have decoded all lines.
- * I do any cleaning-up needed.
- *
- * We don't have to do any cleanup ourselves: all of our operand
- * symbol table is static, and free()ing it is naughty.
- */
-static void 
-vip_end ()
-{
+  return retval;
 }
 
 /*
@@ -1790,37 +1855,38 @@ vip_end ()
  * No argument string should generate such an error string:
  * it means a bug in our code, not in the user's text.
  *
- * You MUST have called vip_begin() once and vip_end() never before using
- * this function.
+ * You MUST have called vip_begin() once before using this function.
  */
 
-char *                         /* "" or bug string */
+static void
 vip (vitP, instring)
-     struct vit *vitP;         /* We build an exploded instruction here. */
-     char *instring;           /* Text of a vax instruction: we modify. */
+     struct vit *vitP;         /* We build an exploded instruction here.  */
+     char *instring;           /* Text of a vax instruction: we modify.  */
 {
-  register struct vot_wot *vwP;        /* How to bit-encode this opcode. */
-  register char *p;            /* 1/skip whitespace.2/scan vot_how */
-  register char *q;            /*  */
-  register char *bug;          /* "" or program logic error */
-  register unsigned char count;        /* counts number of operands seen */
-  register struct vop *operandp;/* scan operands in struct vit */
-  register char *alloperr;     /* error over all operands */
-  register char c;             /* Remember char, (we clobber it */
-  /* with '\0' temporarily). */
-  register vax_opcodeT oc;     /* Op-code of this instruction. */
-
-  char *vip_op ();
-
-  bug = "";
+  /* How to bit-encode this opcode.  */
+  struct vot_wot *vwP;
+  /* 1/skip whitespace.2/scan vot_how */
+  char *p;
+  char *q;
+  /* counts number of operands seen */
+  unsigned char count;
+  /* scan operands in struct vit */
+  struct vop *operandp;
+  /* error over all operands */
+  const char *alloperr;
+  /* Remember char, (we clobber it with '\0' temporarily).  */
+  char c;
+  /* Op-code of this instruction.  */
+  vax_opcodeT oc;
+
   if (*instring == ' ')
-    ++instring;                        /* Skip leading whitespace. */
-  for (p = instring; *p && *p != ' '; p++);;   /* MUST end in end-of-string or exactly 1 space. */
-  /* Scanned up to end of operation-code. */
-  /* Operation-code is ended with whitespace. */
+    ++instring;                        /* Skip leading whitespace.  */
+  for (p = instring; *p && *p != ' '; p++);;   /* MUST end in end-of-string or exactly 1 space.  */
+  /* Scanned up to end of operation-code.  */
+  /* Operation-code is ended with whitespace.  */
   if (p - instring == 0)
     {
-      vitP->vit_error = "No operator";
+      vitP->vit_error = _("No operator");
       count = 0;
       memset (vitP->vit_opcode, '\0', sizeof (vitP->vit_opcode));
     }
@@ -1834,45 +1900,45 @@ vip (vitP, instring)
        * We trust instring points to an op-name, with no whitespace.
        */
       vwP = (struct vot_wot *) hash_find (op_hash, instring);
-      *p = c;                  /* Restore char after op-code. */
+      *p = c;                  /* Restore char after op-code.  */
       if (vwP == 0)
        {
-         vitP->vit_error = "Unknown operator";
+         vitP->vit_error = _("Unknown operator");
          count = 0;
          memset (vitP->vit_opcode, '\0', sizeof (vitP->vit_opcode));
        }
       else
        {
          /*
-          * We found a match! So lets pick up as many operands as the
+          * We found a match! So let's pick up as many operands as the
           * instruction wants, and even gripe if there are too many.
           * We expect comma to seperate each operand.
           * We let instring track the text, while p tracks a part of the
           * struct vot.
           */
+         const char *howp;
          /*
           * The lines below know about 2-byte opcodes starting FD,FE or FF.
           * They also understand synthetic opcodes. Note:
           * we return 32 bits of opcode, including bucky bits, BUT
           * an opcode length is either 8 or 16 bits for vit_opcode_nbytes.
           */
-         oc = vwP->vot_code;   /* The op-code. */
+         oc = vwP->vot_code;   /* The op-code.  */
          vitP->vit_opcode_nbytes = (oc & 0xFF) >= 0xFD ? 2 : 1;
          md_number_to_chars (vitP->vit_opcode, oc, 4);
          count = 0;            /* no operands seen yet */
          instring = p;         /* point just past operation code */
          alloperr = "";
-         for (p = vwP->vot_how, operandp = vitP->vit_operand;
-              !*alloperr && !*bug && *p;
-              operandp++, p += 2
-           )
+         for (howp = vwP->vot_how, operandp = vitP->vit_operand;
+              !(alloperr && *alloperr) && *howp;
+              operandp++, howp += 2)
            {
              /*
               * Here to parse one operand. Leave instring pointing just
               * past any one ',' that marks the end of this operand.
               */
-             if (!p[1])
-               bug = "p";      /* ODD(!!) number of bytes in vot_how?? */
+             if (!howp[1])
+               as_fatal (_("odd number of bytes in operand description"));
              else if (*instring)
                {
                  for (q = instring; (c = *q) && c != ','; q++)
@@ -1882,31 +1948,30 @@ vip (vitP, instring)
                   * character.
                   */
                  *q = 0;
-                 operandp->vop_width = p[1];
-                 operandp->vop_nbytes = vax_operand_width_size[p[1]];
-                 operandp->vop_access = p[0];
-                 bug = vip_op (instring, operandp);
-                 *q = c;       /* Restore input text. */
-                 if (*(operandp->vop_error))
-                   alloperr = "Bad operand";
+                 operandp->vop_width = howp[1];
+                 operandp->vop_nbytes = vax_operand_width_size[(unsigned) howp[1]];
+                 operandp->vop_access = howp[0];
+                 vip_op (instring, operandp);
+                 *q = c;       /* Restore input text.  */
+                 if (operandp->vop_error)
+                   alloperr = _("Bad operand");
                  instring = q + (c ? 1 : 0);   /* next operand (if any) */
                  count++;      /*  won another argument, may have an operr */
                }
              else
-               alloperr = "Not enough operands";
+               alloperr = _("Not enough operands");
            }
          if (!*alloperr)
            {
              if (*instring == ' ')
-               instring++;     /* Skip whitespace. */
+               instring++;     /* Skip whitespace.  */
              if (*instring)
-               alloperr = "Too many operands";
+               alloperr = _("Too many operands");
            }
          vitP->vit_error = alloperr;
        }
     }
   vitP->vit_operands = count;
-  return (bug);
 }
 \f
 #ifdef test
@@ -1920,17 +1985,14 @@ char answer[100];               /* human types a line of vax assembler here */
 char *mybug;                   /* "" or an internal logic diagnostic */
 int mycount;                   /* number of operands */
 struct vop *myvop;             /* scan operands from myvit */
-int mysynth;                   /* 1 means want synthetic opcodes. */
+int mysynth;                   /* 1 means want synthetic opcodes.  */
 char my_immediate[200];
 char my_indirect[200];
 char my_displen[200];
 
-char *vip ();
-
 main ()
 {
   char *p;
-  char *vip_begin ();
 
   printf ("0 means no synthetic instructions.   ");
   printf ("Value for vip_begin?  ");
@@ -1943,7 +2005,7 @@ main ()
   gets (my_indirect);
   printf ("enter displen symbols   eg enter ^   ");
   gets (my_displen);
-  if (*(p = vip_begin (mysynth, my_immediate, my_indirect, my_displen)))
+  if (p = vip_begin (mysynth, my_immediate, my_indirect, my_displen))
     {
       error ("vip_begin=%s", p);
     }
@@ -1957,11 +2019,7 @@ main ()
        {
          break;                /* out of for each input text loop */
        }
-      mybug = vip (&myvit, answer);
-      if (*mybug)
-       {
-         printf ("BUG:\"%s\"\n", mybug);
-       }
+      vip (&myvit, answer);
       if (*myvit.vit_error)
        {
          printf ("ERR:\"%s\"\n", myvit.vit_error);
@@ -1986,28 +2044,27 @@ main ()
              putchar (*p);
            }
          printf ("\"\n");
-         if (*myvop->vop_error)
+         if (myvop->vop_error)
            {
              printf ("  err:\"%s\"\n", myvop->vop_error);
            }
-         if (*myvop->vop_warn)
+         if (myvop->vop_warn)
            {
              printf ("  wrn:\"%s\"\n", myvop->vop_warn);
            }
        }
     }
   vip_end ();
-  exit ();
+  exit (EXIT_SUCCESS);
 }
 
 #endif /* #ifdef test */
 
 /* end of vax_ins_parse.c */
 
-/* JF this used to be a separate file also */
 /* vax_reg_parse.c - convert a VAX register name to a number */
 
-/* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU. */
+/* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU.  */
 
 /*
  *          v a x _ r e g _ p a r s e ( )
@@ -2041,28 +2098,48 @@ main ()
  *
  */
 
-#include <ctype.h>
+#include "safe-ctype.h"
 #define AP (12)
 #define FP (13)
 #define SP (14)
 #define PC (15)
 \f
 int                            /* return -1 or 0:15 */
-vax_reg_parse (c1, c2, c3)     /* 3 chars of register name */
-     char c1, c2, c3;          /* c3 == 0 if 2-character reg name */
+vax_reg_parse (c1, c2, c3, c4) /* 3 chars of register name */
+     char c1, c2, c3, c4;      /* c3 == 0 if 2-character reg name */
 {
-  register int retval;         /* return -1:15 */
+  int retval;          /* return -1:15 */
 
   retval = -1;
 
-  if (isupper (c1))
-    c1 = tolower (c1);
-  if (isupper (c2))
-    c2 = tolower (c2);
-  if (isdigit (c2) && c1 == 'r')
+#ifdef OBJ_ELF
+  if (c1 != '%')       /* register prefixes are mandatory for ELF */
+    return retval;
+  c1 = c2;
+  c2 = c3;
+  c3 = c4;
+#endif
+#ifdef OBJ_VMS
+  if (c4 != 0)         /* register prefixes are not allowed under VMS */
+    return retval;
+#endif
+#ifdef OBJ_AOUT
+  if (c1 == '%')       /* register prefixes are optional under a.out */
+    {
+      c1 = c2;
+      c2 = c3;
+      c3 = c4;
+    }
+  else if (c3 && c4)   /* can't be 4 characters long.  */
+    return retval;
+#endif
+
+  c1 = TOLOWER (c1);
+  c2 = TOLOWER (c2);
+  if (ISDIGIT (c2) && c1 == 'r')
     {
       retval = c2 - '0';
-      if (isdigit (c3))
+      if (ISDIGIT (c3))
        {
          retval = retval * 10 + c3 - '0';
          retval = (retval > 15) ? -1 : retval;
@@ -2193,11 +2270,6 @@ vax_reg_parse (c1, c2, c3)       /* 3 chars of register name */
  * if the other outputs are to be taken seriously.
  */
 
-
-/* vax registers we need to know */
-/* JF #define SP      (14) */
-/* JF for one big happy file #define PC      (15) */
-
 /*
  * Because this module is useful for both VMS and UN*X style assemblers
  * and because of the variety of UN*X assemblers we must recognise
@@ -2226,7 +2298,7 @@ vax_reg_parse (c1, c2, c3)        /* 3 chars of register name */
 #define S VIP_INDIRECT,
 #define D VIP_DISPLEN,
 static const char
-  vip_metacharacters[256] =
+vip_metacharacters[256] =
 {
   _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _      /* ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O*/
   _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _      /* ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
@@ -2253,43 +2325,27 @@ static const char
 #else
 static char vip_metacharacters[256];
 
-/* Macro is faster under GCC;  The constant table is faster yet, but only works with ASCII */
-#if 0
-static
-#ifdef __GNUC__
-  inline
-#endif
 static void
 vip_op_1 (bit, syms)
      int bit;
-     char *syms;
+     const char *syms;
 {
   unsigned char t;
 
-  while (t = *syms++)
+  while ((t = *syms++) != 0)
     vip_metacharacters[t] |= bit;
 }
 
-#else
-#define vip_op_1(bit,syms) {           \
-                                           unsigned char t;                    \
-                                               char *table=vip_metacharacters; \
-                                                   while(t= *syms++)                   \
-                                                       table[t]|=bit;                  \
-                                                   }
-#endif
-
-static void 
-vip_op_defaults (immediate, indirect, displen) /* can be called any time */
-     char *immediate;          /* Strings of characters for each job. */
-     char *indirect;
-     char *displen;            /* more arguments may appear in future! */
+/* Can be called any time.  More arguments may appear in future.  */
+static void
+vip_op_defaults (immediate, indirect, displen)
+     const char *immediate;
+     const char *indirect;
+     const char *displen;
 {
   vip_op_1 (VIP_IMMEDIATE, immediate);
   vip_op_1 (VIP_INDIRECT, indirect);
   vip_op_1 (VIP_DISPLEN, displen);
-
-  return;
 }
 
 #endif
@@ -2353,119 +2409,127 @@ vip_op_defaults (immediate, indirect, displen)        /* can be called any time */
  * Again, I dare not explain it: just trace ALL the code!
  */
 \f
-char *                         /* (code here) bug message, "" = OK */
-/* our code bug, NOT bad assembly language */
+static void
 vip_op (optext, vopP)
      /* user's input string e.g.: "@B^foo@bar(AP)[FP]:" */
      char *optext;
      /* Input fields: vop_access, vop_width.
        Output fields: _ndx, _reg, _mode, _short, _warn,
        _error _expr_begin, _expr_end, _nbytes.
-       vop_nbytes : number of bytes in a datum. */
+       vop_nbytes : number of bytes in a datum.  */
      struct vop *vopP;
 {
-  char *p;                     /* track operand text forward */
-  char *q;                     /* track operand text backward */
-  int at;                      /* 1 if leading '@' ('*') seen */
-  char len;                    /* one of " bilsw" */
-  int hash;                    /* 1 if leading '#' ('$') seen */
-  int sign = 0;                        /* -1, 0 or +1 */
-  int paren = 0;               /* 1 if () surround register */
-  int reg = 0;                 /* register number, -1:absent */
-  int ndx = 0;                 /* index register number -1:absent */
-  char *bug;                   /* report any logic error in here, ""==OK */
-  char *err;                   /* report illegal operand, ""==OK */
+  /* track operand text forward */
+  char *p;
+  /* track operand text backward */
+  char *q;
+  /* 1 if leading '@' ('*') seen */
+  int at;
+  /* one of " bilsw" */
+  char len;
+  /* 1 if leading '#' ('$') seen */
+  int hash;
+  /* -1, 0 or +1 */
+  int sign = 0;
+  /* 1 if () surround register */
+  int paren = 0;
+  /* register number, -1:absent */
+  int reg = 0;
+  /* index register number -1:absent */
+  int ndx = 0;
+  /* report illegal operand, ""==OK */
   /* " " is a FAKE error: means we won */
-  /* ANY err that begins with ' ' is a fake. */
+  /* ANY err that begins with ' ' is a fake.  */
   /* " " is converted to "" before return */
-  char *wrn;                   /* warn about weird modes pf address */
-  char *oldq = NULL;           /* preserve q in case we backup */
-  int mode = 0;                        /* build up 4-bit operand mode here */
+  const char *err;
+  /* warn about weird modes pf address */
+  const char *wrn;
+  /* preserve q in case we backup */
+  char *oldq = NULL;
+  /* build up 4-bit operand mode here */
   /* note: index mode is in ndx, this is */
   /* the major mode of operand address */
+  int mode = 0;
   /*
-        * Notice how we move wrong-arg-type bugs INSIDE this module: if we
-        * get the types wrong below, we lose at compile time rather than at
-        * lint or run time.
-        */
-  char access;                 /* vop_access. */
-  char width;                  /* vop_width. */
-
-  int vax_reg_parse ();                /* returns 0:15 or -1 if not a register */
+   * Notice how we move wrong-arg-type bugs INSIDE this module: if we
+   * get the types wrong below, we lose at compile time rather than at
+   * lint or run time.
+   */
+  char access_mode;            /* vop_access.  */
+  char width;                  /* vop_width.  */
 
-  access = vopP->vop_access;
+  access_mode = vopP->vop_access;
   width = vopP->vop_width;
-  bug =                                /* none of our code bugs (yet) */
-    err =                      /* no user text errors */
-    wrn = "";                  /* no warnings even */
+  /* None of our code bugs (yet), no user text errors, no warnings
+     even.  */
+  err = wrn = 0;
 
   p = optext;
 
-  if (*p == ' ')               /* Expect all whitespace reduced to ' '. */
+  if (*p == ' ')               /* Expect all whitespace reduced to ' '.  */
     p++;                       /* skip over whitespace */
 
-  if (at = INDIRECTP (*p))
+  if ((at = INDIRECTP (*p)) != 0)
     {                          /* 1 if *p=='@'(or '*' for Un*x) */
       p++;                     /* at is determined */
-      if (*p == ' ')           /* Expect all whitespace reduced to ' '. */
+      if (*p == ' ')           /* Expect all whitespace reduced to ' '.  */
        p++;                    /* skip over whitespace */
     }
 
   /*
-        * This code is subtle. It tries to detect all legal (letter)'^'
-        * but it doesn't waste time explicitly testing for premature '\0' because
-        * this case is rejected as a mismatch against either (letter) or '^'.
-        */
+   * This code is subtle. It tries to detect all legal (letter)'^'
+   * but it doesn't waste time explicitly testing for premature '\0' because
+   * this case is rejected as a mismatch against either (letter) or '^'.
+   */
   {
-    register char c;
+    char c;
 
     c = *p;
-    if (isupper (c))
-      c = tolower (c);
+    c = TOLOWER (c);
     if (DISPLENP (p[1]) && strchr ("bilws", len = c))
       p += 2;                  /* skip (letter) '^' */
     else                       /* no (letter) '^' seen */
       len = ' ';               /* len is determined */
   }
 
-  if (*p == ' ')               /* Expect all whitespace reduced to ' '. */
+  if (*p == ' ')               /* Expect all whitespace reduced to ' '.  */
     p++;                       /* skip over whitespace */
 
-  if (hash = IMMEDIATEP (*p))  /* 1 if *p=='#' ('$' for Un*x) */
+  if ((hash = IMMEDIATEP (*p)) != 0)   /* 1 if *p=='#' ('$' for Un*x) */
     p++;                       /* hash is determined */
 
   /*
-        * p points to what may be the beginning of an expression.
-        * We have peeled off the front all that is peelable.
-        * We know at, len, hash.
-        *
-        * Lets point q at the end of the text and parse that (backwards).
-        */
+   * p points to what may be the beginning of an expression.
+   * We have peeled off the front all that is peelable.
+   * We know at, len, hash.
+   *
+   * Lets point q at the end of the text and parse that (backwards).
+   */
 
   for (q = p; *q; q++)
     ;
   q--;                         /* now q points at last char of text */
 \f
-  if (*q == ' ' && q >= p)     /* Expect all whitespace reduced to ' '. */
+  if (*q == ' ' && q >= p)     /* Expect all whitespace reduced to ' '.  */
     q--;
   /* reverse over whitespace, but don't */
   /* run back over *p */
 
   /*
-        * As a matter of policy here, we look for [Rn], although both Rn and S^#
-        * forbid [Rn]. This is because it is easy, and because only a sick
-        * cyborg would have [...] trailing an expression in a VAX-like assembler.
-        * A meticulous parser would first check for Rn followed by '(' or '['
-        * and not parse a trailing ']' if it found another. We just ban expressions
-        * ending in ']'.
-        */
+   * As a matter of policy here, we look for [Rn], although both Rn and S^#
+   * forbid [Rn]. This is because it is easy, and because only a sick
+   * cyborg would have [...] trailing an expression in a VAX-like assembler.
+   * A meticulous parser would first check for Rn followed by '(' or '['
+   * and not parse a trailing ']' if it found another. We just ban expressions
+   * ending in ']'.
+   */
   if (*q == ']')
     {
       while (q >= p && *q != '[')
        q--;
       /* either q<p or we got matching '[' */
       if (q < p)
-       err = "no '[' to match ']'";
+       err = _("no '[' to match ']'");
       else
        {
          /*
@@ -2473,19 +2537,21 @@ vip_op (optext, vopP)
           * name error. So again we don't need to check for early '\0'.
           */
          if (q[3] == ']')
-           ndx = vax_reg_parse (q[1], q[2], 0);
+           ndx = vax_reg_parse (q[1], q[2], 0, 0);
          else if (q[4] == ']')
-           ndx = vax_reg_parse (q[1], q[2], q[3]);
+           ndx = vax_reg_parse (q[1], q[2], q[3], 0);
+         else if (q[5] == ']')
+           ndx = vax_reg_parse (q[1], q[2], q[3], q[4]);
          else
            ndx = -1;
          /*
-                        * Since we saw a ']' we will demand a register name in the [].
-                        * If luser hasn't given us one: be rude.
-                        */
+          * Since we saw a ']' we will demand a register name in the [].
+          * If luser hasn't given us one: be rude.
+          */
          if (ndx < 0)
-           err = "bad register in []";
+           err = _("bad register in []");
          else if (ndx == PC)
-           err = "[PC] index banned";
+           err = _("[PC] index banned");
          else
            q--;                /* point q just before "[...]" */
        }
@@ -2494,16 +2560,16 @@ vip_op (optext, vopP)
     ndx = -1;                  /* no ']', so no iNDeX register */
 
   /*
-        * If err = "..." then we lost: run away.
-        * Otherwise ndx == -1 if there was no "[...]".
-        * Otherwise, ndx is index register number, and q points before "[...]".
-        */
+   * If err = "..." then we lost: run away.
+   * Otherwise ndx == -1 if there was no "[...]".
+   * Otherwise, ndx is index register number, and q points before "[...]".
+   */
 \f
-  if (*q == ' ' && q >= p)     /* Expect all whitespace reduced to ' '. */
+  if (*q == ' ' && q >= p)     /* Expect all whitespace reduced to ' '.  */
     q--;
   /* reverse over whitespace, but don't */
   /* run back over *p */
-  if (!*err)
+  if (!err || !*err)
     {
       sign = 0;                        /* no ()+ or -() seen yet */
 
@@ -2520,7 +2586,7 @@ vip_op (optext, vopP)
            q--;
          /* either q<p or we got matching '(' */
          if (q < p)
-           err = "no '(' to match ')'";
+           err = _("no '(' to match ')'");
          else
            {
              /*
@@ -2528,9 +2594,11 @@ vip_op (optext, vopP)
               * name error. So again we don't need to check for early '\0'.
               */
              if (q[3] == ')')
-               reg = vax_reg_parse (q[1], q[2], 0);
+               reg = vax_reg_parse (q[1], q[2], 0, 0);
              else if (q[4] == ')')
-               reg = vax_reg_parse (q[1], q[2], q[3]);
+               reg = vax_reg_parse (q[1], q[2], q[3], 0);
+             else if (q[5] == ')')
+               reg = vax_reg_parse (q[1], q[2], q[3], q[4]);
              else
                reg = -1;
              /*
@@ -2575,7 +2643,7 @@ vip_op (optext, vopP)
        * We don't check len. We want a specific error message later if
        * user tries "x^...-(Rn)". This is a feature not a bug.
        */
-      if (!*err)
+      if (!err || !*err)
        {
          if (paren && sign < 1)/* !sign is adequate test */
            {
@@ -2596,12 +2664,15 @@ vip_op (optext, vopP)
           */
          if (!paren)
            {
-             if (*q == ' ' && q >= p)  /* Expect all whitespace reduced to ' '. */
+             if (*q == ' ' && q >= p)  /* Expect all whitespace reduced to ' '.  */
                q--;
              /* reverse over whitespace, but don't */
              /* run back over *p */
-             if (q > p && q < p + 3)   /* room for Rn or Rnn exactly? */
-               reg = vax_reg_parse (p[0], p[1], q < p + 2 ? 0 : p[2]);
+             /* room for Rn or Rnn (include prefix) exactly? */
+             if (q > p && q < p + 4)
+               reg = vax_reg_parse (p[0], p[1],
+                 q < p + 2 ? 0 : p[2],
+                 q < p + 3 ? 0 : p[3]);
              else
                reg = -1;       /* always comes here if no register at all */
              /*
@@ -2652,15 +2723,15 @@ vip_op (optext, vopP)
    *      err  " "              or error message, and other outputs trashed
    */
   /* branch operands have restricted forms */
-  if (!*err && access == 'b')
+  if ((!err || !*err) && access_mode == 'b')
     {
       if (at || hash || sign || paren || ndx >= 0 || reg >= 0 || len != ' ')
-       err = "invalid branch operand";
+       err = _("invalid branch operand");
       else
        err = " ";
     }
 \f
-  /* Since nobody seems to use it: comment this 'feature'(?) out for now. */
+  /* Since nobody seems to use it: comment this 'feature'(?) out for now.  */
 #ifdef NEVER
   /*
    * Case of stand-alone operand. e.g. ".long foo"
@@ -2681,52 +2752,31 @@ vip_op (optext, vopP)
    *      ndx  -1
    *      err  " "              or error message, and other outputs trashed
    */
-  if (!*err)
+  if ((!err || !*err) && access_mode == ' ')
     {
-      if (access == ' ')
-       {                       /* addresses have restricted forms */
-         if (at)
-           err = "address prohibits @";
+      if (at)
+       err = _("address prohibits @");
+      else if (hash)
+       err = _("address prohibits #");
+      else if (sign)
+       {
+         if (sign < 0)
+           err = _("address prohibits -()");
          else
-           {
-             if (hash)
-               err = "address prohibits #";
-             else
-               {
-                 if (sign)
-                   {
-                     if (sign < 0)
-                       err = "address prohibits -()";
-                     else
-                       err = "address prohibits ()+";
-                   }
-                 else
-                   {
-                     if (paren)
-                       err = "address prohibits ()";
-                     else
-                       {
-                         if (ndx >= 0)
-                           err = "address prohibits []";
-                         else
-                           {
-                             if (reg >= 0)
-                               err = "address prohibits register";
-                             else
-                               {
-                                 if (len != ' ')
-                                   err = "address prohibits displacement length specifier";
-                                 else
-                                   {
-                                     err = " ";        /* succeed */
-                                     mode = 0;
-                                   }
-                               }
-                           }
-                       }
-                   }
-               }
-           }
+           err = _("address prohibits ()+");
+       }
+      else if (paren)
+       err = _("address prohibits ()");
+      else if (ndx >= 0)
+       err = _("address prohibits []");
+      else if (reg >= 0)
+       err = _("address prohibits register");
+      else if (len != ' ')
+       err = _("address prohibits displacement length specifier");
+      else
+       {
+         err = " ";    /* succeed */
+         mode = 0;
        }
     }
 #endif /*#Ifdef NEVER*/
@@ -2749,10 +2799,10 @@ vip_op (optext, vopP)
    *      exp
    *      ndx      -1
    */
-  if (!*err && len == 's')
+  if ((!err || !*err) && len == 's')
     {
       if (!hash || paren || at || ndx >= 0)
-       err = "invalid operand of S^#";
+       err = _("invalid operand of S^#");
       else
        {
          if (reg >= 0)
@@ -2766,17 +2816,17 @@ vip_op (optext, vopP)
              reg = 0;
            }
          /*
-                        * We have all the expression we will ever get.
-                        */
+          * We have all the expression we will ever get.
+          */
          if (p > q)
-           err = "S^# needs expression";
-         else if (access == 'r')
+           err = _("S^# needs expression");
+         else if (access_mode == 'r')
            {
              err = " ";        /* WIN! */
              mode = 0;
            }
          else
-           err = "S^# may only read-access";
+           err = _("S^# may only read-access");
        }
     }
 \f
@@ -2798,18 +2848,18 @@ vip_op (optext, vopP)
    *      exp      ""                enforce empty expression
    *      ndx      optional          warn if same as reg
    */
-  if (!*err && sign < 0)
+  if ((!err || !*err) && sign < 0)
     {
       if (len != ' ' || hash || at || p <= q)
-       err = "invalid operand of -()";
+       err = _("invalid operand of -()");
       else
        {
          err = " ";            /* win */
          mode = 7;
          if (reg == PC)
-           wrn = "-(PC) unpredictable";
+           wrn = _("-(PC) unpredictable");
          else if (reg == ndx)
-           wrn = "[]index same as -()register: unpredictable";
+           wrn = _("[]index same as -()register: unpredictable");
        }
     }
 \f
@@ -2842,18 +2892,18 @@ vip_op (optext, vopP)
    *      exp      ""                enforce empty expression
    *      ndx      optional          warn if same as reg
    */
-  if (!*err && sign > 0)
+  if ((!err || !*err) && sign > 0)
     {
       if (len != ' ' || hash || p <= q)
-       err = "invalid operand of ()+";
+       err = _("invalid operand of ()+");
       else
        {
          err = " ";            /* win */
          mode = 8 + (at ? 1 : 0);
          if (reg == PC)
-           wrn = "(PC)+ unpredictable";
+           wrn = _("(PC)+ unpredictable");
          else if (reg == ndx)
-           wrn = "[]index same as ()+register: unpredictable";
+           wrn = _("[]index same as ()+register: unpredictable");
        }
     }
 \f
@@ -2875,12 +2925,12 @@ vip_op (optext, vopP)
    *      exp
    *      ndx      optional
    */
-  if (!*err && hash)
+  if ((!err || !*err) && hash)
     {
       if (len != 'i' && len != ' ')
-       err = "# conflicts length";
+       err = _("# conflicts length");
       else if (paren)
-       err = "# bars register";
+       err = _("# bars register");
       else
        {
          if (reg >= 0)
@@ -2896,13 +2946,13 @@ vip_op (optext, vopP)
          err = " ";            /* win */
 
          /* JF a bugfix, I think! */
-         if (at && access == 'a')
+         if (at && access_mode == 'a')
            vopP->vop_nbytes = 4;
 
          mode = (at ? 9 : 8);
          reg = PC;
-         if ((access == 'm' || access == 'w') && !at)
-           wrn = "writing or modifying # is unpredictable";
+         if ((access_mode == 'm' || access_mode == 'w') && !at)
+           wrn = _("writing or modifying # is unpredictable");
        }
     }
   /*
@@ -2929,19 +2979,19 @@ vip_op (optext, vopP)
    *      exp      ""                enforce empty expression
    *      ndx      optional          warn if same as reg
    */
-  if (!*err && !paren && reg >= 0)
+  if ((!err || !*err) && !paren && reg >= 0)
     {
       if (len != ' ')
-       err = "length not needed";
+       err = _("length not needed");
       else if (at)
        {
          err = " ";            /* win */
          mode = 6;             /* @Rn */
        }
       else if (ndx >= 0)
-       err = "can't []index a register, because it has no address";
-      else if (access == 'a')
-       err = "a register has no address";
+       err = _("can't []index a register, because it has no address");
+      else if (access_mode == 'a')
+       err = _("a register has no address");
       else
        {
          /*
@@ -2952,36 +3002,36 @@ vip_op (optext, vopP)
           * Compute highest byte affected, compare to PC0.
           */
          if ((vopP->vop_nbytes + reg * 4) > 60)
-           wrn = "PC part of operand unpredictable";
+           wrn = _("PC part of operand unpredictable");
          err = " ";            /* win */
          mode = 5;             /* Rn */
        }
     }
   /*
-        * If !*err,        sign  == 0
-        *                  hash  == 0
-        *                  paren == 1  OR reg==-1
-        */
+   * If !*err,        sign  == 0
+   *                  hash  == 0
+   *                  paren == 1  OR reg==-1
+   */
 \f
   /*
-        * Rest of cases fit into one bunch.
-        *
-        * in:  at       optional
-        *      len      ' ' or 'b' or 'w' or 'l'
-        *      hash     0             by program logic
-        *      p:q      expected          (empty is not an error)
-        *      sign     0                 by program logic
-        *      paren    optional
-        *      reg      optional
-        *      ndx      optional
-        *
-        * out: mode     10 + @ + len
-        *      reg      optional
-        *      len      ' ' or 'b' or 'w' or 'l'
-        *      exp                        maybe empty
-        *      ndx      optional          warn if same as reg
-        */
-  if (!*err)
+   * Rest of cases fit into one bunch.
+   *
+   * in:  at       optional
+   *      len      ' ' or 'b' or 'w' or 'l'
+   *      hash     0             by program logic
+   *      p:q      expected          (empty is not an error)
+   *      sign     0                 by program logic
+   *      paren    optional
+   *      reg      optional
+   *      ndx      optional
+   *
+   * out: mode     10 + @ + len
+   *      reg      optional
+   *      len      ' ' or 'b' or 'w' or 'l'
+   *      exp                        maybe empty
+   *      ndx      optional          warn if same as reg
+   */
+  if (!err || !*err)
     {
       err = " ";               /* win (always) */
       mode = 10 + (at ? 1 : 0);
@@ -3006,7 +3056,7 @@ vip_op (optext, vopP)
    */
 
   if (*err == ' ')
-    err = "";                  /* " " is no longer an error */
+    err = 0;                   /* " " is no longer an error */
 
   vopP->vop_mode = mode;
   vopP->vop_reg = reg;
@@ -3016,9 +3066,7 @@ vip_op (optext, vopP)
   vopP->vop_ndx = ndx;
   vopP->vop_error = err;
   vopP->vop_warn = wrn;
-  return (bug);
-
-}                              /* vip_op() */
+}
 \f
 /*
 
@@ -3036,7 +3084,7 @@ vip_op (optext, vopP)
 
   */
 \f
-#ifdef TEST                    /* #Define to use this testbed. */
+#ifdef TEST                    /* #Define to use this testbed.  */
 
 /*
  * Follows a test program for this function.
@@ -3066,8 +3114,6 @@ char my_displen[200];
 
 main ()
 {
-  char *vip_op ();             /* make cc happy */
-
   printf ("enter immediate symbols eg enter #   ");
   gets (my_immediate);
   printf ("enter indirect symbols  eg enter @   ");
@@ -3081,7 +3127,7 @@ main ()
       fflush (stdout);
       gets (answer);
       if (!answer[0])
-       exit (0);
+       exit (EXIT_SUCCESS);
       myaccess = answer[0];
       mywidth = answer[1];
       switch (mywidth)
@@ -3175,140 +3221,168 @@ const int md_reloc_size = 8;  /* Size of relocation record */
 void
 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
      char *ptr;
-     long from_addr, to_addr;
-     fragS *frag;
-     symbolS *to_symbol;
+     addressT from_addr;
+     addressT to_addr ATTRIBUTE_UNUSED;
+     fragS *frag ATTRIBUTE_UNUSED;
+     symbolS *to_symbol ATTRIBUTE_UNUSED;
 {
-  long offset;
-
-  offset = to_addr - (from_addr + 1);
-  *ptr++ = 0x31;
+  valueT offset;
+
+  /* This former calculation was off by two:
+      offset = to_addr - (from_addr + 1);
+     We need to account for the one byte instruction and also its
+     two byte operand.  */
+  offset = to_addr - (from_addr + 1 + 2);
+  *ptr++ = VAX_BRW;            /* branch with word (16 bit) offset */
   md_number_to_chars (ptr, offset, 2);
 }
 
 void
 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
      char *ptr;
-     long from_addr, to_addr;
+     addressT from_addr ATTRIBUTE_UNUSED;
+     addressT to_addr;
      fragS *frag;
      symbolS *to_symbol;
 {
-  long offset;
+  valueT offset;
 
   offset = to_addr - S_GET_VALUE (to_symbol);
-  *ptr++ = 0x17;
-  *ptr++ = 0x9F;
+  *ptr++ = VAX_JMP;            /* arbitrary jump */
+  *ptr++ = VAX_ABSOLUTE_MODE;
   md_number_to_chars (ptr, offset, 4);
-  fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (symbolS *) 0, (long) 0, 0, NO_RELOC);
+  fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (long) 0, 0, NO_RELOC);
 }
+\f
+#ifdef OBJ_VMS
+const char *md_shortopts = "d:STt:V+1h:Hv::";
+#elif defined(OBJ_ELC)
+const char *md_shortopts = "d:STt:VkK";
+#else
+const char *md_shortopts = "d:STt:V";
+#endif
+struct option md_longopts[] = {
+  {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
 
 int
-md_parse_option (argP, cntP, vecP)
-     char **argP;
-     int *cntP;
-     char ***vecP;
+md_parse_option (c, arg)
+     int c;
+     char *arg;
 {
-  char *temp_name;             /* name for -t or -d options */
-  char opt;
-
-  switch (**argP)
+  switch (c)
     {
-    case 'J':
-      /* as_warn ("I can do better than -J!"); */
-      break;
-
     case 'S':
-      as_warn ("SYMBOL TABLE not implemented");
-      break;                   /* SYMBOL TABLE not implemented */
+      as_warn (_("SYMBOL TABLE not implemented"));
+      break;
 
     case 'T':
-      as_warn ("TOKEN TRACE not implemented");
-      break;                   /* TOKEN TRACE not implemented */
+      as_warn (_("TOKEN TRACE not implemented"));
+      break;
 
     case 'd':
-    case 't':
-      opt = **argP;
-      if (**argP)
-       {                       /* Rest of argument is filename. */
-         temp_name = *argP;
-         while (**argP)
-           (*argP)++;
-       }
-      else if (*cntP)
-       {
-         while (**argP)
-           (*argP)++;
-         --(*cntP);
-         temp_name = *++(*vecP);
-         **vecP = NULL;        /* Remember this is not a file-name. */
-       }
-      else
-       {
-         as_warn ("I expected a filename after -%c.", opt);
-         temp_name = "{absent}";
-       }
+      as_warn (_("Displacement length %s ignored!"), arg);
+      break;
 
-      if (opt == 'd')
-       as_warn ("Displacement length %s ignored!", temp_name);
-      else
-       as_warn ("I don't need or use temp. file \"%s\".", temp_name);
+    case 't':
+      as_warn (_("I don't need or use temp. file \"%s\"."), arg);
       break;
 
     case 'V':
-      as_warn ("I don't use an interpass file! -V ignored");
+      as_warn (_("I don't use an interpass file! -V ignored"));
       break;
 
-#ifdef VMS
-    case '+':                  /* For g++ */
+#ifdef OBJ_VMS
+    case '+':                  /* For g++.  Hash any name > 31 chars long.  */
+      flag_hash_long_names = 1;
       break;
 
-    case 'h':                  /* No hashing of mixed-case names */
+    case '1':                  /* For backward compatibility */
+      flag_one = 1;
       break;
 
     case 'H':                  /* Show new symbol after hash truncation */
+      flag_show_after_trunc = 1;
+      break;
+
+    case 'h':                  /* No hashing of mixed-case names */
+      {
+       extern char vms_name_mapping;
+       vms_name_mapping = atoi (arg);
+       flag_no_hash_mixed_case = 1;
+      }
+      break;
+
+    case 'v':
+      {
+       extern char *compiler_version_string;
+       if (!arg || !*arg || access (arg, 0) == 0)
+         return 0;             /* have caller show the assembler version */
+       compiler_version_string = arg;
+      }
       break;
 #endif
 
+#ifdef OBJ_ELF
+    case 'K':
+    case 'k':
+      flag_want_pic = 1;
+      break;                   /* -pic, Position Independent Code */
+#endif
+
     default:
       return 0;
-
     }
+
   return 1;
 }
 
+void
+md_show_usage (stream)
+     FILE *stream;
+{
+  fprintf (stream, _("\
+VAX options:\n\
+-d LENGTH              ignored\n\
+-J                     ignored\n\
+-S                     ignored\n\
+-t FILE                        ignored\n\
+-T                     ignored\n\
+-V                     ignored\n"));
+#ifdef OBJ_VMS
+  fprintf (stream, _("\
+VMS options:\n\
+-+                     hash encode names longer than 31 characters\n\
+-1                     `const' handling compatible with gcc 1.x\n\
+-H                     show new symbol after hash truncation\n\
+-h NUM                 don't hash mixed-case names, and adjust case:\n\
+                       0 = upper, 2 = lower, 3 = preserve case\n\
+-v\"VERSION\"          code being assembled was produced by compiler \"VERSION\"\n"));
+#endif
+}
+\f
 /* We have no need to default values of symbols.  */
 
-/* ARGSUSED */
 symbolS *
 md_undefined_symbol (name)
-     char *name;
+     char *name ATTRIBUTE_UNUSED;
 {
   return 0;
 }
 
-/* Parse an operand that is machine-specific.
-   We just return without modifying the expression if we have nothing
-   to do.  */
-
-/* ARGSUSED */
-void
-md_operand (expressionP)
-     expressionS *expressionP;
-{
-}
-
 /* Round up a section size to the appropriate boundary.  */
-long
+valueT
 md_section_align (segment, size)
-     segT segment;
-     long size;
+     segT segment ATTRIBUTE_UNUSED;
+     valueT size;
 {
   return size;                 /* Byte alignment is fine */
 }
 
 /* Exactly what point is a PC-relative offset relative TO?
    On the vax, they're relative to the address of the offset, plus
-   its size. (??? Is this right?  FIXME-SOON) */
+   its size. */
 long
 md_pcrel_from (fixP)
      fixS *fixP;
@@ -3316,4 +3390,96 @@ md_pcrel_from (fixP)
   return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
 }
 
+#ifdef OBJ_AOUT
+#ifndef BFD_ASSEMBLER
+void
+tc_headers_hook(headers)
+     object_headers *headers;
+{
+#ifdef TE_NetBSD
+  N_SET_INFO(headers->header, OMAGIC, M_VAX4K_NETBSD, 0);
+  headers->header.a_info = htonl(headers->header.a_info);
+#endif
+}
+#endif /* !BFD_ASSEMBLER */
+#endif /* OBJ_AOUT */
+
+#ifdef BFD_ASSEMBLER
+arelent *
+tc_gen_reloc (section, fixp)
+     asection *section ATTRIBUTE_UNUSED;
+     fixS *fixp;
+{
+  arelent *reloc;
+  bfd_reloc_code_real_type code;
+
+  if (fixp->fx_tcbit)
+    abort();
+
+  if (fixp->fx_r_type != BFD_RELOC_NONE)
+    {
+      code = fixp->fx_r_type;
+
+      if (fixp->fx_pcrel)
+       {
+         switch (code)
+           {
+           case BFD_RELOC_8_PCREL:
+           case BFD_RELOC_16_PCREL:
+           case BFD_RELOC_32_PCREL:
+#ifdef OBJ_ELF
+           case BFD_RELOC_8_GOT_PCREL:
+           case BFD_RELOC_16_GOT_PCREL:
+           case BFD_RELOC_32_GOT_PCREL:
+           case BFD_RELOC_8_PLT_PCREL:
+           case BFD_RELOC_16_PLT_PCREL:
+           case BFD_RELOC_32_PLT_PCREL:
+#endif
+             break;
+           default:
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("Cannot make %s relocation PC relative"),
+                           bfd_get_reloc_code_name (code));
+           }
+       }
+    }
+  else
+    {
+#define F(SZ,PCREL)            (((SZ) << 1) + (PCREL))
+      switch (F (fixp->fx_size, fixp->fx_pcrel))
+       {
+#define MAP(SZ,PCREL,TYPE)     case F(SZ,PCREL): code = (TYPE); break
+         MAP (1, 0, BFD_RELOC_8);
+         MAP (2, 0, BFD_RELOC_16);
+         MAP (4, 0, BFD_RELOC_32);
+         MAP (1, 1, BFD_RELOC_8_PCREL);
+         MAP (2, 1, BFD_RELOC_16_PCREL);
+         MAP (4, 1, BFD_RELOC_32_PCREL);
+       default:
+         abort ();
+       }
+    }
+#undef F
+#undef MAP
+
+  reloc = (arelent *) xmalloc (sizeof (arelent));
+  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;
+#ifndef OBJ_ELF
+  if (fixp->fx_pcrel)
+    reloc->addend = fixp->fx_addnumber;
+  else
+    reloc->addend = 0;
+#else
+  reloc->addend = fixp->fx_offset;
+#endif
+
+  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+  assert (reloc->howto != 0);
+
+  return reloc;
+}
+#endif /* BFD_ASSEMBLER */
+
 /* end of tc-vax.c */
This page took 0.068979 seconds and 4 git commands to generate.