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]

Re: d10v: swapping insns requires swapping relocs


On Dec  3, 2001, Nick Clifton <nickc@cambridge.redhat.com> wrote:

> It might be better (and less prone to bit rot in the future) if
> instead of setting a 'swapped' flag in all of the places where
> instruction swapping occurs, you alter the code that tests to see if
> swapping has occurred:

Good idea!  Upon further investigation, I've understood what was going
on with fxs, so I'm pretty confident this patch is correct, while the
previous patch would fail to mark insn2's operands if insns happened
to be swapped.  Ok to install?

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

	* config/tc-d10v.c (write_2_short): Don't skip dummy fixups, so
	that we can tell which operand refers to the insn put in the L
	container and mark it as such, so that the relocation type can be
	adjusted.

Index: gas/config/tc-d10v.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-d10v.c,v
retrieving revision 1.22
diff -u -p -r1.22 tc-d10v.c
--- gas/config/tc-d10v.c 2001/12/04 10:07:03 1.22
+++ gas/config/tc-d10v.c 2001/12/04 12:50:08
@@ -799,22 +799,14 @@ write_2_short (opcode1, insn1, opcode2, 
 	  else if (opcode2->unit == MU)
 	    insn = FM00 | (insn2 << 15) | insn1;
 	  else
-	    {
-	      insn = FM00 | (insn1 << 15) | insn2;
-	      /* Advance over dummy fixup since packed insn1 in L.  */
-	      fx = fx->next;
-	    }
+	    insn = FM00 | (insn1 << 15) | insn2;
 	}
       else if (opcode1->unit == IU)
 	/* Reverse sequential with IU opcode1 on right and done first.  */
 	insn = FM10 | (insn2 << 15) | insn1;
       else
-	{
-	  /* Sequential with non-IU opcode1 on left and done first.  */
-	  insn = FM01 | (insn1 << 15) | insn2;
-	  /* Advance over dummy fixup since packed insn1 in L.  */
-	  fx = fx->next;
-	}
+	/* Sequential with non-IU opcode1 on left and done first.  */
+	insn = FM01 | (insn1 << 15) | insn2;
       break;
 
     case PACK_PARALLEL:
@@ -838,11 +830,7 @@ write_2_short (opcode1, insn1, opcode2, 
 	  insn = FM00 | (insn2 << 15) | insn1;
 	}
       else
-	{
-	  insn = FM00 | (insn1 << 15) | insn2;
-	  /* Advance over dummy fixup since packed insn1 in L.  */
-	  fx = fx->next;
-	}
+	insn = FM00 | (insn1 << 15) | insn2;
       break;
 
     case PACK_LEFT_RIGHT:
@@ -858,8 +846,6 @@ write_2_short (opcode1, insn1, opcode2, 
 	as_fatal (_("IU instruction may not be in the left container"));
       if (opcode1->exec_type & ALONE)
 	as_warn (_("Instruction in R container is squashed by flow control instruction in L container."));
-      /* Advance over dummy fixup.  */
-      fx = fx->next;
       break;
 
     case PACK_RIGHT_LEFT:
@@ -875,8 +861,6 @@ write_2_short (opcode1, insn1, opcode2, 
 	as_fatal (_("MU instruction may not be in the right container"));
       if (opcode2->exec_type & ALONE)
 	as_warn (_("Instruction in R container is squashed by flow control instruction in L container."));
-      /* Advance over dummy fixup.  */
-      fx = fx->next;
       break;
 
     default:
@@ -886,13 +870,8 @@ write_2_short (opcode1, insn1, opcode2, 
   f = frag_more (4);
   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.  */
+  /* Process fixup chains.  fx refers to insn2 when j == 0, and to
+     insn1 when j == 1.  Yes, it's reversed.  */
 
   for (j = 0; j < 2; j++)
     {
@@ -904,7 +883,18 @@ 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))
+	      if (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R
+		  /* 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
+		     j==0, we're processing insn2's operands, so we
+		     want to mark the operand if insn2 is *not* in the
+		     R container.  When j==1, we're processing insn1's
+		     operands, so we want to mark the operand if insn2
+		     *is* in the R container.  Note that, if two
+		     instructions are identical, we're never going to
+		     swap them, so the test is safe.  */
+		  && j == ((insn & 0x7fff) == insn2))
 		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]