rs_fill_nop and md_generate_nops

Make rs_fill_nop behave like rs_fill in using a repeat count
(fr_offset) to emit fr_var length repeated nop patterns.  Besides
being more elegant, this reduces memory required for large .nops
directives.

	* as.h (rs_fill_nop): Update comment.
	* config/tc-i386.c (i386_generate_nops): Handle rs_fill_nop as
	for rs_align_code.
	* config/tc-i386.h (MAX_MEM_FOR_RS_SPACE_NOP): Define.
	* listing.c (calc_hex): Handle rs_fill_nop as for rs_fill.
	* read.c (MAX_MEM_FOR_RS_SPACE_NOP): Define.
	(s_nops): Use MAX_MEM_FOR_RS_SPACE_NOP setting up frag.
	* write.c (write_contents): Call md_generate_nops for rs_fill_nop
	before the fr_fix part is written, so that rs_fill_nop can be
	handled as for rs_fill.
diff --git a/gas/as.h b/gas/as.h
index 826d88d..4b5f78b 100644
--- a/gas/as.h
+++ b/gas/as.h
@@ -247,9 +247,7 @@
      1 constant byte: no-op fill control byte.  */
   rs_space_nop,
 
-  /* Similar to rs_fill.  It is used to implement .nops directive.
-     When listings are enabled, fr_opcode gets the buffer assigned, once
-     that's available.  */
+  /* Similar to rs_fill.  It is used to implement .nops directive.  */
   rs_fill_nop,
 
   /* A DWARF leb128 value; only ELF uses this.  The subtype is 0 for
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 1669d43..73d552e 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1769,7 +1769,7 @@
       count -= non_repeat;
     }
 
-  if (fragP->fr_type == rs_align_code)
+  if (fragP->fr_type != rs_machine_dependent)
     {
       /* Set up the frag so that everything we have emitted so far is
 	 included in fr_fix.  The repeating larger nop only needs to
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 2119d71..9137d84 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -390,6 +390,7 @@
    Yes, the branch might be one byte longer in CODE_16BIT but then the
    largest nop is smaller.  */
 #define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 5 + 2 * 15 - 1)
+#define MAX_MEM_FOR_RS_SPACE_NOP MAX_MEM_FOR_RS_ALIGN_CODE
 
 /* We want .cfi_* pseudo-ops for generating unwind info.  */
 #define TARGET_USE_CFIPOP 1
diff --git a/gas/listing.c b/gas/listing.c
index c47a43d..0d1f4e8 100644
--- a/gas/listing.c
+++ b/gas/listing.c
@@ -826,7 +826,7 @@
 	  data_buffer_size += 2;
 	  octet_in_frag++;
 	}
-      if (frag_ptr->fr_type == rs_fill)
+      if (frag_ptr->fr_type == rs_fill || frag_ptr->fr_type == rs_fill_nop)
 	{
 	  unsigned int var_rep_max = octet_in_frag;
 	  unsigned int var_rep_idx = octet_in_frag;
@@ -851,27 +851,6 @@
 		var_rep_idx = var_rep_max;
 	    }
 	}
-      else if (frag_ptr->fr_type == rs_fill_nop && frag_ptr->fr_opcode)
-	{
-	  /* Print as many bytes from fr_opcode as is sensible.  */
-	  octet_in_frag = 0;
-	  while (octet_in_frag < (unsigned int) frag_ptr->fr_offset
-		 && data_buffer_size < MAX_BYTES - 3)
-	    {
-	      if (address == ~(unsigned int) 0)
-		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
-
-	      sprintf (data_buffer + data_buffer_size,
-		       "%02X",
-		       frag_ptr->fr_opcode[octet_in_frag] & 0xff);
-	      data_buffer_size += 2;
-
-	      octet_in_frag++;
-	    }
-
-	  free (frag_ptr->fr_opcode);
-	  frag_ptr->fr_opcode = NULL;
-	}
 
       frag_ptr = frag_ptr->fr_next;
     }
diff --git a/gas/read.c b/gas/read.c
index de26d4b..832a196 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -3617,6 +3617,13 @@
 	     && frag_off + frag_now_fix () < start_off + exp.X_add_number);
 }
 
+/* Use this to specify the amount of memory allocated for representing
+   the nops.  Needs to be large enough to hold any fixed size prologue
+   plus the replicating portion.  */
+#ifndef MAX_MEM_FOR_RS_SPACE_NOP
+# define MAX_MEM_FOR_RS_SPACE_NOP 1
+#endif
+
 void
 s_nops (int ignore ATTRIBUTE_UNUSED)
 {
@@ -3665,8 +3672,7 @@
   /* Store the no-op instruction control byte in the first byte of frag.  */
   char *p;
   symbolS *sym = make_expr_symbol (&exp);
-  p = frag_var (rs_space_nop, 1, 1, (relax_substateT) 0,
-		sym, (offsetT) 0, (char *) 0);
+  p = frag_var (rs_space_nop, MAX_MEM_FOR_RS_SPACE_NOP, 1, 0, sym, 0, NULL);
   *p = val.X_add_number;
 }
 
diff --git a/gas/write.c b/gas/write.c
index c725841..8ccd996 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -1653,6 +1653,19 @@
       offsetT count;
 
       gas_assert (f->fr_type == rs_fill || f->fr_type == rs_fill_nop);
+
+      count = f->fr_offset;
+      fill_literal = f->fr_literal + f->fr_fix;
+      if (f->fr_type == rs_fill_nop && count > 0)
+	{
+	  md_generate_nops (f, fill_literal, count, *fill_literal);
+	  /* md_generate_nops updates fr_fix and fr_var.  */
+	  f->fr_offset = (f->fr_next->fr_address - f->fr_address
+			  - f->fr_fix) / f->fr_var;
+	  count = f->fr_offset;
+	  fill_literal = f->fr_literal + f->fr_fix;
+	}
+
       if (f->fr_fix)
 	{
 	  x = bfd_set_section_contents (stdoutput, sec,
@@ -1671,39 +1684,6 @@
 	}
 
       fill_size = f->fr_var;
-      count = f->fr_offset;
-      fill_literal = f->fr_literal + f->fr_fix;
-
-      if (f->fr_type == rs_fill_nop)
-	{
-	  gas_assert (count >= 0 && fill_size == 1);
-	  if (count > 0)
-	    {
-	      char *buf = xmalloc (count);
-	      md_generate_nops (f, buf, count, *fill_literal);
-	      x = bfd_set_section_contents
-		(stdoutput, sec, buf, (file_ptr) offset,
-		 (bfd_size_type) count);
-	      if (!x)
-		as_fatal (ngettext ("can't fill %ld byte "
-				    "in section %s of %s: '%s'",
-				    "can't fill %ld bytes "
-				    "in section %s of %s: '%s'",
-				    (long) count),
-			  (long) count,
-			  bfd_section_name (sec),
-			  bfd_get_filename (stdoutput),
-			  bfd_errmsg (bfd_get_error ()));
-	      offset += count;
-#ifndef NO_LISTING
-	      if (listing & LISTING_LISTING)
-		f->fr_opcode = buf;
-	      else
-#endif
-		free (buf);
-	    }
-	  continue;
-	}
 
       gas_assert (count >= 0);
       if (fill_size && count)