diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2c27f79b2322940a57db1440c6de87bb21495bb5..da042fe084057e7f510210db8a7e2d30d7c97b02 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2001-08-17  Richard Henderson  <rth@redhat.com>
+
+	* config/mips/iris6.h (TARGET_IRIX6): New.
+	(current_section_name, current_section_flags): New.
+	(ASM_OUTPUT_ALIGN, ASM_FILE_START, ASM_FILE_END): New.
+	(MAX_OFILE_ALIGNMENT): New.
+	(ASM_OUTPUT_ALIGNED_LOCAL): Use bss_section.
+	* config/mips/mips.c (mips_make_temp_file, temp_filename): Remove.
+	(copy_file_data): Split out from 
+	(mips_asm_file_end): ... here.
+	(mips_asm_file_start): Remove extra .section directive.  Use
+	tmpfile instead of mips_make_temp_file.
+	(mips_unique_section): Use const char * as needed for warnings.
+	(iris6_asm_named_section_1): Renamed from iris6_asm_named_section;
+	re-add align parameter.
+	(iris6_asm_named_section): New.
+	(iris_section_align_entry_eq, iris_section_align_entry_hash): New.
+	(iris6_asm_output_align, iris6_section_align_1): New.
+	(iris6_asm_file_start, iris6_asm_file_end): New.
+	* config/mips/mips-protos.h: Update decls.
+
 2001-08-17  Janis Johnson  <janis187@us.ibm.com>
 
 	* doc/install.texi (Install GCC): Add links to build status pages.
diff --git a/gcc/config/mips/iris6.h b/gcc/config/mips/iris6.h
index ee334870efb1e40d1dc5d9ce9dc34f7346ec86c2..ce9df16fff347afc88dc083b5f45152c91552a4d 100644
--- a/gcc/config/mips/iris6.h
+++ b/gcc/config/mips/iris6.h
@@ -18,6 +18,9 @@ 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.  */
 
+/* Let mips.c know we need the Irix6 functions.  */
+#define TARGET_IRIX6 1
+
 /* Default to -mabi=n32 and -mips3.  */
 #define MIPS_ISA_DEFAULT 3
 #define MIPS_ABI_DEFAULT ABI_N32
@@ -31,7 +34,7 @@ Boston, MA 02111-1307, USA.  */
 #include "mips/abi64.h"
 
 /* Irix6 assembler does handle DWARF2 directives.  Override setting in
- irix5.h file.  */
+   irix5.h file.  */
 #undef DWARF2_UNWIND_INFO
 
 /* The Irix6 assembler will sometimes assign labels to the wrong
@@ -130,6 +133,7 @@ Boston, MA 02111-1307, USA.  */
 /* Force the generation of dwarf .debug_frame sections even if not
    compiling -g.  This guarantees that we can unwind the stack. */
 #define DWARF2_FRAME_INFO 1
+
 /* The size in bytes of a DWARF field indicating an offset or length
    relative to a debug info section, specified to be 4 bytes in the DWARF-2
    specification.  The SGI/MIPS ABI defines it to be the same as PTR_SIZE.  */
@@ -289,13 +293,61 @@ rdata_section ()							\
 	fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP_32);	\
       in_section = in_rdata;						\
     }									\
+}									\
+									\
+const char *								\
+current_section_name ()							\
+{									\
+  switch (in_section)							\
+    {									\
+    case no_section:	return NULL;					\
+    case in_text:	return ".text";					\
+    case in_data:	return ".data";					\
+    case in_sdata:	return ".sdata";				\
+    case in_bss:	return ".bss";					\
+    case in_rdata:							\
+    case in_const:							\
+      if (mips_abi != ABI_32 && mips_abi != ABI_O64)			\
+	return ".rodata";						\
+      else								\
+	return ".rdata";						\
+    case in_named:							\
+      return in_named_name;						\
+    }									\
+  abort ();								\
+}									\
+									\
+unsigned int								\
+current_section_flags ()						\
+{									\
+  switch (in_section)							\
+    {									\
+    case no_section:	return 0;					\
+    case in_text:	return SECTION_CODE;				\
+    case in_data:	return SECTION_WRITE;				\
+    case in_sdata:	return SECTION_WRITE | SECTION_SMALL;		\
+    case in_bss:	return SECTION_WRITE | SECTION_BSS;		\
+    case in_rdata:							\
+    case in_const:	return 0;					\
+    case in_named:	return get_named_section_flags (in_named_name);	\
+    }									\
+  abort ();								\
 }
 
 /* Switch into a generic section.  */
 #undef TARGET_ASM_NAMED_SECTION
 #define TARGET_ASM_NAMED_SECTION  iris6_asm_named_section
 
-/* ??? Perhaps just include svr4.h in this file?  */
+/* SGI assembler needs all sorts of extra help to do alignment properly.  */
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN iris6_asm_output_align
+#undef ASM_FILE_START
+#define ASM_FILE_START  iris6_asm_file_start
+#undef ASM_FILE_END
+#define ASM_FILE_END	iris6_asm_file_end
+
+#undef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT (32768*8)
 
 /* ??? SGI assembler may core dump when compiling with -g.
    Sometimes as succeeds, but then we get a linker error. (cmds.c in 072.sc)
@@ -317,11 +369,10 @@ do									   \
   {									   \
     if (mips_abi != ABI_32 && mips_abi != ABI_O64)			   \
       {									   \
-	fprintf (STREAM, "%s\n", BSS_SECTION_ASM_OP);			   \
+	bss_section ();							   \
 	mips_declare_object (STREAM, NAME, "", ":\n", 0);		   \
 	ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT));	   \
 	ASM_OUTPUT_SKIP (STREAM, SIZE);					   \
-	fprintf (STREAM, "%s\n", POPSECTION_ASM_OP);			   \
       }									   \
     else								   \
       mips_declare_object (STREAM, NAME, "\n\t.lcomm\t", ",%u\n", (SIZE)); \
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 6a83b0260b3818833430b5e399c9d1f5698e52b1..5cc409c339771bcadc4b8db6d77085b7728a4035 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -29,6 +29,11 @@ Boston, MA 02111-1307, USA.  */
 extern HOST_WIDE_INT	compute_frame_size PARAMS ((HOST_WIDE_INT));
 extern void		mips_asm_file_end PARAMS ((FILE *));
 extern void		mips_asm_file_start PARAMS ((FILE *));
+extern void		iris6_asm_file_start PARAMS ((FILE *));
+extern void		iris6_asm_file_end PARAMS ((FILE *));
+extern void		iris6_asm_output_align PARAMS ((FILE *, unsigned));
+extern const char *	current_section_name PARAMS ((void));
+extern unsigned int	current_section_flags PARAMS ((void));
 extern int		mips_can_use_return_insn PARAMS ((void));
 extern void		mips_declare_object PARAMS ((FILE *, const char *, const char *, const char *, int));
 extern void		mips_expand_epilogue PARAMS ((void));
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 68d9e53dfff1540776a82701e1c0f136d6c46fb7..d9cdcf5d2583ac9a5409cf847c4da2aa55d8fa42 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA.  */
 #include "recog.h"
 #include "toplev.h"
 #include "output.h"
-
 #include "tree.h"
 #include "function.h"
 #include "expr.h"
@@ -50,6 +49,8 @@ Boston, MA 02111-1307, USA.  */
 #include "tm_p.h"
 #include "ggc.h"
 #include "gstab.h"
+#include "hashtab.h"
+#include "debug.h"
 #include "target.h"
 #include "target-def.h"
 
@@ -90,7 +91,6 @@ static void block_move_loop			PARAMS ((rtx, rtx,
 							 int,
 							 rtx, rtx));
 static void block_move_call			PARAMS ((rtx, rtx, rtx));
-static FILE *mips_make_temp_file		PARAMS ((void));
 static rtx mips_add_large_offset_to_sp		PARAMS ((HOST_WIDE_INT,
 							 FILE *));
 static void mips_annotate_frame_insn		PARAMS ((rtx, rtx));
@@ -115,8 +115,18 @@ static void mips_add_gc_roots                   PARAMS ((void));
 static void mips_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 static void mips_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 static enum processor_type mips_parse_cpu       PARAMS ((const char *));
+static void copy_file_data			PARAMS ((FILE *, FILE *));
+#ifdef TARGET_IRIX6
+static void iris6_asm_named_section_1		PARAMS ((const char *,
+							 unsigned int,
+							 unsigned int));
 static void iris6_asm_named_section		PARAMS ((const char *,
 							 unsigned int));
+static int iris_section_align_entry_eq		PARAMS ((const PTR, const PTR));
+static hashval_t iris_section_align_entry_hash	PARAMS ((const PTR));
+static int iris6_section_align_1		PARAMS ((void **, void *));
+#endif
+
 /* Global variables for machine-dependent things.  */
 
 /* Threshold for data being put into the small data/bss area, instead
@@ -276,10 +286,6 @@ struct mips_frame_info current_frame_info;
 /* Zero structure to initialize current_frame_info.  */
 struct mips_frame_info zero_frame_info;
 
-/* Temporary filename used to buffer .text until end of program
-   for -mgpopt.  */
-static char *temp_filename;
-
 /* Pseudo-reg holding the address of the current function when
    generating embedded PIC code.  Created by LEGITIMIZE_ADDRESS, used
    by mips_finalize_pic if it was created.  */
@@ -5786,20 +5792,6 @@ mips_output_external_libcall (file, name)
 }
 #endif
 
-/* Compute a string to use as a temporary file name.  */
-
-static FILE *
-mips_make_temp_file ()
-{
-  FILE *stream;
-
-  temp_filename = make_temp_file (0);
-  stream = fopen (temp_filename, "w+");
-  if (!stream)
-    fatal_io_error ("can't open %s", temp_filename);
-  return stream;
-}
-
 /* Emit a new filename to a stream.  If this is MIPS ECOFF, watch out
    for .file's that start within a function.  If we are smuggling stabs, try to
    put out a MIPS ECOFF file and a stab.  */
@@ -6045,20 +6037,14 @@ mips_asm_file_start (stream)
   if (TARGET_MIPS16)
     fprintf (stream, "\t.set\tmips16\n");
 
-  /* Start a section, so that the first .popsection directive is guaranteed
-     to have a previously defined section to pop back to.  */
-  if (mips_abi != ABI_32 && mips_abi != ABI_O64 && mips_abi != ABI_EABI)
-    fprintf (stream, "\t.section\t.text\n");
-
   /* This code exists so that we can put all externs before all symbol
      references.  This is necessary for the MIPS assembler's global pointer
      optimizations to work.  */
   if (TARGET_FILE_SWITCHING)
     {
       asm_out_data_file = stream;
-      asm_out_text_file = mips_make_temp_file ();
+      asm_out_text_file = tmpfile ();
     }
-
   else
     asm_out_data_file = asm_out_text_file = stream;
 
@@ -6077,10 +6063,8 @@ void
 mips_asm_file_end (file)
      FILE *file;
 {
-  char buffer[8192];
   tree name_tree;
   struct extern_list *p;
-  int len;
 
   if (HALF_PIC_P ())
     {
@@ -6116,23 +6100,30 @@ mips_asm_file_end (file)
   if (TARGET_FILE_SWITCHING)
     {
       fprintf (file, "\n\t.text\n");
-      rewind (asm_out_text_file);
-      if (ferror (asm_out_text_file))
-	fatal_io_error ("can't rewind %s", temp_filename);
+      copy_file_data (file, asm_out_text_file);
+    }
+}
 
-      while ((len = fread (buffer, 1, sizeof (buffer), asm_out_text_file)) > 0)
-	if ((int) fwrite (buffer, 1, len, file) != len)
-	  fatal_io_error ("can't write to %s", asm_file_name);
+static void
+copy_file_data (to, from)
+     FILE *to, *from;
+{
+  char buffer[8192];
+  size_t len;
 
-      if (len < 0)
-	fatal_io_error ("can't read from %s", temp_filename);
+  rewind (from);
+  if (ferror (from))
+    fatal_io_error ("can't rewind temp file");
 
-      if (fclose (asm_out_text_file) != 0)
-	fatal_io_error ("can't close %s", temp_filename);
+  while ((len = fread (buffer, 1, sizeof (buffer), from)) > 0)
+    if (fwrite (buffer, 1, len, to) != len)
+      fatal_io_error ("can't write to output file");
 
-      unlink (temp_filename);
-      free (temp_filename);
-    }
+  if (ferror (from))
+    fatal_io_error ("can't read from temp file");
+
+  if (fclose (from))
+    fatal_io_error ("can't close temp file");
 }
 
 /* Emit either a label, .comm, or .lcomm directive, and mark that the symbol
@@ -9752,43 +9743,6 @@ mips_parse_cpu (cpu_string)
   return cpu;
 }
 
-/* Output assembly to switch to section NAME with attribute FLAGS.  */
-
-static void
-iris6_asm_named_section (name, flags)
-     const char *name;
-     unsigned int flags;
-{
-  unsigned int sh_type, sh_flags, sh_entsize;
-
-  sh_flags = 0;
-  if (!(flags & SECTION_DEBUG))
-    sh_flags |= 2; /* SHF_ALLOC */
-  if (flags & SECTION_WRITE)
-    sh_flags |= 1; /* SHF_WRITE */
-  if (flags & SECTION_CODE)
-    sh_flags |= 4; /* SHF_EXECINSTR */
-  if (flags & SECTION_SMALL)
-    sh_flags |= 0x10000000; /* SHF_MIPS_GPREL */
-  if (strcmp (name, ".debug_frame") == 0)
-    sh_flags |= 0x08000000; /* SHF_MIPS_NOSTRIP */
-
-  if (flags & SECTION_DEBUG)
-    sh_type = 0x7000001e; /* SHT_MIPS_DWARF */
-  else if (flags & SECTION_BSS)
-    sh_type = 8; /* SHT_NOBITS */
-  else
-    sh_type = 1; /* SHT_PROGBITS */
-
-  if (flags & SECTION_CODE)
-    sh_entsize = 4;
-  else
-    sh_entsize = 0;
-
-  fprintf (asm_out_file, "\t.section %s,%u,%u,%u,%u\n",
-	   name, sh_type, sh_flags, sh_entsize, 0);
-}
-
 /* Cover function for UNIQUE_SECTION.  */
 
 void
@@ -9797,8 +9751,9 @@ mips_unique_section (decl, reloc)
      int reloc;
 {
   int len, size, sec;
-  char *name, *string, *prefix;
-  static char *prefixes[4][2] = {
+  const char *name, *prefix;
+  char *string;
+  static const char *prefixes[4][2] = {
     { ".text.", ".gnu.linkonce.t." },
     { ".rodata.", ".gnu.linkonce.r." },
     { ".data.", ".gnu.linkonce.d." },
@@ -9860,3 +9815,164 @@ mips_unique_section (decl, reloc)
 
   DECL_SECTION_NAME (decl) = build_string (len, string);
 }
+
+#ifdef TARGET_IRIX6
+/* Output assembly to switch to section NAME with attribute FLAGS.  */
+
+static void
+iris6_asm_named_section_1 (name, flags, align)
+     const char *name;
+     unsigned int flags;
+     unsigned int align;
+{
+  unsigned int sh_type, sh_flags, sh_entsize;
+
+  sh_flags = 0;
+  if (!(flags & SECTION_DEBUG))
+    sh_flags |= 2; /* SHF_ALLOC */
+  if (flags & SECTION_WRITE)
+    sh_flags |= 1; /* SHF_WRITE */
+  if (flags & SECTION_CODE)
+    sh_flags |= 4; /* SHF_EXECINSTR */
+  if (flags & SECTION_SMALL)
+    sh_flags |= 0x10000000; /* SHF_MIPS_GPREL */
+  if (strcmp (name, ".debug_frame") == 0)
+    sh_flags |= 0x08000000; /* SHF_MIPS_NOSTRIP */
+
+  if (flags & SECTION_DEBUG)
+    sh_type = 0x7000001e; /* SHT_MIPS_DWARF */
+  else if (flags & SECTION_BSS)
+    sh_type = 8; /* SHT_NOBITS */
+  else
+    sh_type = 1; /* SHT_PROGBITS */
+
+  if (flags & SECTION_CODE)
+    sh_entsize = 4;
+  else
+    sh_entsize = 0;
+
+  fprintf (asm_out_file, "\t.section %s,%#x,%#x,%u,%u\n",
+	   name, sh_type, sh_flags, sh_entsize, align);
+}
+
+static void
+iris6_asm_named_section (name, flags)
+     const char *name;
+     unsigned int flags;
+{
+  if (TARGET_FILE_SWITCHING && (flags & SECTION_CODE))
+    asm_out_file = asm_out_text_file;
+  iris6_asm_named_section_1 (name, flags, 0);
+}
+
+/* In addition to emitting a .align directive, record the maximum
+   alignment requested for the current section.  */
+
+struct iris_section_align_entry
+{
+  const char *name;
+  unsigned int log;
+  unsigned int flags;
+};
+
+static htab_t iris_section_align_htab;
+static FILE *iris_orig_asm_out_file;
+
+static int
+iris_section_align_entry_eq (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  const struct iris_section_align_entry *old = p1;
+  const char *new = p2;
+
+  return strcmp (old->name, new) == 0;
+}
+
+static hashval_t
+iris_section_align_entry_hash (p)
+     const PTR p;
+{
+  const struct iris_section_align_entry *old = p;
+  return htab_hash_string (old->name);
+}
+
+void
+iris6_asm_output_align (file, log)
+     FILE *file;
+     unsigned int log;
+{
+  const char *section = current_section_name ();
+  struct iris_section_align_entry **slot, *entry;
+
+  if (! section)
+    abort ();
+
+  slot = (struct iris_section_align_entry **)
+    htab_find_slot_with_hash (iris_section_align_htab, section,
+			      htab_hash_string (section), INSERT);
+  entry = *slot;
+  if (! entry)
+    {
+      entry = (struct iris_section_align_entry *)
+	xmalloc (sizeof (struct iris_section_align_entry));
+      *slot = entry;
+      entry->name = section;
+      entry->log = log;
+      entry->flags = current_section_flags ();
+    }
+  else if (entry->log < log)
+    entry->log = log;
+
+  fprintf (file, "\t.align\t%u\n", log);
+}
+
+/* The Iris assembler does not record alignment from .align directives,
+   but takes it from the first .section directive seen.  Play yet more
+   file switching games so that we can emit a .section directive at the
+   beginning of the file with the proper alignment attached.  */
+   
+void
+iris6_asm_file_start (stream)
+     FILE *stream;
+{
+  mips_asm_file_start (stream);
+
+  iris_orig_asm_out_file = asm_out_file;
+  stream = tmpfile ();
+  asm_out_file = stream;
+  asm_out_data_file = stream;
+  if (! TARGET_FILE_SWITCHING)
+    asm_out_text_file = stream;
+
+  iris_section_align_htab = htab_create (31, iris_section_align_entry_hash,
+					 iris_section_align_entry_eq, NULL);
+}
+
+static int
+iris6_section_align_1 (slot, data)
+     void **slot;
+     void *data ATTRIBUTE_UNUSED;
+{
+  const struct iris_section_align_entry *entry
+    = *(const struct iris_section_align_entry **) slot;
+
+  iris6_asm_named_section_1 (entry->name, entry->flags, 1 << entry->log);
+  return 1;
+}
+
+void
+iris6_asm_file_end (stream)
+     FILE *stream;
+{
+  /* Emit section directives with the proper alignment at the top of the
+     real output file.  */
+  asm_out_file = iris_orig_asm_out_file;
+  htab_traverse (iris_section_align_htab, iris6_section_align_1, NULL);
+
+  /* Copy the data emitted to the temp file to the real output file.  */
+  copy_file_data (asm_out_file, stream);
+
+  mips_asm_file_end (stream);
+}
+#endif /* TARGET_IRIX6 */