Changes compared to previous version:

Match style
----------
Add some function comments
----------
Remove commented out peephole (it was 0 &&)
----------
Match required whitespace.
don't debug_rtx.
use gcc_unreachable.
----------
Undo changes to constraints.md
They're just undoing GCC preferred style.
----------
Address style comment:
    
A nit.  In that expander you have "gen_rtx_NE(VOIDmode ..."  There
should be a space between the NE and the open parenthesis.  That kind of
nit is repeated several times.
----------
Undo some netbsd changes. This reverts:

Add new predicate volatile_mem_operand and use it for jbbssi<mode>

Fixes PR port-vax/53039: GCC/VAX hits ICE building libstdc++

GCC wants to change the label and then doesn't recognise the
new insn, it believes it doesn't satisfy the memory_operand
predicate.

It appears the memory_operand predicate doesn't accept volatile
memory accesses during the RTL generation phase.

The predicate is from rs6000 code.

from krister

Jeff Law notes:

Again, you're almost certainly just papering over hte problem.  There's
no reason I'm aware of for a zero_extract insn to be restricted to
volatile memory operands.   All you're doing is making the pattern not
match very often which happens to avoid the bug.

If I had to hazard a guess it looks like those jbs* patterns don't
accept a reversed pc/label_ref.  There may be other problems, that's the
most glaring one I see.

As an example of it done right, look at "*branch" and "*branch_reversed".
----------



diff --git a/gcc/config/vax/.vax.md.swp b/gcc/config/vax/.vax.md.swp
new file mode 100644
index 0000000..b063e59
Binary files /dev/null and b/gcc/config/vax/.vax.md.swp differ
diff --git a/gcc/config/vax/builtins.md b/gcc/config/vax/builtins.md
index bf4d2ae..2261467 100644
--- a/gcc/config/vax/builtins.md
+++ b/gcc/config/vax/builtins.md
@@ -24,6 +24,12 @@
   ]
 )
 
+(define_expand "condjump"
+  [(set (pc)
+	(if_then_else (match_operand 0)
+		      (label_ref (match_operand 1))
+		      (pc)))])
+
 (define_expand "ffssi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
 	(ffs:SI (match_operand:SI 1 "general_operand" "")))]
@@ -31,17 +37,17 @@
   "
 {
   rtx label = gen_label_rtx ();
-  emit_insn (gen_ffssi2_internal (operands[0], operands[1]));
-  emit_jump_insn (gen_bne (label));
-  emit_insn (gen_negsi2 (operands[0], const1_rtx));
+  emit_insn (gen_ctzsi2 (operands[0], operands[1]));
+  emit_jump_insn (gen_condjump (gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx), label));
+  emit_move_insn (operands[0], constm1_rtx);
   emit_label (label);
   emit_insn (gen_addsi3 (operands[0], operands[0], const1_rtx));
   DONE;
 }")
 
-(define_insn "ffssi2_internal"
+(define_insn "ctzsi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
-	(ffs:SI (match_operand:SI 1 "general_operand" "nrQt")))
+	(ctz:SI (match_operand:SI 1 "general_operand" "nrQT")))
    (set (cc0) (match_dup 0))]
   ""
   "ffs $0,$32,%1,%0")
@@ -189,4 +195,3 @@
 	  (const_int 0))])]
   ""
   "jbcci %1,%0,%l2")
-
diff --git a/gcc/config/vax/constraints.md b/gcc/config/vax/constraints.md
index 8483bbf..d22f2c7 100644
--- a/gcc/config/vax/constraints.md
+++ b/gcc/config/vax/constraints.md
@@ -100,7 +100,7 @@
    "operand is a MEM that does not have a mode-dependent address."
    (and (match_code "mem")
 	(match_test "!mode_dependent_address_p (XEXP (op, 0),
-					        MEM_ADDR_SPACE (op))")))
+						MEM_ADDR_SPACE (op))")))
 
 (define_memory_constraint "B"
     ""
diff --git a/gcc/config/vax/elf.h b/gcc/config/vax/elf.h
index dd8d3d9..42b5c04 100644
--- a/gcc/config/vax/elf.h
+++ b/gcc/config/vax/elf.h
@@ -65,7 +65,6 @@ along with GCC; see the file COPYING3.  If not see
 			      gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),\
 			      16))
 
-
 /* The VAX wants no space between the case instruction and the jump table.  */
 #undef  ASM_OUTPUT_BEFORE_CASE_LABEL
 #define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE, PREFIX, NUM, TABLE)
@@ -104,5 +103,5 @@ along with GCC; see the file COPYING3.  If not see
     fputs (integer_asm_op (SIZE, FALSE), FILE);		\
     fprintf (FILE, "%%pcrel%d(", SIZE * 8);		\
     assemble_name (FILE, LABEL);			\
-    fputc (')', FILE);					\
+    fprintf (FILE, "%+d)", SIZE);			\
   } while (0)
diff --git a/gcc/config/vax/netbsd-elf.h b/gcc/config/vax/netbsd-elf.h
index e7cbe24..b5ba43e 100644
--- a/gcc/config/vax/netbsd-elf.h
+++ b/gcc/config/vax/netbsd-elf.h
@@ -43,25 +43,17 @@ along with GCC; see the file COPYING3.  If not see
 #define NETBSD_ENTRY_POINT "__start"
 
 #undef LINK_SPEC
-#if 0
-/* FIXME: We must link all executables statically until PIC support
-   is added to the compiler.  */
-#define LINK_SPEC \
-  "%{assert*} %{R*} %{rpath*} \
-   %{shared:%ethe -shared option is not currently supported for VAX ELF} \
-   %{!shared: \
-     -dc -dp \
-     %{!nostdlib: \
-       %{!r: \
-	 %{!e*:-e %(netbsd_entry_point)}}} \
-     %{!static:-static} \
-     %{static:-static}}"
-#else
 #define LINK_SPEC NETBSD_LINK_SPEC_ELF
-#endif
 
-#define EXTRA_SPECS				\
-  { "netbsd_entry_point", NETBSD_ENTRY_POINT },
+#undef EXTRA_SPECS
+#define EXTRA_SPECS NETBSD_SUBTARGET_EXTRA_SPECS
+#undef SUBTARGET_EXTRA_SPECS
+
+#undef INTPTR_TYPE
+#define INTPTR_TYPE "long int"
+
+#undef UINTPTR_TYPE
+#define UINTPTR_TYPE "long unsigned int"
 
 /* We use gas, not the UNIX assembler.  */
 #undef TARGET_DEFAULT
diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h
index a85cf36..247d4d5 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -16,8 +16,10 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
+#include <stdbool.h>
 
 extern bool legitimate_constant_address_p (rtx);
+extern bool legitimate_pic_operand_p (rtx);
 extern void vax_expand_prologue (void);
 
 #ifdef RTX_CODE
@@ -28,9 +30,11 @@ extern void print_operand_address (FILE *, rtx);
 extern void print_operand (FILE *, rtx, int);
 extern void vax_notice_update_cc (rtx, rtx);
 extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code);
+extern bool vax_decomposed_dimode_operand_p (rtx, rtx);
 extern const char * vax_output_int_move (rtx, rtx *, machine_mode);
 extern const char * vax_output_int_add (rtx_insn *, rtx *, machine_mode);
 extern const char * vax_output_int_subtract (rtx_insn *, rtx *, machine_mode);
+extern const char * vax_output_movmemsi (rtx_insn *, rtx *);
 #endif /* RTX_CODE */
 
 #ifdef REAL_VALUE_TYPE
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 1c220ff..cb8b2b5 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -63,7 +63,7 @@ static void vax_trampoline_init (rtx, tree, rtx);
 static poly_int64 vax_return_pops_args (tree, tree, poly_int64);
 static bool vax_mode_dependent_address_p (const_rtx, addr_space_t);
 static HOST_WIDE_INT vax_starting_frame_offset (void);
-
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
@@ -132,6 +132,8 @@ vax_option_override (void)
   if (TARGET_G_FLOAT)
     REAL_MODE_FORMAT (DFmode) = &vax_g_format;
 
+  flag_dwarf2_cfi_asm = 0;
+
 #ifdef SUBTARGET_OVERRIDE_OPTIONS
   SUBTARGET_OVERRIDE_OPTIONS;
 #endif
@@ -165,9 +167,13 @@ vax_expand_prologue (void)
   HOST_WIDE_INT size;
   rtx insn;
 
+  offset = 20;
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
-      mask |= 1 << regno;
+      {
+	mask |= 1 << regno;
+	offset += 4;
+      }
 
   insn = emit_insn (gen_procedure_entry_mask (GEN_INT (mask)));
   RTX_FRAME_RELATED_P (insn) = 1;
@@ -189,11 +195,23 @@ vax_expand_prologue (void)
 
      The rest of the prologue will adjust the SP for the local frame.  */
 
-  vax_add_reg_cfa_offset (insn, 4, arg_pointer_rtx);
-  vax_add_reg_cfa_offset (insn, 8, frame_pointer_rtx);
-  vax_add_reg_cfa_offset (insn, 12, pc_rtx);
+  add_reg_note (insn, REG_CFA_DEF_CFA,
+		plus_constant (Pmode, frame_pointer_rtx, offset));
+  insn = emit_insn (gen_blockage ());
+  RTX_FRAME_RELATED_P (insn) = 1;
+
+#ifdef notyet
+  /*
+   * We can't do this, the dwarf code asserts and we don't have yet a 
+   * way to get to the psw
+   */
+  vax_add_reg_cfa_offset (insn, 4, gen_rtx_REG (Pmode, PSW_REGNUM));
+#endif
+  vax_add_reg_cfa_offset (insn, 8, arg_pointer_rtx);
+  vax_add_reg_cfa_offset (insn, 12, frame_pointer_rtx);
+  vax_add_reg_cfa_offset (insn, 16, pc_rtx);
 
-  offset = 16;
+  offset = 20;
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     if (mask & (1 << regno))
       {
@@ -201,12 +219,6 @@ vax_expand_prologue (void)
 	offset += 4;
       }
 
-  /* Because add_reg_note pushes the notes, adding this last means that
-     it will be processed first.  This is required to allow the other
-     notes be interpreted properly.  */
-  add_reg_note (insn, REG_CFA_DEF_CFA,
-		plus_constant (Pmode, frame_pointer_rtx, offset));
-
   /* Allocate the local stack frame.  */
   size = get_frame_size ();
   size -= vax_starting_frame_offset ();
@@ -357,7 +369,9 @@ print_operand_address (FILE * file, rtx addr)
 	  addr = XEXP (addr, 1);
 	}
       else
-	gcc_unreachable ();
+	{
+	   gcc_unreachable ();
+	}
 
       if (REG_P (addr))
 	{
@@ -368,9 +382,8 @@ print_operand_address (FILE * file, rtx addr)
 	}
       else if (GET_CODE (addr) == MULT)
 	ireg = addr;
-      else
+      else if (GET_CODE (addr) == PLUS)
 	{
-	  gcc_assert (GET_CODE (addr) == PLUS);
 	  if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
 	      || MEM_P (XEXP (addr, 0)))
 	    {
@@ -395,12 +408,14 @@ print_operand_address (FILE * file, rtx addr)
 	      else
 		reg1 = XEXP (addr, 0);
 	    }
-	  else
+	  else if (GET_CODE (XEXP (addr, 0)) == MULT && !ireg)
 	    {
-	      gcc_assert (GET_CODE (XEXP (addr, 0)) == MULT);
-	      gcc_assert (!ireg);
 	      ireg = XEXP (addr, 0);
 	    }
+	  else
+	    {
+	      gcc_unreachable ();
+	    }
 
 	  if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
 	      || MEM_P (XEXP (addr, 1)))
@@ -426,12 +441,18 @@ print_operand_address (FILE * file, rtx addr)
 	      else
 		reg1 = XEXP (addr, 1);
 	    }
-	  else
+	  else if (GET_CODE (XEXP (addr, 1)) == MULT && !ireg)
 	    {
-	      gcc_assert (GET_CODE (XEXP (addr, 1)) == MULT);
-	      gcc_assert (!ireg);
 	      ireg = XEXP (addr, 1);
 	    }
+	  else
+	    {
+	      gcc_unreachable ();
+	    }
+	}
+      else
+	{
+	  gcc_unreachable ();
 	}
 
       /* If REG1 is nonzero, figure out if it is a base or index register.  */
@@ -443,7 +464,10 @@ print_operand_address (FILE * file, rtx addr)
 		  && (MEM_P (offset)
 		      || (flag_pic && symbolic_operand (offset, SImode)))))
 	    {
-	      gcc_assert (!ireg);
+	      if (ireg)
+		{
+		  gcc_unreachable ();
+		}
 	      ireg = reg1;
 	    }
 	  else
@@ -456,7 +480,6 @@ print_operand_address (FILE * file, rtx addr)
 	    {
 	      if (breg && ireg)
 		{
-		  debug_rtx (orig);
 		  output_operand_lossage ("symbol used with both base and indexed registers");
 		}
 
@@ -465,7 +488,6 @@ print_operand_address (FILE * file, rtx addr)
 		  && GET_CODE (XEXP (XEXP (offset, 0), 0)) == SYMBOL_REF
 		  && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (offset, 0), 0)))
 		{
-		  debug_rtx (orig);
 		  output_operand_lossage ("symbol with offset used in PIC mode");
 		}
 #endif
@@ -489,12 +511,16 @@ print_operand_address (FILE * file, rtx addr)
 	{
 	  if (GET_CODE (ireg) == MULT)
 	    ireg = XEXP (ireg, 0);
-	  gcc_assert (REG_P (ireg));
+	  if (! REG_P (ireg))
+	    {
+	      output_operand_lossage ("non-register index expression");
+	    }
 	  fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
 	}
       break;
 
     default:
+      gcc_assert (! REG_P(addr));
       output_addr_const (file, addr);
     }
 }
@@ -549,11 +575,14 @@ print_operand (FILE *file, rtx x, int code)
 		       sizeof (dstr), 0, 1);
       fprintf (file, "$0%c%s", ASM_DOUBLE_CHAR, dstr);
     }
+  else if (GET_CODE (x) == SUBREG)
+    {
+      output_operand_lossage ("SUBREG operand");
+    }
   else
     {
       if (flag_pic > 1 && symbolic_operand (x, SImode))
 	{
-	  debug_rtx (x);
 	  output_operand_lossage ("symbol used as immediate operand");
 	}
       putc ('$', file);
@@ -1091,6 +1120,7 @@ vax_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
 	    case IOR:
 	    case XOR:
 	    case NOT:
+	    case CTZ:
 	    case MEM:
 	    case REG:
 	      cc_status.flags = CC_NO_OVERFLOW;
@@ -1266,7 +1296,7 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
 
       if (operands[1] == const0_rtx)
 	{
-	  if (push_operand (operands[1], SImode))
+	  if (push_operand (operands[0], SImode))
 	    return "pushl %1";
 	  return "clrl %0";
 	}
@@ -1358,9 +1388,6 @@ vax_output_int_add (rtx_insn *insn, rtx *operands, machine_mode mode)
 	int carry = 1;
 	bool sub;
 
-	if (TARGET_QMATH && 0)
-	  debug_rtx (insn);
-
 	split_quadword_operands (insn, PLUS, operands, low, 3);
 
 	if (TARGET_QMATH)
@@ -1509,7 +1536,7 @@ vax_output_int_add (rtx_insn *insn, rtx *operands, machine_mode mode)
       if (flag_pic
 	  && (symbolic_operand (operands[1], SImode)
 	      || symbolic_operand (operands[1], SImode)))
-	debug_rtx (insn);
+	gcc_unreachable();
 
       return "addl3 %1,%2,%0";
 
@@ -1567,9 +1594,6 @@ vax_output_int_subtract (rtx_insn *insn, rtx *operands, machine_mode mode)
 	const char *pattern;
 	int carry = 1;
 
-	if (TARGET_QMATH && 0)
-	  debug_rtx (insn);
-
 	split_quadword_operands (insn, MINUS, operands, low, 3);
 
 	if (TARGET_QMATH)
@@ -1631,6 +1655,112 @@ vax_output_int_subtract (rtx_insn *insn, rtx *operands, machine_mode mode)
   }
 }
 
+static rtx
+mkrtx(enum rtx_code code, enum machine_mode mode, rtx base, HOST_WIDE_INT off)
+{
+  rtx tmp;
+
+  if (GET_CODE (base) == CONST)
+    base = XEXP (base, 0);
+
+  if (GET_CODE (base) == PLUS)
+    {
+      rtx a = XEXP (base, 0);
+      rtx b = XEXP (base, 1);
+      if (GET_CODE (b) == CONST)
+	b = XEXP (b, 0);
+      if (CONST_INT_P (b))
+	{
+	  off += INTVAL (b);
+	  base = a;
+	}
+      else if (REG_P (a) && GET_CODE (b) == SYMBOL_REF)
+	{
+	  if (off != 0)
+	    {
+	      base = gen_rtx_PLUS (Pmode, a, plus_constant(Pmode, b, off));
+	      off = 0;
+	    }
+	}
+      else if (REG_P (a) && GET_CODE (b) == PLUS)
+	{
+	  off += INTVAL (XEXP (b, 1));
+	  base = gen_rtx_PLUS (Pmode, a, plus_constant(Pmode, XEXP (b, 0), off));
+	  off = 0;
+	}
+      else
+	{
+	  gcc_unreachable ();
+	}
+    }
+  if (code == POST_INC)
+    tmp = gen_rtx_POST_INC (SImode, base);
+  else if (off == 0 || (REG_P (base) && code == REG))
+    tmp = base;
+  else
+    tmp = plus_constant (Pmode, base, off);
+  return gen_rtx_MEM (mode, tmp);
+}
+
+/* For small moves (<=48 bytes), expand to the proper series of
+   mov[qlwb] instructions. */
+const char *
+vax_output_movmemsi (rtx_insn *insn, rtx *operands)
+{
+  HOST_WIDE_INT n = INTVAL (operands[2]);
+  HOST_WIDE_INT off;
+  rtx src, dest;
+  const char *pat = NULL;
+  const enum rtx_code *src_codes;
+  const enum rtx_code *dest_codes;
+  int code_idx = 0;
+  int mode_idx;
+
+  static const enum machine_mode xmodes[4] =
+    {
+      QImode, HImode, SImode, DImode
+    };
+  static const char * const pats[4] = 
+    {
+      "movb %1,%0", "movw %1,%0", "movl %1,%0", "movq %1,%0", 
+    };
+  static const enum rtx_code codes[2][3] =
+    {
+      { PLUS, PLUS, PLUS },
+      { POST_INC, POST_INC, REG },
+    };
+
+  src = XEXP (operands[1], 0);
+
+  src_codes =
+    codes[REG_P (src) && find_regno_note (insn, REG_DEAD, REGNO(src))];
+
+  dest = XEXP (operands[0], 0);
+
+  dest_codes =
+    codes[REG_P (dest) && find_regno_note (insn, REG_DEAD, REGNO(dest))];
+
+  for (off = 0, code_idx = 0, mode_idx = 3; mode_idx >= 0; mode_idx--)
+    {
+      const enum machine_mode mode = xmodes[mode_idx];
+      const HOST_WIDE_INT mode_len = GET_MODE_SIZE (mode);
+      for (; n >= mode_len; n -= mode_len, off += mode_len)
+	{
+	  if (pat != NULL)
+	    output_asm_insn (pat, operands);
+	  if (n == mode_len)
+	    code_idx = 2;
+	  operands[0] = mkrtx(dest_codes[code_idx], mode, dest, off);
+	  operands[1] = mkrtx(src_codes[code_idx], mode, src, off);
+	  if (pat == NULL)
+	    code_idx = 1;
+	  pat = pats[mode_idx];
+	}
+    }
+
+  return pat;
+}
+
 /* True if X is an rtx for a constant that is a valid address.  */
 
 bool
@@ -1647,9 +1777,25 @@ legitimate_constant_address_p (rtx x)
       && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (x, 0), 0)))
     return false;
 #endif
+   gcc_assert (! REG_P (x));
    return true;
 }
 
+/* When generating PIC code, return false (disallow) an operand to
+   be global symbol + offset */
+bool
+legitimate_pic_operand_p (rtx x)
+{
+#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
+  if (GET_CODE (x) != CONST)
+    return true;
+  if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+      && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (x, 0), 0)))
+    return false;
+#endif
+  return true;
+}
+
 /* The other macros defined here are used only in legitimate_address_p ().  */
 
 /* Nonzero if X is a hard reg that can be used as an index
@@ -1956,8 +2102,10 @@ vax_expand_addsub_di_operands (rtx * operands, enum rtx_code code)
 	 and that's just a left shift of 1.  */
       if (rtx_equal_p (operands[1], operands[2]))
 	{
-	  gcc_assert (code != MINUS);
-	  emit_insn (gen_ashldi3 (operands[0], operands[1], const1_rtx));
+	  if (code == MINUS)
+	    emit_insn (gen_movdi (operands[0], const0_rtx));
+	  else
+	    emit_insn (gen_ashldi3 (operands[0], operands[1], const1_rtx));
 	  return;
 	}
 
@@ -2022,7 +2170,7 @@ adjacent_operands_p (rtx lo, rtx hi, machine_mode mode)
   if (REG_P (lo))
     return mode == SImode && REGNO (lo) + 1 == REGNO (hi);
   if (CONST_INT_P (lo))
-    return INTVAL (hi) == 0 && UINTVAL (lo) < 64;
+    return INTVAL (hi) == 0 && INTVAL (lo) >= 0 && INTVAL (lo) < 64;
   if (CONST_INT_P (lo))
     return mode != SImode;
 
@@ -2167,3 +2315,54 @@ vax_starting_frame_offset (void)
   return TARGET_ELF ? -4 : 0;
 }
 
+/* return true if the DImode can be decomposed */
+bool
+vax_decomposed_dimode_operand_p (rtx lo, rtx hi)
+{
+  HOST_WIDE_INT lo_offset = 0;
+  HOST_WIDE_INT hi_offset = 0;
+
+  /* If the codes aren't the same, can't be a DImode operand.  */
+  if (GET_CODE (lo) != GET_CODE (hi))
+    return false;
+
+  /* If a register, hi regno must be one more than the lo regno.  */
+  if (REG_P (lo))
+    return REGNO (lo) + 1 == REGNO (hi);
+
+  /* If not memory, can't be a DImode operand.  */
+  if (!MEM_P (lo))
+    return false;
+
+  /* Get addresses of memory operands.  */
+  lo = XEXP(lo, 0);
+  hi = XEXP(hi, 0);
+
+  /* If POST_INC, regno must match.  */
+  if (GET_CODE (lo) == POST_INC && GET_CODE (hi) == POST_INC)
+    return REGNO (XEXP (lo, 0)) == REGNO (XEXP (hi, 0));
+
+  if (GET_CODE (lo) == PLUS)
+    {
+      /* If PLUS or MULT, this must an indexed address so fail.  */
+      if (GET_CODE (XEXP (lo, 0)) == PLUS
+	  || GET_CODE (XEXP (lo, 0)) == MULT
+	  || !CONST_INT_P (XEXP (lo, 1)))
+	return false;
+      lo_offset = INTVAL (XEXP (lo, 1));
+      lo = XEXP(lo, 0);
+    }
+
+  if (GET_CODE (hi) == PLUS)
+    {
+      /* If PLUS or MULT, this must an indexed address so fail.  */
+      if (GET_CODE (XEXP (hi, 0)) == PLUS
+	  || GET_CODE (XEXP (hi, 0)) == MULT
+	  || !CONST_INT_P (XEXP (hi, 1)))
+	return false;
+      hi_offset = INTVAL (XEXP (hi, 1));
+      hi = XEXP(hi, 0);
+    }
+
+  return rtx_equal_p(lo, hi) && lo_offset + 4 == hi_offset;
+}
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index e7137dc..10da067 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#include "vax-protos.h"
 
 /* Target CPU builtins.  */
 #define TARGET_CPU_CPP_BUILTINS()		\
@@ -138,6 +139,9 @@ along with GCC; see the file COPYING3.  If not see
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
+/* VAX PSW for DWARF-2 */
+#define PSW_REGNUM VAX_PSW_REGNUM
+
 /* VAX pc is overloaded on a register.  */
 #define PC_REGNUM VAX_PC_REGNUM
 
@@ -346,6 +350,10 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 					RETURN_ADDRESS_OFFSET))		\
    : (rtx) 0)
 
+/* A C expression that is nonzero if X is a legitimate immediate operand
+   on the target machine when generating position independent code.  */
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
 
 /* Addressing modes, and classification of registers for them.  */
 
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index 298f339..c8682bf 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -40,6 +40,7 @@
    (VAX_FP_REGNUM 13)	    ; Register 13 contains the frame pointer
    (VAX_SP_REGNUM 14)	    ; Register 14 contains the stack pointer
    (VAX_PC_REGNUM 15)	    ; Register 15 contains the program counter
+   (VAX_PSW_REGNUM 16)	    ; Program Status Word
   ]
 )
 
@@ -57,6 +58,22 @@
 ;; Some output patterns want integer immediates with a prefix...
 (define_mode_attr  iprefx [(QI "B") (HI "H") (SI "N")])
 
+;; Types of instructions (for scheduling purposes).
+
+(define_attr "type" "load,store,bit1,mult,macc,div,fpu,single,other"
+  (const_string "other"))
+
+
+(define_insn_reservation "vax_other" 1
+			 (eq_attr "type" "other")
+			 "nothing")
+(define_insn_reservation "vax_mult" 2
+			 (eq_attr "type" "mult")
+			 "nothing")
+(define_insn_reservation "vax_memory" 2
+			 (eq_attr "type" "load")
+			 "nothing")
+
 ;;
 (include "constraints.md")
 (include "predicates.md")
@@ -215,6 +232,11 @@
   ""
   "
 {
+  if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) <= 48)
+    {
+      emit_insn (gen_movmemsi1_2 (operands[0], operands[1], operands[2]));
+      DONE;
+    }
   emit_insn (gen_cpymemhi1 (operands[0], operands[1], operands[2]));
   DONE;
 }")
@@ -224,6 +246,13 @@
 ;; that anything generated as this insn will be recognized as one
 ;; and that it won't successfully combine with anything.
 
+(define_insn "movmemsi1_2"
+  [(set (match_operand:BLK 0 "memory_operand" "=B")
+	(match_operand:BLK 1 "memory_operand" "B"))
+   (use (match_operand:SI 2 "const_int_operand" "g"))]
+  "INTVAL (operands[2]) <= 48"
+  "* return vax_output_movmemsi (insn, operands);")
+
 (define_insn "cpymemhi1"
   [(set (match_operand:BLK 0 "memory_operand" "=o")
 	(match_operand:BLK 1 "memory_operand" "o"))
@@ -773,6 +802,9 @@
 ;; These handle aligned 8-bit and 16-bit fields,
 ;; which can usually be done with move instructions.
 
+;; netbsd changed this to REG_P (operands[0]) || (MEM_P (operands[0]) && ...
+;; but gcc made it just !MEM_P (operands[0]) || ...
+
 (define_insn ""
   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+ro")
 			 (match_operand:QI 1 "const_int_operand" "n")
@@ -780,9 +812,10 @@
 	(match_operand:SI 3 "general_operand" "g"))]
    "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
    && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
-   && (!MEM_P (operands[0])
-       || ! mode_dependent_address_p (XEXP (operands[0], 0),
-				       MEM_ADDR_SPACE (operands[0])))"
+   && (REG_P (operands[0])
+       || (MEM_P (operands[0])
+	  && ! mode_dependent_address_p (XEXP (operands[0], 0),
+				       MEM_ADDR_SPACE (operands[0]))))"
   "*
 {
   if (REG_P (operands[0]))
@@ -809,9 +842,10 @@
 			 (match_operand:SI 3 "const_int_operand" "n")))]
   "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
    && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
-   && (!MEM_P (operands[1])
-       || ! mode_dependent_address_p (XEXP (operands[1], 0),
-				      MEM_ADDR_SPACE (operands[1])))"
+   && (REG_P (operands[1])
+       || (MEM_P (operands[1])
+	  && ! mode_dependent_address_p (XEXP (operands[1], 0),
+				      MEM_ADDR_SPACE (operands[1]))))"
   "*
 {
   if (REG_P (operands[1]))
@@ -837,9 +871,10 @@
 			 (match_operand:SI 3 "const_int_operand" "n")))]
   "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
    && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
-   && (!MEM_P (operands[1])
-       || ! mode_dependent_address_p (XEXP (operands[1], 0),
-				      MEM_ADDR_SPACE (operands[1])))"
+   && (REG_P (operands[1])
+       || (MEM_P (operands[1])
+	  && ! mode_dependent_address_p (XEXP (operands[1], 0),
+				      MEM_ADDR_SPACE (operands[1]))))"
   "*
 {
   if (REG_P (operands[1]))
@@ -1081,26 +1116,26 @@
 
 (define_expand "cbranch<mode>4"
   [(set (cc0)
-        (compare (match_operand:VAXint 1 "nonimmediate_operand" "")
-                 (match_operand:VAXint 2 "general_operand" "")))
+	(compare (match_operand:VAXint 1 "nonimmediate_operand" "")
+		 (match_operand:VAXint 2 "general_operand" "")))
    (set (pc)
-        (if_then_else
-              (match_operator 0 "ordered_comparison_operator" [(cc0)
-                                                               (const_int 0)])
-              (label_ref (match_operand 3 "" ""))
-              (pc)))]
+	(if_then_else
+	      (match_operator 0 "ordered_comparison_operator" [(cc0)
+							       (const_int 0)])
+	      (label_ref (match_operand 3 "" ""))
+	      (pc)))]
  "")
 
 (define_expand "cbranch<mode>4"
   [(set (cc0)
-        (compare (match_operand:VAXfp 1 "general_operand" "")
-                 (match_operand:VAXfp 2 "general_operand" "")))
+	(compare (match_operand:VAXfp 1 "general_operand" "")
+		 (match_operand:VAXfp 2 "general_operand" "")))
    (set (pc)
-        (if_then_else
-              (match_operator 0 "ordered_comparison_operator" [(cc0)
-                                                               (const_int 0)])
-              (label_ref (match_operand 3 "" ""))
-              (pc)))]
+	(if_then_else
+	      (match_operator 0 "ordered_comparison_operator" [(cc0)
+							       (const_int 0)])
+	      (label_ref (match_operand 3 "" ""))
+	      (pc)))]
  "")
 
 (define_insn "*branch"
@@ -1660,3 +1695,30 @@
   emit_barrier ();
   DONE;
 })
+
+(include "builtins.md")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "push_operand" "")
+	(const_int 0))
+   (set (match_dup 0)
+	(match_operand:SI 1 "const_int_operand" ""))]
+  "INTVAL (operands[1]) >= 0"
+  [(set (match_dup 0)
+	(match_dup 1))]
+  "operands[0] = gen_rtx_MEM (DImode, XEXP (operands[0], 0));")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "push_operand" "")
+	(match_operand:SI 1 "general_operand" ""))
+   (set (match_dup 0)
+	(match_operand:SI 2 "general_operand" ""))]
+  "vax_decomposed_dimode_operand_p (operands[2], operands[1])"
+  [(set (match_dup 0)
+	(match_dup 2))]
+  "{
+    operands[0] = gen_rtx_MEM (DImode, XEXP (operands[0], 0));
+    operands[2] = REG_P (operands[2])
+      ? gen_rtx_REG (DImode, REGNO (operands[2]))
+      : gen_rtx_MEM (DImode, XEXP (operands[2], 0));
+}")
