This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

powerpc padding nops


This patch performs a simple optimization for powerpc nop padding,
replacing a large (>4 by default) number of nops with a branch.

	* config/tc-ppc.c (nop_limit): New var.
	(OPTION_NOPS): Define.
	(md_longopts): Add --nops.
	(md_parse_option): Handle it.
	(md_show_usage): Publish.
	(ppc_handle_align): Pad with a branch followed by nops if more
	than nop_limit nops.

Index: gas/config/tc-ppc.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ppc.c,v
retrieving revision 1.174
diff -u -p -r1.174 tc-ppc.c
--- gas/config/tc-ppc.c	29 Jul 2010 07:48:43 -0000	1.174
+++ gas/config/tc-ppc.c	7 Oct 2010 05:11:28 -0000
@@ -180,6 +180,10 @@ const char ppc_symbol_chars[] = "%[";
 /* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
 int ppc_cie_data_alignment;
 
+/* More than this number of nops in an alignment op gets a branch
+   instead.  */
+unsigned long nop_limit = 4;
+
 /* The type of processor we are assembling for.  This is one or more
    of the PPC_OPCODE flags defined in opcode/ppc.h.  */
 ppc_cpu_t ppc_cpu = 0;
@@ -1018,7 +1022,9 @@ const char *const md_shortopts = "b:l:us
 #else
 const char *const md_shortopts = "um:";
 #endif
+#define OPTION_NOPS (OPTION_MD_BASE + 0)
 const struct option md_longopts[] = {
+  {"nops", required_argument, NULL, OPTION_NOPS},
   {NULL, no_argument, NULL, 0}
 };
 const size_t md_longopts_size = sizeof (md_longopts);
@@ -1172,6 +1178,15 @@ md_parse_option (int c, char *arg)
       break;
 #endif
 
+    case OPTION_NOPS:
+      {
+	char *end;
+	nop_limit = strtoul (optarg, &end, 0);
+	if (*end)
+	  as_bad (_("--nops needs a numeric argument"));
+      }
+      break;
+      
     default:
       return 0;
     }
@@ -1238,6 +1253,8 @@ PowerPC options:\n\
 -V                      print assembler version number\n\
 -Qy, -Qn                ignored\n"));
 #endif
+  fprintf (stream, _("\
+-nops=count             when aligning, more than COUNT nops uses a branch\n"));
 }
 
 /* Set ppc_cpu if it is not already set.  */
@@ -5748,6 +5765,31 @@ ppc_handle_align (struct frag *fragP)
       char *dest = fragP->fr_literal + fragP->fr_fix;
 
       fragP->fr_var = 4;
+
+      if (count > 4 * nop_limit && count < 0x2000000)
+	{
+	  struct frag *rest;
+
+	  /* Make a branch, then follow with nops.  Insert another
+	     frag to handle the nops.  */
+	  md_number_to_chars (dest, 0x48000000 + count, 4);
+	  count -= 4;
+	  if (count == 0)
+	    return;
+
+	  rest = xmalloc (SIZEOF_STRUCT_FRAG + 4);
+	  memcpy (rest, fragP, SIZEOF_STRUCT_FRAG);
+	  fragP->fr_next = rest;
+	  fragP = rest;
+	  rest->fr_address += rest->fr_fix + 4;
+	  rest->fr_fix = 0;
+	  /* If we leave the next frag as rs_align_code we'll come here
+	     again, resulting in a bunch of branches rather than a
+	     branch followed by nops.  */
+	  rest->fr_type = rs_align;
+	  dest = rest->fr_literal;
+	}
+
       md_number_to_chars (dest, 0x60000000, 4);
 
       if ((ppc_cpu & PPC_OPCODE_POWER6) != 0

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]