]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gas/config/tc-vax.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / gas / config / tc-vax.c
index b0ac3f745f3680328b80338ae1e6fb946189a2ff..36defe4765ca3c7db4f251e67cb7c9f0bb76fff8 100644 (file)
@@ -1,13 +1,11 @@
 /* tc-vax.c - vax-specific -
-   Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1987-2023 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -129,7 +127,7 @@ int flag_want_pic;          /* -k */
  bbsc          e4
  bbcc          e5
  Always, you complement 0th bit to reverse condition.
- Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement
+ Always, 1-byte opcode, longword-address, byte-address, 1-byte-displacement
 
  2c.   J<cond> where cond tests low-order memory bit
  length of byte,word,long.
@@ -190,7 +188,7 @@ int flag_want_pic;          /* -k */
 #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.]  */
+/* Don't 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.  */
@@ -238,7 +236,7 @@ const relax_typeS md_relax_table[] =
 #undef WB
 
 void float_cons (int);
-int flonum_gen2vax (char, FLONUM_TYPE *, LITTLENUM_TYPE *);
+int flonum_gen2vax (int, FLONUM_TYPE *, LITTLENUM_TYPE *);
 
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -280,15 +278,21 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
 {
   valueT value = * valueP;
 
-  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)
-    number_to_chars_littleendian (fixP->fx_where + fixP->fx_frag->fr_literal,
-                                 value, fixP->fx_size);
+  if (fixP->fx_subsy != (symbolS *) NULL)
+    as_bad_subtract (fixP);
 
-  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+  if (fixP->fx_addsy == NULL)
     fixP->fx_done = 1;
+
+  if (fixP->fx_done)
+    number_to_chars_littleendian (fixP->fx_where + fixP->fx_frag->fr_literal,
+                                 value, fixP->fx_size);
+  else
+    /* Initialise the part of an instruction frag covered by the
+       relocation.  (Many occurrences of frag_more followed by fix_new
+       lack any init of the frag.)  Since VAX uses RELA relocs the
+       value we write into this field doesn't really matter.  */
+    memset (fixP->fx_where + fixP->fx_frag->fr_literal, 0, fixP->fx_size);
 }
 
 /* Convert a number from VAX byte order (little endian)
@@ -377,7 +381,7 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
          int old_fr_fix;
 
          old_fr_fix = fragP->fr_fix;
-         p = fragP->fr_literal + old_fr_fix;
+         p = &fragP->fr_literal[0] + old_fr_fix;
 #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
@@ -396,23 +400,20 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
                  || 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));
-               }
+             /* Indirect references cannot go through the GOT or PLT,
+                let's hope they'll become local in the final link.  */
+             if ((ELF_ST_VISIBILITY (S_GET_OTHER (fragP->fr_symbol))
+                  != STV_DEFAULT)
+                 || (p[0] & 0x10))
+               reloc_type = BFD_RELOC_32_PCREL;
+             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
-               {
-                 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;
-               }
+               reloc_type = BFD_RELOC_32_GOT_PCREL;
            }
 #endif
          switch (RELAX_STATE (fragP->fr_subtype))
@@ -524,7 +525,7 @@ md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
 
   know (fragP->fr_type == rs_machine_dependent);
   where = fragP->fr_fix;
-  addressP = fragP->fr_literal + where;
+  addressP = &fragP->fr_literal[0] + where;
   opcodeP = fragP->fr_opcode;
   symbolP = fragP->fr_symbol;
   know (symbolP);
@@ -735,7 +736,7 @@ md_ri_to_chars (char *the_bytes, struct reloc_info_generic ri)
        source file, and changed the makefile.  */
 
 /* Handle of the OPCODE hash table.  */
-static struct hash_control *op_hash;
+static htab_t op_hash;
 
 /* In: 1 character, from "bdfghloqpw" being the data-type of an operand
        of a vax instruction.
@@ -782,11 +783,11 @@ static const short int vax_operand_width_size[256] =
    ban these opcodes. They are mnemonics for "elastic" instructions
    that are supposed to assemble into the fewest bytes needed to do a
    branch, or to do a conditional branch, or whatever.
-  
+
    The opcode is in the usual place [low-order n*8 bits]. This means
    that if you mask off the bucky bits, the usual rules apply about
    how long the opcode is.
-  
+
    All VAX branch displacements come at the end of the instruction.
    For simple branches (1-byte opcode + 1-byte displacement) the last
    operand is coded 'b?' where the "data type" '?' is a clue that we
@@ -794,14 +795,14 @@ static const short int vax_operand_width_size[256] =
    and branch around a jump. This is by far the most common case.
    That is why the VIT_OPCODE_SYNTHETIC bit is set: it says this is
    a 0-byte op-code followed by 2 or more bytes of operand address.
-  
+
    If the op-code has VIT_OPCODE_SPECIAL set, then we have a more unusual
    case.
-  
+
    For JBSB & JBR the treatment is the similar, except (1) we have a 'bw'
    option before (2) we can directly JSB/JMP because there is no condition.
    These operands have 'b-' as their access/data type.
-  
+
    That leaves a bunch of random opcodes: JACBx, JxOBxxx. In these
    cases, we do the same idea. JACBxxx are all marked with a 'b!'
    JAOBxxx & JSOBxxx are marked with a 'b:'.  */
@@ -852,6 +853,8 @@ static const struct vot
   {"jbcs",     {"rlvbb?", 0x800000e3}},
   {"jbsc",     {"rlvbb?", 0x800000e4}},
   {"jbcc",     {"rlvbb?", 0x800000e5}},
+  {"jbssi",    {"rlvbb?", 0x800000e6}},
+  {"jbcci",    {"rlvbb?", 0x800000e7}},
   {"jlbs",     {"rlb?", 0x800000e8}},
   {"jlbc",     {"rlb?", 0x800000e9}},
 
@@ -947,41 +950,40 @@ vip_op_defaults (const char *immediate, const char *indirect, const char *disple
    instruction table.
    You must nominate metacharacters for eg DEC's "#", "@", "^".  */
 
-static const char *
+static void
 vip_begin (int synthetic_too,          /* 1 means include jXXX op-codes.  */
           const char *immediate,
           const char *indirect,
           const char *displen)
 {
   const struct vot *vP;                /* scan votstrs */
-  const char *retval = 0;      /* error text */
 
-  op_hash = hash_new ();
+  op_hash = str_htab_create ();
 
-  for (vP = votstrs; *vP->vot_name && !retval; vP++)
-    retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+  for (vP = votstrs; *vP->vot_name; vP++)
+    if (str_hash_insert (op_hash, vP->vot_name, &vP->vot_detail, 0) != NULL)
+      as_fatal (_("duplicate %s"), vP->vot_name);
 
   if (synthetic_too)
-    for (vP = synthetic_votstrs; *vP->vot_name && !retval; vP++)
-      retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+    for (vP = synthetic_votstrs; *vP->vot_name; vP++)
+      if (str_hash_insert (op_hash, vP->vot_name, &vP->vot_detail, 0) != NULL)
+       as_fatal (_("duplicate %s"), vP->vot_name);
 
 #ifndef CONST_TABLE
   vip_op_defaults (immediate, indirect, displen);
 #endif
-
-  return retval;
 }
 
 /* Take 3 char.s, the last of which may be `\0` (non-existent)
    and return the VAX register number that they represent.
-  
+
    Return -1 if they don't form a register name. Good names return
    a number from 0:15 inclusive.
-  
+
    Case is not important in a name.
-  
+
    Register names understood are:
-  
+
        R0
        R1
        R2
@@ -1078,20 +1080,20 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
    For speed, expect a string of whitespace to be reduced to a single ' '.
    This is the case for GNU AS, and is easy for other DEC-compatible
    assemblers.
-  
+
    Knowledge about DEC VAX assembler operand notation lives here.
    This doesn't even know what a register name is, except it believes
    all register names are 2 or 3 characters, and lets vax_reg_parse() say
    what number each name represents.
    It does, however, know that PC, SP etc are special registers so it can
    detect addressing modes that are silly for those registers.
-  
+
    Where possible, it delivers 1 fatal or 1 warning message if the operand
    is suspect. Exactly what we test for is still evolving.
 
    ---
        Arg block.
-  
+
    There were a number of 'mismatched argument type' bugs to vip_op.
    The most general solution is to typedef each (of many) arguments.
    We used instead a typedef'd argument block. This is less modular
@@ -1099,7 +1101,7 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
    on most engines, and seems to keep programmers happy. It will have
    to be done properly if we ever want to use vip_op as a general-purpose
    module (it was designed to be).
-  
+
        G^
 
    Doesn't support DEC "G^" format operands. These always take 5 bytes
@@ -1110,14 +1112,14 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
    If there is some other use for "G^", feel free to code it in!
 
        speed
-  
+
    If I nested if()s more, I could avoid testing (*err) which would save
    time, space and page faults. I didn't nest all those if()s for clarity
    and because I think the mode testing can be re-arranged 1st to test the
-   commoner constructs 1st. Does anybody have statistics on this?  
-  
+   commoner constructs 1st. Does anybody have statistics on this?
+
        error messages
-  
+
    In future, we should be able to 'compose' error messages in a scratch area
    and give the user MUCH more informative error messages. Although this takes
    a little more code at run-time, it will make this module much more self-
@@ -1126,18 +1128,18 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
    the Un*x characters "$`*", that most users will expect from this AS.
 
    ----
-   
+
    The input is a string, ending with '\0'.
-  
+
    We also require a 'hint' of what kind of operand is expected: so
    we can remind caller not to write into literals for instance.
-  
+
    The output is a skeletal instruction.
-  
+
    The algorithm has two parts.
    1. extract the syntactic features (parse off all the @^#-()+[] mode crud);
    2. express the @^#-()+[] as some parameters suited to further analysis.
-  
+
    2nd step is where we detect the googles of possible invalid combinations
    a human (or compiler) might write. Note that if we do a half-way
    decent assembler, we don't know how long to make (eg) displacement
@@ -1154,19 +1156,19 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
     -  error text(s)            why we couldn't understand the operand
 
    ----
-    
+
    To decode output of this, test errtxt. If errtxt[0] == '\0', then
    we had no errors that prevented parsing. Also, if we ever report
    an internal bug, errtxt[0] is set non-zero. So one test tells you
    if the other outputs are to be taken seriously.
 
    ----
-   
+
    Dec defines the semantics of address modes (and values)
    by a two-letter code, explained here.
-  
+
      letter 1:   access type
-  
+
        a         address calculation - no data access, registers forbidden
        b         branch displacement
        m         read - let go of bus - write back    "modify"
@@ -1174,9 +1176,9 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
        v         bit field address: like 'a' but registers are OK
        w         write
        space    no operator (eg ".long foo") [our convention]
-  
+
      letter 2:   data type (i.e. width, alignment)
-  
+
        b         byte
        d         double precision floating point (D format)
        f         single precision floating point (F format)
@@ -1189,11 +1191,11 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
        ?        simple synthetic branch operand
        -        unconditional synthetic JSB/JSR operand
        !        complex synthetic branch operand
-  
+
    The '-?!' letter 2's are not for external consumption. They are used
    for various assemblers. Generally, all unknown widths are assumed 0.
    We don't limit your choice of width character.
-  
+
    DEC operands are hard work to parse. For example, '@' as the first
    character means indirect (deferred) mode but elsewhere it is a shift
    operator.
@@ -1202,9 +1204,9 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
    We try hard not to parse anything that MIGHT be part of the expression
    buried in that syntax. For example if we see @...(Rn) we don't check
    for '-' before the '(' because mode @-(Rn) does not exist.
-  
+
    After parsing we have:
-  
+
    at                     1 if leading '@' (or Un*x '*')
    len                    takes one value from " bilsw". eg B^ -> 'b'.
    hash                   1 if leading '#' (or Un*x '$')
@@ -1215,7 +1217,7 @@ vax_reg_parse (char c1, char c2, char c3, char c4)
    paren                  1 if () are around register
    reg                    major register number 0:15    -1 means absent
    ndx                    index register number 0:15    -1 means absent
-  
+
    Again, I dare not explain it: just trace ALL the code!
 
    Summary of vip_op outputs.
@@ -1272,10 +1274,8 @@ vip_op (char *optext, struct vop *vopP)
      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_mode = vopP->vop_access;
-  width = vopP->vop_width;
   /* None of our code bugs (yet), no user text errors, no warnings
      even.  */
   err = wrn = 0;
@@ -1315,7 +1315,7 @@ vip_op (char *optext, struct vop *vopP)
   /* 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++)
@@ -1490,7 +1490,7 @@ vip_op (char *optext, struct vop *vopP)
      We will deliver a 4-bit reg, and a 4-bit mode.  */
 
   /* Case of branch operand. Different. No L^B^W^I^S^ allowed for instance.
-    
+
      in:  at   ?
           len  ?
           hash ?
@@ -1499,7 +1499,7 @@ vip_op (char *optext, struct vop *vopP)
           paren        ?
           reg   ?
           ndx   ?
-    
+
      out: mode  0
           reg   -1
           len  ' '
@@ -1518,7 +1518,7 @@ vip_op (char *optext, struct vop *vopP)
   /* Since nobody seems to use it: comment this 'feature'(?) out for now.  */
 #ifdef NEVER
   /* Case of stand-alone operand. e.g. ".long foo"
-    
+
      in:  at   ?
           len  ?
           hash ?
@@ -1527,7 +1527,7 @@ vip_op (char *optext, struct vop *vopP)
           paren        ?
           reg   ?
           ndx   ?
-    
+
      out: mode  0
           reg   -1
           len  ' '
@@ -1564,7 +1564,7 @@ vip_op (char *optext, struct vop *vopP)
 #endif
 
   /* Case of S^#.
-    
+
      in:  at       0
           len      's'               definition
           hash     1              demand
@@ -1573,7 +1573,7 @@ vip_op (char *optext, struct vop *vopP)
           paren    0             by "()" scan logic because "S^" seen
           reg      -1                or nn by mistake
           ndx      -1
-    
+
      out: mode     0
           reg      -1
           len      's'
@@ -1605,9 +1605,9 @@ vip_op (char *optext, struct vop *vopP)
            err = _("S^# may only read-access");
        }
     }
-  
+
   /* Case of -(Rn), which is weird case.
-    
+
      in:  at       0
           len      '
           hash     0
@@ -1616,7 +1616,7 @@ vip_op (char *optext, struct vop *vopP)
           paren    1              by definition
           reg      present           by definition
           ndx      optional
-    
+
      out: mode     7
           reg      present
           len      ' '
@@ -1647,7 +1647,7 @@ vip_op (char *optext, struct vop *vopP)
     }
 
   /* Case of (Rn)+, which is slightly different.
-    
+
      in:  at
           len      ' '
           hash     0
@@ -1656,7 +1656,7 @@ vip_op (char *optext, struct vop *vopP)
           paren    1              by definition
           reg      present           by definition
           ndx      optional
-    
+
      out: mode     8+@
           reg      present
           len      ' '
@@ -1678,7 +1678,7 @@ vip_op (char *optext, struct vop *vopP)
     }
 
   /* Case of #, without S^.
-    
+
      in:  at
           len      ' ' or 'i'
           hash     1              by definition
@@ -1687,7 +1687,7 @@ vip_op (char *optext, struct vop *vopP)
           paren    0
           reg      absent
           ndx      optional
-    
+
      out: mode     8+@
           reg      PC
           len      ' ' or 'i'
@@ -1726,7 +1726,7 @@ vip_op (char *optext, struct vop *vopP)
 
   /* Case of Rn. We separate this one because it has a few special
      errors the remaining modes lack.
-    
+
      in:  at       optional
           len      ' '
           hash     0             by program logic
@@ -1735,7 +1735,7 @@ vip_op (char *optext, struct vop *vopP)
           paren    0             by definition
           reg      present           by definition
           ndx      optional
-    
+
      out: mode     5+@
           reg      present
           len      ' '               enforce no length
@@ -1772,7 +1772,7 @@ vip_op (char *optext, struct vop *vopP)
                       paren == 1  OR reg==-1  */
 
   /* Rest of cases fit into one bunch.
-    
+
      in:  at       optional
           len      ' ' or 'b' or 'w' or 'l'
           hash     0             by program logic
@@ -1781,7 +1781,7 @@ vip_op (char *optext, struct vop *vopP)
           paren    optional
           reg      optional
           ndx      optional
-    
+
      out: mode     10 + @ + len
           reg      optional
           len      ' ' or 'b' or 'w' or 'l'
@@ -1795,8 +1795,10 @@ vip_op (char *optext, struct vop *vopP)
        {
        case 'l':
          mode += 2;
+         /* Fall through.  */
        case 'w':
          mode += 2;
+         /* Fall through.  */
        case ' ':       /* Assumed B^ until our caller changes it.  */
        case 'b':
          break;
@@ -1831,15 +1833,15 @@ vip_op (char *optext, struct vop *vopP)
    knowledge of how you parse (or evaluate) your expressions.
    We do however strip off and decode addressing modes and operation
    mnemonic.
-  
+
    The exploded instruction is returned to a struct vit of your choice.
    #include "vax-inst.h" to know what a struct vit is.
-  
+
    This function's value is a string. If it is not "" then an internal
    logic error was found: read this code to assign meaning to the string.
    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 before using this function.  */
 
 static void
@@ -1864,7 +1866,7 @@ vip (struct vit *vitP,            /* We build an exploded instruction here.  */
 
   if (*instring == ' ')
     ++instring;
-  
+
   /* MUST end in end-of-string or exactly 1 space.  */
   for (p = instring; *p && *p != ' '; p++)
     ;
@@ -1884,7 +1886,7 @@ vip (struct vit *vitP,            /* We build an exploded instruction here.  */
       /* Here with instring pointing to what better be an op-name, and p
          pointing to character just past that.
          We trust instring points to an op-name, with no whitespace.  */
-      vwP = (struct vot_wot *) hash_find (op_hash, instring);
+      vwP = (struct vot_wot *) str_hash_find (op_hash, instring);
       /* Restore char after op-code.  */
       *p = c;
       if (vwP == 0)
@@ -1983,8 +1985,7 @@ main (void)
   printf ("enter displen symbols   eg enter ^   ");
   gets (my_displen);
 
-  if (p = vip_begin (mysynth, my_immediate, my_indirect, my_displen))
-    error ("vip_begin=%s", p);
+  vip_begin (mysynth, my_immediate, my_indirect, my_displen)
 
   printf ("An empty input line will quit you from the vax instruction parser\n");
   for (;;)
@@ -2035,8 +2036,6 @@ main (void)
    We declare arrays non-local in case some of our tiny-minded machines
    default to small stacks. Also, helps with some debuggers.  */
 
-#include <stdio.h>
-
 char answer[100];              /* Human types into here.  */
 char *p;                       /*  */
 char *myerr;
@@ -2112,7 +2111,7 @@ main (void)
 
        default:
          my_operand_length = 2;
-         printf ("I dn't understand access width %c\n", mywidth);
+         printf ("I don't understand access width %c\n", mywidth);
          break;
        }
       printf ("VAX assembler instruction operand: ");
@@ -2211,7 +2210,7 @@ struct option md_longopts[] =
 size_t md_longopts_size = sizeof (md_longopts);
 
 int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
 {
   switch (c)
     {
@@ -2343,7 +2342,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
   if (fixp->fx_tcbit)
     abort ();
 
-  if (fixp->fx_r_type != BFD_RELOC_NONE)
+  if (fixp->fx_r_type != NO_RELOC)
     {
       code = fixp->fx_r_type;
 
@@ -2389,8 +2388,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 #undef F
 #undef MAP
 
-  reloc = xmalloc (sizeof (arelent));
-  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+  reloc = XNEW (arelent);
+  reloc->sym_ptr_ptr = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
 #ifndef OBJ_ELF
@@ -2403,7 +2402,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 #endif
 
   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
-  assert (reloc->howto != 0);
+  gas_assert (reloc->howto != 0);
 
   return reloc;
 }
@@ -2716,6 +2715,7 @@ md_assemble (char *instruction_string)
   if (need_pass_2 || goofed)
     return;
 
+  dwarf2_emit_insn (0);
   /* 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);
@@ -3127,9 +3127,9 @@ md_assemble (char *instruction_string)
                          || operandP->vop_access == 'a')
                        {
                          if (operandP->vop_access == 'v')
-                           as_warn (_("Invalid operand:  immediate value used as base address."));
+                           as_warn (_("Invalid operand: immediate value used as base address."));
                          else
-                           as_warn (_("Invalid operand:  immediate value used as address."));
+                           as_warn (_("Invalid operand: immediate value used as address."));
                          /* gcc 2.6.3 is known to generate these in at least
                             one case.  */
                        }
@@ -3154,7 +3154,8 @@ md_assemble (char *instruction_string)
                          if (flag_want_pic && operandP->vop_mode == 8
                                && this_add_symbol != NULL)
                            {
-                             as_warn (_("Symbol used as immediate operand in PIC mode."));
+                             as_warn (_("Symbol %s used as immediate operand in PIC mode."),
+                                      S_GET_NAME (this_add_symbol));
                            }
 #endif
                          p[0] = (operandP->vop_mode << 4) | 0xF;
@@ -3170,7 +3171,8 @@ md_assemble (char *instruction_string)
                                                  min (sizeof (valueT),
                                                       (size_t) nbytes));
                              if ((size_t) nbytes > sizeof (valueT))
-                               memset (p + 5, '\0', nbytes - sizeof (valueT));
+                               memset (p + 1 + sizeof (valueT),
+                                       '\0', nbytes - sizeof (valueT));
                            }
                          else
                            {
@@ -3252,12 +3254,10 @@ md_assemble (char *instruction_string)
 void
 md_begin (void)
 {
-  const char *errtxt;
   FLONUM_TYPE *fP;
   int i;
 
-  if ((errtxt = vip_begin (1, "$", "*", "`")) != 0)
-    as_fatal (_("VIP_BEGIN error:%s"), errtxt);
+  vip_begin (1, "$", "*", "`");
 
   for (i = 0, fP = float_operand;
        fP < float_operand + VIT_MAX_OPERANDS;
@@ -3267,3 +3267,142 @@ md_begin (void)
       fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];
     }
 }
+
+bfd_reloc_code_real_type
+vax_cons (expressionS *exp, int size)
+{
+  char *save;
+  const char *vax_cons_special_reloc;
+
+  SKIP_WHITESPACE ();
+  vax_cons_special_reloc = NULL;
+  save = input_line_pointer;
+  if (input_line_pointer[0] == '%')
+    {
+      if (startswith (input_line_pointer + 1, "pcrel"))
+       {
+         input_line_pointer += 6;
+         vax_cons_special_reloc = "pcrel";
+       }
+      if (vax_cons_special_reloc)
+       {
+         int bad = 0;
+
+         switch (size)
+           {
+           case 1:
+             if (*input_line_pointer != '8')
+               bad = 1;
+             input_line_pointer--;
+             break;
+           case 2:
+             if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
+               bad = 1;
+             break;
+           case 4:
+             if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
+               bad = 1;
+             break;
+           default:
+             bad = 1;
+             break;
+           }
+
+         if (bad)
+           {
+             as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
+                     vax_cons_special_reloc, size * 8, size);
+           }
+         else
+           {
+             input_line_pointer += 2;
+             if (*input_line_pointer != '(')
+               {
+                 as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                         vax_cons_special_reloc, size * 8);
+                 bad = 1;
+               }
+           }
+
+         if (bad)
+           {
+             input_line_pointer = save;
+             vax_cons_special_reloc = NULL;
+           }
+         else
+           {
+             int c;
+             char *end = ++input_line_pointer;
+             int npar = 0;
+
+             while (! is_end_of_line[(c = *end)])
+               {
+                 if (c == '(')
+                   npar++;
+                 else if (c == ')')
+                   {
+                     if (!npar)
+                       break;
+                     npar--;
+                   }
+                 end++;
+               }
+
+             if (c != ')')
+               as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                       vax_cons_special_reloc, size * 8);
+             else
+               {
+                 *end = '\0';
+                 expression (exp);
+                 *end = c;
+                 if (input_line_pointer != end)
+                   {
+                     as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                             vax_cons_special_reloc, size * 8);
+                   }
+                 else
+                   {
+                     input_line_pointer++;
+                     SKIP_WHITESPACE ();
+                     c = *input_line_pointer;
+                     if (! is_end_of_line[c] && c != ',')
+                       as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
+                               vax_cons_special_reloc, size * 8);
+                   }
+               }
+           }
+       }
+    }
+  if (vax_cons_special_reloc == NULL)
+    expression (exp);
+  else
+    switch (size)
+      {
+      case 1: return BFD_RELOC_8_PCREL;
+      case 2: return BFD_RELOC_16_PCREL;
+      case 4: return BFD_RELOC_32_PCREL;
+      }
+  return NO_RELOC;
+}
+
+/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
+   reloc for a cons.  */
+
+void
+vax_cons_fix_new (fragS *frag, int where, unsigned int nbytes, expressionS *exp,
+                 bfd_reloc_code_real_type r)
+{
+  if (r == NO_RELOC)
+    r = (nbytes == 1 ? BFD_RELOC_8
+        : nbytes == 2 ? BFD_RELOC_16
+        : BFD_RELOC_32);
+
+  fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
+}
+
+const char *
+md_atof (int type, char * litP, int * sizeP)
+{
+  return vax_md_atof (type, litP, sizeP);
+}