--- gcc/toplev.c.jj	2013-02-13 09:29:16.197757222 +0100
+++ gcc/toplev.c	2013-02-13 11:34:38.855800182 +0100
@@ -912,7 +912,7 @@ init_asm_output (const char *name)
       if (!strcmp (asm_file_name, "-"))
 	asm_out_file = stdout;
       else
-	asm_out_file = fopen (asm_file_name, "w");
+	asm_out_file = fopen (asm_file_name, "w+b");
       if (asm_out_file == 0)
 	fatal_error ("can%'t open %s for writing: %m", asm_file_name);
     }
--- gcc/c-family/c-pch.c.jj	2013-02-13 09:29:16.065757956 +0100
+++ gcc/c-family/c-pch.c	2013-02-13 11:34:45.552761549 +0100
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.
 #include "tree.h"
 #include "flags.h"
 #include "c-common.h"
+#include "output.h" /* for asm_out_file */
 #include "debug.h"
 #include "c-pragma.h"
 #include "ggc.h"
@@ -67,11 +68,19 @@ struct c_pch_validity
   size_t target_data_length;
 };
 
+struct c_pch_header
+{
+  unsigned long asm_size;
+};
+
 #define IDENT_LENGTH 8
 
 /* The file we'll be writing the PCH to.  */
 static FILE *pch_outfile;
 
+/* The position in the assembler output file when pch_init was called.  */
+static long asm_file_startpos;
+
 static const char *get_ident (void);
 
 /* Compute an appropriate 8-byte magic number for the PCH file, so that
@@ -83,7 +92,7 @@ static const char *
 get_ident (void)
 {
   static char result[IDENT_LENGTH];
-  static const char templ[] = "gpch.014";
+  static const char templ[] = "gpch.013";
   static const char c_language_chars[] = "Co+O";
 
   memcpy (result, templ, IDENT_LENGTH);
@@ -97,7 +106,9 @@ get_ident (void)
 static bool pch_ready_to_save_cpp_state = false;
 
 /* Prepare to write a PCH file, if one is being written.  This is
-   called at the start of compilation.  */
+   called at the start of compilation.
+
+   Also, print out the executable checksum if -fverbose-asm is in effect.  */
 
 void
 pch_init (void)
@@ -107,6 +118,15 @@ pch_init (void)
   void *target_validity;
   static const char partial_pch[] = "gpcWrite";
 
+#ifdef ASM_COMMENT_START
+  if (flag_verbose_asm)
+    {
+      fprintf (asm_out_file, "%s ", ASM_COMMENT_START);
+      c_common_print_pch_checksum (asm_out_file);
+      fputc ('\n', asm_out_file);
+    }
+#endif
+
   if (!pch_file)
     return;
 
@@ -136,6 +156,14 @@ pch_init (void)
       || fwrite (target_validity, v.target_data_length, 1, f) != 1)
     fatal_error ("can%'t write to %s: %m", pch_file);
 
+  /* We need to be able to re-read the output.  */
+  /* The driver always provides a valid -o option.  */
+  if (asm_file_name == NULL
+      || strcmp (asm_file_name, "-") == 0)
+    fatal_error ("%qs is not a valid output file", asm_file_name);
+
+  asm_file_startpos = ftell (asm_out_file);
+
   /* Let the debugging format deal with the PCHness.  */
   (*debug_hooks->handle_pch) (0);
 
@@ -172,6 +200,11 @@ pch_cpp_save_state (void)
 void
 c_common_write_pch (void)
 {
+  char *buf;
+  long asm_file_end;
+  long written;
+  struct c_pch_header h;
+
   timevar_push (TV_PCH_SAVE);
 
   targetm.prepare_pch_save ();
@@ -180,6 +213,34 @@ c_common_write_pch (void)
 
   cpp_write_pch_deps (parse_in, pch_outfile);
 
+  asm_file_end = ftell (asm_out_file);
+  h.asm_size = asm_file_end - asm_file_startpos;
+
+  if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
+    fatal_error ("can%'t write %s: %m", pch_file);
+
+  buf = XNEWVEC (char, 16384);
+
+  if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
+    fatal_error ("can%'t seek in %s: %m", asm_file_name);
+
+  for (written = asm_file_startpos; written < asm_file_end; )
+    {
+      long size = asm_file_end - written;
+      if (size > 16384)
+	size = 16384;
+      if (fread (buf, size, 1, asm_out_file) != 1)
+	fatal_error ("can%'t read %s: %m", asm_file_name);
+      if (fwrite (buf, size, 1, pch_outfile) != 1)
+	fatal_error ("can%'t write %s: %m", pch_file);
+      written += size;
+    }
+  free (buf);
+  /* asm_out_file can be written afterwards, so fseek to clear
+     _IOREAD flag.  */
+  if (fseek (asm_out_file, 0, SEEK_END) != 0)
+    fatal_error ("can%'t seek in %s: %m", asm_file_name);
+
   gt_pch_save (pch_outfile);
 
   timevar_push (TV_PCH_CPP_SAVE);
@@ -341,6 +402,7 @@ c_common_read_pch (cpp_reader *pfile, co
 		   int fd, const char *orig_name ATTRIBUTE_UNUSED)
 {
   FILE *f;
+  struct c_pch_header h;
   struct save_macro_data *smd;
   expanded_location saved_loc;
   bool saved_trace_includes;
@@ -357,6 +419,38 @@ c_common_read_pch (cpp_reader *pfile, co
 
   cpp_get_callbacks (parse_in)->valid_pch = NULL;
 
+  if (fread (&h, sizeof (h), 1, f) != 1)
+    {
+      cpp_errno (pfile, CPP_DL_ERROR, "reading");
+      fclose (f);
+      goto end;
+    }
+
+  if (!flag_preprocess_only)
+    {
+      unsigned long written;
+      char * buf = XNEWVEC (char, 16384);
+
+      for (written = 0; written < h.asm_size; )
+	{
+	  long size = h.asm_size - written;
+	  if (size > 16384)
+	    size = 16384;
+	  if (fread (buf, size, 1, f) != 1
+	      || fwrite (buf, size, 1, asm_out_file) != 1)
+	    cpp_errno (pfile, CPP_DL_ERROR, "reading");
+	  written += size;
+	}
+      free (buf);
+    }
+  else
+    {
+      /* If we're preprocessing, don't write to a NULL
+	 asm_out_file.  */
+      if (fseek (f, h.asm_size, SEEK_CUR) != 0)
+	cpp_errno (pfile, CPP_DL_ERROR, "seeking");
+    }
+
   /* Save the location and then restore it after reading the PCH.  */
   saved_loc = expand_location (line_table->highest_line);
   saved_trace_includes = line_table->trace_includes;
@@ -435,3 +529,14 @@ c_common_pch_pragma (cpp_reader *pfile,
   close (fd);
 }
 
+/* Print out executable_checksum[].  */
+
+void
+c_common_print_pch_checksum (FILE *f)
+{
+  int i;
+  fputs ("Compiler executable checksum: ", f);
+  for (i = 0; i < 16; i++)
+    fprintf (f, "%02x", executable_checksum[i]);
+  putc ('\n', f);
+}
--- gcc/c-family/c-opts.c.jj	2013-02-13 09:29:16.110757723 +0100
+++ gcc/c-family/c-opts.c	2013-02-13 11:34:45.551761562 +0100
@@ -999,13 +999,7 @@ c_common_init (void)
   cpp_init_iconv (parse_in);
 
   if (version_flag)
-    {
-      int i;
-      fputs ("Compiler executable checksum: ", stderr);
-      for (i = 0; i < 16; i++)
-	fprintf (stderr, "%02x", executable_checksum[i]);
-      putc ('\n', stderr);
-    }
+    c_common_print_pch_checksum (stderr);
 
   /* Has to wait until now so that cpplib has its hash table.  */
   init_pragma ();
--- gcc/c-family/c-common.h.jj	2013-02-13 09:29:16.152757462 +0100
+++ gcc/c-family/c-common.h	2013-02-13 11:34:45.551761562 +0100
@@ -1011,6 +1011,7 @@ extern void c_common_read_pch (cpp_reade
 extern void c_common_write_pch (void);
 extern void c_common_no_more_pch (void);
 extern void c_common_pch_pragma (cpp_reader *pfile, const char *);
+extern void c_common_print_pch_checksum (FILE *f);
 
 /* In *-checksum.c */
 extern const unsigned char executable_checksum[16];
