diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 267ce8922418a4895fb7e08c2ca93f6171e8b90d..2241bad1aded7ef7198cc3fa249dc0565bcb72bf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+Wed May  3 12:40:53 2000  Clinton Popetz  <cpopetz@cygnus.com>
+
+	* gensupport.c: New file.
+	* gensupport.h: New file.
+	* Makefile.in (HOST_RTL): Depend on gensupport.
+	(gensupport.o) New rule.
+	* genattr.c: Use gensupport for reading .md files.
+	* genattrtab.c: Ditto. 
+	* gencodes.c: Ditto. 
+	* genconfig.c: Ditto. 
+	* genemit.c: Ditto. 
+	* genextract.c: Ditto. 
+	* genflags.c: Ditto. 
+	* genopinit.c: Ditto. 
+	* genoutput.c: Ditto. 
+	* genpeep.c: Ditto. 
+	* genrecog.c: Ditto.
+	* rtl.def (define_insn_and_split): New DEF_RTL_EXPR.
+	* md.texi (Insn Splitting): Document define_insn_and_split.
+
 Tue May  2 00:20:30 2000  Jason Eckhardt  <jle@cygnus.com>
 
         * flow.c (verify_flow_info): Added two more sanity checks. The
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 197cc7f281ae3470a859bd41bf1516edff4ea091..5bd8cc9abc41566e8c7b6374e7a33e2b579caa4c 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -586,7 +586,9 @@ HOST_LIBS = $(USE_HOST_OBSTACK) $(USE_HOST_ALLOCA) $(USE_HOST_MALLOC)  \
 	    $(HOST_INTLLIBS) $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) \
 	    $(HOST_CLIB)
 
-HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o $(HOST_PREFIX)ggc-none.o
+HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o \
+		$(HOST_PREFIX)ggc-none.o $(HOST_PREFIX)gensupport.o
+
 HOST_PRINT = $(HOST_PREFIX)print-rtl.o
 HOST_ERRORS = $(HOST_PREFIX)errors.o
 
@@ -1514,6 +1516,7 @@ toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) function.h \
 	  -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
 
 rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h $(GGC_H) toplev.h
+gensupport.o : gensupport.c $(CONFIG_H) system.h $(RTL_H) 
 
 print-rtl.o : print-rtl.c $(CONFIG_H) system.h $(RTL_H) $(BASIC_BLOCK_H)
 rtlanal.o : rtlanal.c $(CONFIG_H) system.h $(RTL_H)
diff --git a/gcc/genattr.c b/gcc/genattr.c
index 30160a443795a66ff07ca8cccebc3636e1229c7a..36a37b1a40884f844d22592165233e354196b434 100644
--- a/gcc/genattr.c
+++ b/gcc/genattr.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -222,8 +223,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
   int have_delay = 0;
   int have_annul_true = 0;
   int have_annul_false = 0;
@@ -245,13 +244,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   printf ("/* Generated automatically by the program `genattr'\n\
 from the machine description file `md'.  */\n\n");
@@ -266,12 +260,12 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      int line_no, insn_code_number;
+
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
 
-      desc = read_rtx (infile);
       if (GET_CODE (desc) == DEFINE_ATTR)
 	gen_attr (desc);
 
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index 2dab1b6f5bbd09dfa027d15e96bc652f43f45691..b1be9a070e4e9ff8323d547319592d0e7b79a68a 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -100,6 +100,7 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "rtl.h"
 #include "ggc.h"
+#include "gensupport.h"
 
 #ifdef HAVE_SYS_RESOURCE_H
 # include <sys/resource.h>
@@ -4304,8 +4305,8 @@ gen_insn (exp)
   switch (GET_CODE (exp))
     {
     case DEFINE_INSN:
-      id->insn_code = insn_code_number++;
-      id->insn_index = insn_index_number++;
+      id->insn_code = insn_code_number;
+      id->insn_index = insn_index_number;
       id->num_alternatives = count_alternatives (exp);
       if (id->num_alternatives == 0)
 	id->num_alternatives = 1;
@@ -4313,8 +4314,8 @@ gen_insn (exp)
       break;
 
     case DEFINE_PEEPHOLE:
-      id->insn_code = insn_code_number++;
-      id->insn_index = insn_index_number++;
+      id->insn_code = insn_code_number;
+      id->insn_index = insn_index_number;
       id->num_alternatives = count_alternatives (exp);
       if (id->num_alternatives == 0)
 	id->num_alternatives = 1;
@@ -5967,8 +5968,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
   struct attr_desc *attr;
   struct insn_def *id;
   rtx tem;
@@ -5976,6 +5975,12 @@ main (argc, argv)
 
   progname = "genattrtab";
 
+  if (argc <= 1)
+    fatal ("No input file name.");
+
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
+
 #if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT)
   /* Get rid of any avoidable limit on stack size.  */
   {
@@ -5993,17 +5998,6 @@ main (argc, argv)
   obstack_init (hash_obstack);
   obstack_init (temp_obstack);
 
-  if (argc <= 1)
-    fatal ("No input file name.");
-
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
-
   /* Set up true and false rtx's */
   true_rtx = rtx_alloc (CONST_INT);
   XWINT (true_rtx, 0) = 1;
@@ -6021,45 +6015,41 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
-	break;
-      ungetc (c, infile);
-
-      desc = read_rtx (infile);
-      if (GET_CODE (desc) == DEFINE_INSN
-	  || GET_CODE (desc) == DEFINE_PEEPHOLE
-	  || GET_CODE (desc) == DEFINE_ASM_ATTRIBUTES)
-	gen_insn (desc);
-
-      else if (GET_CODE (desc) == DEFINE_EXPAND)
-	insn_code_number++, insn_index_number++;
+      int line_no;
 
-      else if (GET_CODE (desc) == DEFINE_SPLIT)
-	insn_code_number++, insn_index_number++;
-
-      else if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
-	insn_code_number++, insn_index_number++;
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
+	break;
 
-      else if (GET_CODE (desc) == DEFINE_ATTR)
+      switch (GET_CODE (desc))
 	{
-	  gen_attr (desc);
-	  insn_index_number++;
-	}
+	  case DEFINE_INSN:
+	  case DEFINE_PEEPHOLE:
+	  case DEFINE_ASM_ATTRIBUTES:
+	      gen_insn(desc);
+	      break;
+	  
+	  case DEFINE_ATTR:
+	      gen_attr (desc);
+	      break;
 
-      else if (GET_CODE (desc) == DEFINE_DELAY)
-	{
-	  gen_delay (desc);
-	  insn_index_number++;
-	}
+	  case DEFINE_DELAY:
+	      gen_delay (desc);
+	      break;
 
-      else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT)
-	{
-	  gen_unit (desc);
-	  insn_index_number++;
+	  case DEFINE_FUNCTION_UNIT:
+	      gen_unit (desc);
+	      break;
+	      	
+	  default:
+	      break;
 	}
+      if (GET_CODE (desc) != DEFINE_ASM_ATTRIBUTES)
+        insn_index_number++;
     }
 
+  insn_code_number++;
+
   /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one.  */
   if (! got_define_asm_attributes)
     {
diff --git a/gcc/gencodes.c b/gcc/gencodes.c
index 39db3912cda33e8fa5f0a380042e9af16fd584a1..750839b39c8b05ea18da00a10aacf305cad41d07 100644
--- a/gcc/gencodes.c
+++ b/gcc/gencodes.c
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -84,8 +85,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
 
   progname = "gencodes";
   obstack_init (rtl_obstack);
@@ -93,13 +92,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   printf ("/* Generated automatically by the program `gencodes'\n\
 from the machine description file `md'.  */\n\n");
@@ -113,23 +107,14 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      int line_no;
+
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
 
-      desc = read_rtx (infile);
       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
-	{
-	  gen_insn (desc);
-	  insn_code_number++;
-	}
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE
-	  || GET_CODE (desc) == DEFINE_PEEPHOLE2
-	  || GET_CODE (desc) == DEFINE_SPLIT)
-	{
-	  insn_code_number++;
-	}
+	gen_insn (desc);
     }
 
   printf ("  CODE_FOR_nothing };\n");
diff --git a/gcc/genconfig.c b/gcc/genconfig.c
index d78af0384b3fa441a1f0b1fd282801fc3b99b451..077216292e99dd7c5125dd80985fb19faa574536 100644
--- a/gcc/genconfig.c
+++ b/gcc/genconfig.c
@@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -279,8 +280,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
 
   progname = "genconfig";
   obstack_init (rtl_obstack);
@@ -288,13 +287,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   printf ("/* Generated automatically by the program `genconfig'\n\
 from the machine description file `md'.  */\n\n");
@@ -307,27 +301,38 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      int line_no, insn_code_number = 0;
+
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
-
-      desc = read_rtx (infile);
-      if (GET_CODE (desc) == DEFINE_INSN)
-	gen_insn (desc);
-      if (GET_CODE (desc) == DEFINE_EXPAND)
-	gen_expand (desc);
-      if (GET_CODE (desc) == DEFINE_SPLIT)
-	gen_split (desc);
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
-	{
-	  have_peephole2_flag = 1;
-	  gen_split (desc);
-	}
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
+	
+      switch (GET_CODE (desc)) 
 	{
-	  have_peephole_flag = 1;
-	  gen_peephole (desc);
+  	  case DEFINE_INSN:
+	    gen_insn (desc);
+	    break;
+	  
+	  case DEFINE_EXPAND:
+	    gen_expand (desc);
+	    break;
+
+	  case DEFINE_SPLIT:
+	    gen_split (desc);
+	    break;
+
+	  case DEFINE_PEEPHOLE2:
+	    have_peephole2_flag = 1;
+	    gen_split (desc);
+	    break;
+
+	  case DEFINE_PEEPHOLE:
+	    have_peephole_flag = 1;
+	    gen_peephole (desc);
+	    break;
+
+	  default:
+	    break;
 	}
     }
 
diff --git a/gcc/genemit.c b/gcc/genemit.c
index f2bac1686b438e592bf1f317d88d4a5b19fffb6c..6fc604d7c23ed03ac19d29c1f2dab24a3f307bcd 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -779,8 +780,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
 
   progname = "genemit";
   obstack_init (rtl_obstack);
@@ -788,13 +787,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   /* Assign sequential codes to all entries in the machine description
      in parallel with the tables in insn-output.c.  */
@@ -828,37 +822,33 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
-	break;
-      ungetc (c, infile);
+      int line_no;
 
-      desc = read_rtx (infile);
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
+	break;
 
-      if (GET_CODE (desc) == DEFINE_INSN)
+      switch (GET_CODE (desc))
 	{
-	  gen_insn (desc);
-	  ++insn_code_number;
-	}
-      if (GET_CODE (desc) == DEFINE_EXPAND)
-	{
-	  gen_expand (desc);
-	  ++insn_code_number;
-	}
-      if (GET_CODE (desc) == DEFINE_SPLIT)
-	{
-	  gen_split (desc);
-	  ++insn_code_number;
-	}
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
-	{
-	  gen_split (desc);
-	  ++insn_code_number;
-	}
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
-	{
-	  ++insn_code_number;
-	}
+	  case DEFINE_INSN:
+	      gen_insn (desc);
+	      break;
+
+	  case DEFINE_EXPAND:
+	      gen_expand (desc);
+	      break;
+
+	  case DEFINE_SPLIT:
+	      gen_split (desc);
+	      break;
+
+	  case DEFINE_PEEPHOLE2:
+	      gen_split (desc);
+	      break;
+
+	  default:
+	      break;
+	 }
       ++insn_index_number;
     }
 
diff --git a/gcc/genextract.c b/gcc/genextract.c
index 9e291c9bc46bfce4276b0875d94cd39f28598c13..fea04928d24a8cbbfdd319bbe7b5cb5654dce921 100644
--- a/gcc/genextract.c
+++ b/gcc/genextract.c
@@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA.  */
 #include "obstack.h"
 #include "errors.h"
 #include "insn-config.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -389,8 +390,7 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  int c, i;
+  int i;
   struct extraction *p;
   struct code_ptr *link;
   const char *name;
@@ -401,13 +401,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   /* Assign sequential codes to all entries in the machine description
      in parallel with the tables in insn-output.c.  */
@@ -446,17 +441,16 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      int line_no;
+
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
 
-      desc = read_rtx (infile);
-      if (GET_CODE (desc) == DEFINE_INSN)
+       if (GET_CODE (desc) == DEFINE_INSN)
 	{
 	  record_insn_name (insn_code_number, XSTR (desc, 0));
 	  gen_insn (desc);
-	  ++insn_code_number;
 	}
 
       else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
@@ -467,13 +461,7 @@ from the machine description file `md'.  */\n\n");
 	  link->insn_code = insn_code_number;
 	  link->next = peepholes;
 	  peepholes = link;
-	  ++insn_code_number;
 	}
-
-      else if (GET_CODE (desc) == DEFINE_EXPAND
-	       || GET_CODE (desc) == DEFINE_PEEPHOLE2
-	       || GET_CODE (desc) == DEFINE_SPLIT)
-	++insn_code_number;
     }
 
   /* Write out code to handle peepholes and the insn_codes that it should
diff --git a/gcc/genflags.c b/gcc/genflags.c
index 39b5354e7dc280c259e9e376c128c982a7d462d8..f679dd2c4685c4029f31c72a8ef7a783eb044790 100644
--- a/gcc/genflags.c
+++ b/gcc/genflags.c
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -227,8 +228,6 @@ main (argc, argv)
   rtx *call_insns;
   rtx *normal_insns;
   rtx *insn_ptr;
-  FILE *infile;
-  register int c;
 
   progname = "genflags";
   obstack_init (rtl_obstack);
@@ -238,14 +237,9 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
-
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
+  
   printf ("/* Generated automatically by the program `genflags'\n\
 from the machine description file `md'.  */\n\n");
 
@@ -253,12 +247,11 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
-	break;
-      ungetc (c, infile);
+      int line_no, insn_code_number = 0;
 
-      desc = read_rtx (infile);
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
+	break;
       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
 	gen_insn (desc);
     }
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index ac5debbb30f6f64bec8e02c35d2ff3982777355a..2cd5d8edb1c1aa588ae93afd14579571a6a08af7 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -313,8 +314,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
 
   progname = "genopinit";
   obstack_init (rtl_obstack);
@@ -322,13 +321,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   printf ("/* Generated automatically by the program `genopinit'\n\
 from the machine description file `md'.  */\n\n");
@@ -350,12 +344,12 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      int line_no, insn_code_number = 0;
+
+      desc = read_md_rtx (&line_no, &insn_code_number);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
 
-      desc = read_rtx (infile);
       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
 	gen_insn (desc);
     }
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index d581da2adad1b55b8a6e1e0e1056beccd14cec9c..922359dbc6d6d4e1f969849c0d4b82481abd2a85 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -90,6 +90,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 /* No instruction can have more operands than this.  Sorry for this
    arbitrary limit, but what machine will have an instruction with
@@ -720,7 +721,7 @@ gen_insn (insn)
   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
   register int i;
 
-  d->code_number = next_code_number++;
+  d->code_number = next_code_number;
   d->index_number = next_index_number;
   if (XSTR (insn, 0)[0])
     d->name = XSTR (insn, 0);
@@ -759,7 +760,7 @@ gen_peephole (peep)
   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
   register int i;
 
-  d->code_number = next_code_number++;
+  d->code_number = next_code_number;
   d->index_number = next_index_number;
   d->name = 0;
 
@@ -797,7 +798,7 @@ gen_expand (insn)
   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
   register int i;
 
-  d->code_number = next_code_number++;
+  d->code_number = next_code_number;
   d->index_number = next_index_number;
   if (XSTR (insn, 0)[0])
     d->name = XSTR (insn, 0);
@@ -840,7 +841,7 @@ gen_split (split)
   register struct data *d = (struct data *) xmalloc (sizeof (struct data));
   register int i;
 
-  d->code_number = next_code_number++;
+  d->code_number = next_code_number;
   d->index_number = next_index_number;
   d->name = 0;
 
@@ -903,8 +904,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
 
   progname = "genoutput";
   obstack_init (rtl_obstack);
@@ -912,13 +911,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   output_prologue ();
   next_code_number = 0;
@@ -928,12 +922,12 @@ main (argc, argv)
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      int line_no;
+
+      desc = read_md_rtx (&line_no, &next_code_number);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
 
-      desc = read_rtx (infile);
       if (GET_CODE (desc) == DEFINE_INSN)
 	gen_insn (desc);
       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
diff --git a/gcc/genpeep.c b/gcc/genpeep.c
index fd1357da5b7f9b6dda4a5205688e54443036513b..b8ef9aae62bf964df9419511cd9f06f14fc0a1d7 100644
--- a/gcc/genpeep.c
+++ b/gcc/genpeep.c
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
@@ -408,8 +409,6 @@ main (argc, argv)
      char **argv;
 {
   rtx desc;
-  FILE *infile;
-  register int c;
 
   max_opno = -1;
 
@@ -419,13 +418,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return (FATAL_EXIT_CODE);
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   printf ("/* Generated automatically by the program `genpeep'\n\
 from the machine description file `md'.  */\n\n");
@@ -458,13 +452,13 @@ from the machine description file `md'.  */\n\n");
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      int line_no, rtx_number = 0;
+
+      desc = read_md_rtx (&line_no, &rtx_number);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
 
-      desc = read_rtx (infile);
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
+       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
 	{
 	  gen_peephole (desc);
 	  insn_code_number++;
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index 3acf5b1ecface2935b7744663c109849080d57c2..1f0c331b67b00f8832d7229821ca9dfdbbcdcb30 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -55,6 +55,7 @@
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "gensupport.h"
 
 #define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
   printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
@@ -2461,7 +2462,6 @@ make_insn_sequence (insn, type)
 	      next_insn_code);
       break;
     }
-  next_insn_code++;
 
   return head;
 }
@@ -2518,13 +2518,8 @@ main (argc, argv)
   if (argc <= 1)
     fatal ("No input file name.");
 
-  infile = fopen (argv[1], "r");
-  if (infile == 0)
-    {
-      perror (argv[1]);
-      return FATAL_EXIT_CODE;
-    }
-  read_rtx_filename = argv[1];
+  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+    return (FATAL_EXIT_CODE);
 
   next_insn_code = 0;
   next_index = 0;
@@ -2535,13 +2530,10 @@ main (argc, argv)
 
   while (1)
     {
-      c = read_skip_spaces (infile);
-      if (c == EOF)
+      desc = read_md_rtx (&pattern_lineno, &next_insn_code);
+      if (desc == NULL)
 	break;
-      ungetc (c, infile);
-      pattern_lineno = read_rtx_lineno;
 
-      desc = read_rtx (infile);
       if (GET_CODE (desc) == DEFINE_INSN)
 	{
 	  h = make_insn_sequence (desc, RECOG);
@@ -2558,9 +2550,6 @@ main (argc, argv)
 	  merge_trees (&peephole2_tree, &h);
 	}
 	
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE
-	  || GET_CODE (desc) == DEFINE_EXPAND)
-	next_insn_code++;
       next_index++;
     }
 
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
new file mode 100644
index 0000000000000000000000000000000000000000..aff9d847352f4e3a4bc7186b47755cfad1c72b2f
--- /dev/null
+++ b/gcc/gensupport.c
@@ -0,0 +1,191 @@
+/* Read machine descriptions, return top level rtx for use by the
+   various generation passes. 
+
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+   This file is part of GNU CC.
+
+   GNU CC 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)
+   any later version.
+
+   GNU CC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "hconfig.h"
+#include "system.h"
+#include "rtl.h"
+#include "errors.h"
+#include "gensupport.h"
+
+static FILE *input_file;
+
+static int sequence_num;
+
+struct queue_elem {
+    rtx data;
+    struct queue_elem *next;
+};
+
+static struct queue_elem *rtx_ready_queue;
+
+/* Recursively remove constraints from an rtx.  */
+
+static void
+remove_constraints (part)
+     rtx part;
+{
+  register int i, j;
+  register const char *format_ptr;
+
+  if (part == 0)
+    return;
+
+  if (GET_CODE (part) == MATCH_OPERAND)
+    XSTR (part, 2) = "";
+  else if (GET_CODE (part) == MATCH_SCRATCH)
+    XSTR (part, 1) = "";
+
+  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
+
+  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
+    switch (*format_ptr++)
+      {
+      case 'e':
+      case 'u':
+	remove_constraints (XEXP (part, i));
+	break;
+      case 'E':
+	if (XVEC (part, i) != NULL)
+	  for (j = 0; j < XVECLEN (part, i); j++)
+	    remove_constraints (XVECEXP (part, i, j));
+	break;
+      }
+}
+
+/* Handle any synthetic top level rtx, i.e. anything except:
+       DEFINE_INSN
+       DEFINE_EXPAND
+       DEFINE_SPLIT
+       DEFINE_PEEPHOLE
+       DEFINE_PEEPHOLE2
+       DEFINE_ATTRIBUTE
+       DEFINE_FUNCTION_UNIT
+       DEFINE_ASM_ATTRIBUTES */
+
+static void
+process_rtx (desc)
+    rtx* desc;
+{
+  if (GET_CODE (*desc) == DEFINE_INSN_AND_SPLIT) 
+    {
+      struct queue_elem* elem = xmalloc (sizeof (struct queue_elem));
+      const char *split_cond;
+  
+      /* Create a split with values from the insn_and_split. */
+      rtx split = rtx_alloc (DEFINE_SPLIT);
+      XVEC (split, 0) = copy_rtx (XVEC (*desc, 1));
+      remove_constraints (XVEC (split, 0));
+      split_cond = XSTR (split, 1) = XSTR (*desc, 4);
+  
+      /* If the split condition starts with "&&", append it to the
+         insn condition to create the new split condition.  */
+      if (split_cond[0] == '&' && split_cond[1] == '&')
+        {
+	const char *insn_cond = XSTR (*desc, 2);
+  	char *combined = 
+  	    xmalloc (strlen (insn_cond) + strlen (split_cond) + 1);
+  	strcpy (combined, insn_cond);
+  	strcat (combined, split_cond);
+  	XSTR (split, 1) = combined;
+        }
+  
+      XVEC (split, 2) = XVEC (*desc, 5);
+      XSTR (split, 3) = XSTR (*desc, 6);
+  
+      /* Fix up the DEFINE_INSN.  */
+      PUT_CODE (*desc, DEFINE_INSN);
+      XVEC (*desc, 4) = XSTR (*desc, 7);
+  
+      /* Return the DEFINE_INSN part, and put the DEFINE_SPLIT
+         in the queue.  */
+      elem->next = rtx_ready_queue;
+      elem->data = split;	
+      rtx_ready_queue = elem;  
+    }
+}
+
+/* The entry point for initializing the reader.  */
+
+int 
+init_md_reader (filename)
+    const char *filename;
+{
+
+  input_file = fopen (filename, "r");
+
+  if (input_file == 0)
+    {
+      perror (filename);
+      return FATAL_EXIT_CODE;
+    }
+
+  read_rtx_filename = filename;
+  sequence_num = 0;
+  rtx_ready_queue = NULL; 
+
+  return SUCCESS_EXIT_CODE;
+}
+
+
+/* The entry point for reading a single rtx from an md file.  */
+
+rtx 
+read_md_rtx (lineno, seqnr)
+    int *lineno;
+    int *seqnr;
+{ 
+  rtx desc;
+
+  if (rtx_ready_queue != NULL) 
+    {
+      desc = rtx_ready_queue->data;
+      rtx_ready_queue = rtx_ready_queue->next;
+    }
+  else 
+    {
+      int c;
+      c = read_skip_spaces (input_file);
+      if (c == EOF)
+	return NULL;
+
+      ungetc (c, input_file);
+      desc = read_rtx (input_file);
+      process_rtx (&desc);
+    }
+  *lineno = read_rtx_lineno;
+  *seqnr = sequence_num;
+  switch (GET_CODE (desc))
+    {
+      case DEFINE_INSN:
+      case DEFINE_EXPAND:
+      case DEFINE_SPLIT:
+      case DEFINE_PEEPHOLE:
+      case DEFINE_PEEPHOLE2:
+	sequence_num++;
+	break;
+
+      default:
+	break;
+    }
+
+  return desc;
+}
diff --git a/gcc/gensupport.h b/gcc/gensupport.h
new file mode 100644
index 0000000000000000000000000000000000000000..3dbec6b74200140167c26568c20ce66bff60151e
--- /dev/null
+++ b/gcc/gensupport.h
@@ -0,0 +1,24 @@
+/* Declarations for rtx-reader support for gen* routines.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC 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)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+extern int init_md_reader	PARAMS ((const char *));
+extern rtx read_md_rtx		PARAMS ((int *, int *));
+
+
diff --git a/gcc/md.texi b/gcc/md.texi
index 0b46d8164ee18a646508cf6385d0d24acb5c25ea..083a22811da11081a08765b4024fcde8c5b2129b 100644
--- a/gcc/md.texi
+++ b/gcc/md.texi
@@ -3431,6 +3431,56 @@ insns that don't.  Instead, write two separate @code{define_split}
 definitions, one for the insns that are valid and one for the insns that
 are not valid.
 
+For the common case where the pattern of a define_split exactly matches the
+pattern of a define_insn, use @code{define_insn_and_split}.  It looks like
+this:
+
+@smallexample
+(define_insn_and_split
+  [@var{insn-pattern}]
+  "@var{condition}"
+  "@var{output-template}"
+  "@var{split-condition}"
+  [@var{new-insn-pattern-1}
+   @var{new-insn-pattern-2}
+   @dots{}]
+  "@var{preparation statements}"
+  [@var{insn-attributes}])
+
+@end smallexample
+
+@var{insn-pattern}, @var{condition}, @var{output-template}, and
+@var{insn-attributes} are used as in @code{define_insn}.  The
+@var{new-insn-pattern} vector and the @var{preparation-statements} are used as
+in a @code{define_split}.  The @var{split-condition} is also used as in
+@code{define_split}, with the additional behavior that if the condition starts
+with @samp{&&}, the condition used for the split will be the constructed as a
+logical "and" of the split condition with the insn condition.  For example,
+from i386.md:
+
+@smallexample
+(define_insn_and_split "zero_extendhisi2_and"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+     (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
+   (clobber (reg:CC 17))]
+  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
+	      (clobber (reg:CC 17))])]
+  ""
+  [(set_attr "type" "alu1")])
+
+@end smallexample
+
+In this case, the actual split condition will be 
+"TARGET_ZERO_EXTEND_WITH_AND && !optimize_size && reload_completed."
+
+The @code{define_insn_and_split} construction provides exactly the same
+functionality as two separate @code{define_insn} and @code{define_split}
+patterns.  It exists for compactness, and as a maintenance tool to prevent
+having to ensure the two patterns' templates match.
+
 @node Peephole Definitions
 @section Machine-Specific Peephole Optimizers
 @cindex peephole optimizer definitions
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 30c5518e4df5bc5f8103ce15e65c5cc24c8bf24a..29cb5ee4bf8aa38e8991f5495cc364dea3c4c34b 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -203,6 +203,33 @@ DEF_RTL_EXPR(DEFINE_PEEPHOLE, "define_peephole", "EssV", 'x')
 	(`operands' is an alias here for `recog_operand').   */
 DEF_RTL_EXPR(DEFINE_SPLIT, "define_split", "EsES", 'x')
 
+/* Definition of an insn and associated split.
+   This is the concatenation, with a few modifications, of a define_insn
+   and a define_split which share the same pattern.
+   Operand:
+   0: names this instruction.
+      If the name is the null string, the instruction is in the
+      machine description just to be recognized, and will never be emitted by
+      the tree to rtl expander.
+   1: is the pattern.
+   2: is a string which is a C expression
+      giving an additional condition for recognizing this pattern.
+      A null string means no extra condition.
+   3: is the action to execute if this pattern is matched.
+      If this assembler code template starts with a * then it is a fragment of
+      C code to run to decide on a template to use.  Otherwise, it is the
+      template to use.
+   4: C expression that must be true for split.  This may start with "&&"
+      in which case the split condition is the logical and of the insn 
+      condition and what follows the "&&" of this operand.
+   5: vector of insn patterns to place into a SEQUENCE
+   6: optionally, some C code to execute before generating the
+	insns.  This might, for example, create some RTX's and store them in
+	elements of `recog_operand' for use by the vector of insn-patterns.
+	(`operands' is an alias here for `recog_operand').  
+   7: optionally, a vector of attributes for this insn.  */
+DEF_RTL_EXPR(DEFINE_INSN_AND_SPLIT, "define_insn_and_split", "sEsssESV", 'x')
+
 /* Definition of an RTL peephole operation.
    Follows the same arguments as define_split.  */
 DEF_RTL_EXPR(DEFINE_PEEPHOLE2, "define_peephole2", "EsES", 'x')