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: MIPS R_MIPS_HI16 relocs


On Wed, Dec 19, 2001 at 06:46:34PM +0000, Andrew Haley wrote:
> 
> 	* elf32-mips.c (mips_elf_calculate_relocation): Allow -ve values
> 	in R_MIPS_HI16 relocs.

Looks OK to me.  Give Eric a chance to OK it though.  ;)  I'm piping up
here, because I was looking at _bfd_mips_elf_lo16_reloc and thought it
confusing enough to need different comments and some rewriting.  At
least I think it's simpler this way, but I'll leave Eric to judge that.
One's own code is nearly always simpler and better.. :-)

	* elf32-mips.c (_bfd_mips_elf_lo16_reloc): Simplify, and perform
	sign extension adjustments without conditionals.

Index: bfd/elf32-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mips.c,v
retrieving revision 1.133
diff -u -p -r1.133 elf32-mips.c
--- elf32-mips.c	2001/12/18 17:59:58	1.133
+++ elf32-mips.c	2001/12/21 01:12:41
@@ -1786,23 +1786,23 @@ _bfd_mips_elf_lo16_reloc (abfd,
 	     to know anything about the LO16 itself, except where to
 	     find the low 16 bits of the addend needed by the LO16.  */
 	  insn = bfd_get_32 (abfd, l->addr);
-	  vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
-		   & 0xffff);
+	  vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+
+	  /* The low order 16 bits are always treated as a signed
+	     value.  */
+	  vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000;
 	  val = ((insn & 0xffff) << 16) + vallo;
 	  val += l->addend;
 
-	  /* The low order 16 bits are always treated as a signed
-	     value.  Therefore, a negative value in the low order bits
-	     requires an adjustment in the high order bits.  We need
-	     to make this adjustment in two ways: once for the bits we
-	     took from the data, and once for the bits we are putting
-	     back in to the data.  */
-	  if ((vallo & 0x8000) != 0)
-	    val -= 0x10000;
-	  if ((val & 0x8000) != 0)
-	    val += 0x10000;
+	  /* At this point, "val" has the value of the combined HI/LO
+	     pair.  If the low order 16 bits (which will be used for
+	     the LO16 insn) are negative, then we will need an
+	     adjustment for the high order 16 bits.  */
+	  val += 0x8000;
+	  val = (val >> 16) & 0xffff;
 
-	  insn = (insn &~ (bfd_vma) 0xffff) | ((val >> 16) & 0xffff);
+	  insn &= ~ (bfd_vma) 0xffff;
+	  insn |= val;
 	  bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
 
 	  if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)


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