This is the mail archive of the binutils@sources.redhat.com 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]

d10v: swapping insns requires swapping relocs


The d10v assembler may sometimes swap instructions in a package
without adjusting the relocations.  Therefore, it may happen that a
10_PCREL_[LR] relocation ends up being applied to the wrong container.
This patch is supposed to fix all such situations, but I'm not
positive fx always points to the right fix-ups.  There were no
regressions in the testsuite, FWIW.  I'd appreciate a careful look at
these patches from someone who better understands what's going on.  Ok
to install?

Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* config/tc-d10v.c (write_2_short): Mark L reloc insn when
	L and R are swapped.

Index: gas/config/tc-d10v.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-d10v.c,v
retrieving revision 1.19
diff -u -p -r1.19 tc-d10v.c
--- gas/config/tc-d10v.c 2001/11/15 21:28:55 1.19
+++ gas/config/tc-d10v.c 2001/11/29 17:16:02
@@ -767,6 +767,7 @@ write_2_short (opcode1, insn1, opcode2, 
   unsigned long insn;
   char *f;
   int i, j, where;
+  int swapped = 0;
 
   if ((exec_type != PACK_PARALLEL)
       && ((opcode1->exec_type & PARONLY) || (opcode2->exec_type & PARONLY)))
@@ -790,9 +791,15 @@ write_2_short (opcode1, insn1, opcode2, 
 	{
 	  /* Parallel.  */
 	  if (opcode1->unit == IU)
-	    insn = FM00 | (insn2 << 15) | insn1;
+	    {
+	      swapped = 1;
+	      insn = FM00 | (insn2 << 15) | insn1;
+	    }
 	  else if (opcode2->unit == MU)
-	    insn = FM00 | (insn2 << 15) | insn1;
+	    {
+	      swapped = 1;
+	      insn = FM00 | (insn2 << 15) | insn1;
+	    }
 	  else
 	    {
 	      insn = FM00 | (insn1 << 15) | insn2;
@@ -801,8 +808,11 @@ write_2_short (opcode1, insn1, opcode2, 
 	    }
 	}
       else if (opcode1->unit == IU)
-	/* Reverse sequential with IU opcode1 on right and done first.  */
-	insn = FM10 | (insn2 << 15) | insn1;
+	{
+	  /* Reverse sequential with IU opcode1 on right and done first.  */
+	  insn = FM10 | (insn2 << 15) | insn1;
+	  swapped = 1;
+	}
       else
 	{
 	  /* Sequential with non-IU opcode1 on left and done first.  */
@@ -822,6 +832,7 @@ write_2_short (opcode1, insn1, opcode2, 
 	    as_fatal (_("Two IU instructions may not be executed in parallel"));
 	  if (!flag_warn_suppress_instructionswap)
 	    as_warn (_("Swapping instruction order"));
+	  swapped = 1;
 	  insn = FM00 | (insn2 << 15) | insn1;
 	}
       else if (opcode2->unit == MU)
@@ -830,6 +841,7 @@ write_2_short (opcode1, insn1, opcode2, 
 	    as_fatal (_("Two MU instructions may not be executed in parallel"));
 	  if (!flag_warn_suppress_instructionswap)
 	    as_warn (_("Swapping instruction order"));
+	  swapped = 1;
 	  insn = FM00 | (insn2 << 15) | insn1;
 	}
       else
@@ -847,6 +859,7 @@ write_2_short (opcode1, insn1, opcode2, 
 	{
 	  if (!flag_warn_suppress_instructionswap)
 	    as_warn (_("Swapping instruction order"));
+	  swapped = 1;
 	  insn = FM10 | (insn2 << 15) | insn1;
 	}
       else
@@ -864,6 +877,7 @@ write_2_short (opcode1, insn1, opcode2, 
 	{
 	  if (!flag_warn_suppress_instructionswap)
 	    as_warn (_("Swapping instruction order"));
+	  swapped = 1;
 	  insn = FM01 | (insn2 << 15) | insn1;
 	}
       else
@@ -882,12 +896,7 @@ write_2_short (opcode1, insn1, opcode2, 
   number_to_chars_bigendian (f, insn, 4);
 
   /* Process fixup chains.
-     Note that the packing code above advanced fx conditionally.
-     dlindsay@cygnus.com:  There's something subtle going on here involving
-	_dummy_first_bfd_reloc_code_real.  This is related to the
-	difference between BFD_RELOC_D10V_10_PCREL_R and _L, ie whether
-	a fixup is done in the L or R container.  A bug in this code
-	can pass Plum Hall fine, yet still affect hand-written assembler.  */
+     Note that the packing code above advanced fx conditionally.  */
 
   for (j = 0; j < 2; j++)
     {
@@ -899,7 +908,14 @@ write_2_short (opcode1, insn1, opcode2, 
 	      if (fx->fix[i].size == 2)
 		where += 2;
 
-	      if ((fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R) && (j == 0))
+	      /* A BFD_RELOC_D10V_10_PCREL_R relocation applied to the
+                 instruction in the L container has to be adjusted to
+                 BDF_RELOC_D10V_10_PCREL_L.  When processing the L
+                 container, j == 0, unless we swapped the containers,
+                 in which case the L instruction gets j == 1, i.e.,
+                 the L container gets j == swapped.  */
+	      if (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R
+		  && j == swapped)
 		fx->fix[i].operand |= 1024;
 
 	      if (fx->fix[i].reloc == BFD_RELOC_D10V_18)

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

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