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]

Re: [PATCH] Fix handling of R_MIPS_PC16 relocations


Thiemo Seufer wrote:
[snip]
> 	/bfd/ChangeLog (elf_mips_howto_table): Fix rightshift for R_MIPS_PC16.
> 	(mips_reloc_map): Map R_MIPS_PC16 to the BFD_RELOC_16_PCREL_S2.
> 	(mips_elf_calculate_relocation): Fix handling of R_MIPS_PC16.
> 	(_bfd_mips_elf_relocate_section): Likewise.

This patch was wrong. The R_MIPS_PC16 relocation actually spans an
offset of only 16 bit while the hardware (and internal branches
without a reloc) can do 18 bit. I have no explanation why this was
defined this way. The appended patch adds handling for R_MIPS_PC16
to gas and bfd. Tested for mips64-linux and mips-elf.


Thiemo


2001-09-07  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>

	/bfd/ChangeLog
	* elf32-mips.c (mips_elf_calculate_relocation): Fix overflow handling
	of R_MIPS_PC16.

	/gas/ChangeLog
	* config/tc-mips.c (append_insn): Handle BFD_RELOC_16_PCREL.
	(macro_build): Use BFD_RELOC_16_PCREL_S2 only for embedded
	PIC, BFD_RELOC_16_PCREL for the rest.
	(mips_ip): Likewise.
        (md_pcrel_from): return the right offset for the differently shifted
        pcrel relocs.
	(md_apply_fix): Handle BFD_RELOC_16_PCREL.

	/gas/testsuite/ChangeLog
	* gas/mips/beq.d: Check branches to external labels.
	* gas/mips/beq.s: Likewise.
	* gas/mips/bge.d: Likewise.
	* gas/mips/bge.s: Likewise.
	* gas/mips/bgeu.d: Likewise.
	* gas/mips/bgeu.s: Likewise.
	* gas/mips/blt.d: Likewise.
	* gas/mips/blt.s: Likewise.
	* gas/mips/bltu.d: Likewise.
	* gas/mips/bltu.s: Likewise.
	* gas/mips/elempic.d: Switch from R_MIPS_GNU_REL16_S2 to R_MIPS_PC16.
	* gas/mips/empic.d: Likewise.
	* gas/mips/empic.s: Likewise.
	* gas/mips/telempic.d: Likewise.
	* gas/mips/tempic.d: Likewise.


diff -BurpNX /bigdisk/src/binutils-exclude src-orig/bfd/elf32-mips.c src/bfd/elf32-mips.c
--- src-orig/bfd/elf32-mips.c	Fri Aug 31 21:59:55 2001
+++ src/bfd/elf32-mips.c	Thu Sep  6 21:11:29 2001
@@ -6488,8 +6488,8 @@ mips_elf_calculate_relocation (abfd,
 
     case R_MIPS_PC16:
       value = mips_elf_sign_extend (addend, 16) + symbol - p;
-      value = (bfd_vma) ((bfd_signed_vma) value / 4);
       overflowed_p = mips_elf_overflow_p (value, 16);
+      value = (bfd_vma) ((bfd_signed_vma) value / 4);
       break;
 
     case R_MIPS_GOT_HI16:
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/config/tc-mips.c src/gas/config/tc-mips.c
--- src-orig/gas/config/tc-mips.c	Fri Aug 31 22:00:08 2001
+++ src/gas/config/tc-mips.c	Thu Sep  6 21:58:05 2001
@@ -1898,6 +1978,10 @@ append_insn (place, ip, address_expr, re
 		 | ((address_expr->X_add_number & 0x3fffc) >> 2));
 	      break;
 
+	    case BFD_RELOC_16_PCREL:
+	      ip->insn_opcode |= (address_expr->X_add_number >> 2) & 0xffff;
+	      break;
+
 	    case BFD_RELOC_16_PCREL_S2:
 	      goto need_reloc;
 
@@ -1914,7 +1998,8 @@ append_insn (place, ip, address_expr, re
 	    {
 	      fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
 				  address_expr,
-				  reloc_type == BFD_RELOC_16_PCREL_S2,
+				  (reloc_type == BFD_RELOC_16_PCREL
+				   || reloc_type == BFD_RELOC_16_PCREL_S2),
				  reloc_type);
 	      if (unmatched_hi)
 		{
@@ -2699,7 +2804,10 @@ macro_build (place, counter, ep, name, f
 	      ep = NULL;
 	    }
 	  else
-	    r = BFD_RELOC_16_PCREL_S2;
+	    if (mips_pic == EMBEDDED_PIC)
+	      r = BFD_RELOC_16_PCREL_S2;
+	    else
+	      r = BFD_RELOC_16_PCREL;
 	  continue;
 
 	case 'a':
@@ -7791,7 +8131,10 @@ mips_ip (str, ip)
 	      continue;
 
 	    case 'p':		/* pc relative offset */
-	      offset_reloc = BFD_RELOC_16_PCREL_S2;
+	      if (mips_pic == EMBEDDED_PIC)
+		offset_reloc = BFD_RELOC_16_PCREL_S2;
+	      else
+		offset_reloc = BFD_RELOC_16_PCREL;
 	      my_getExpression (&offset_expr, s);
 	      s = expr_end;
 	      continue;
@@ -9427,9 +9836,16 @@ md_pcrel_from (fixP)
       && fixP->fx_addsy != (symbolS *) NULL
       && ! S_IS_DEFINED (fixP->fx_addsy))
     {
-      /* This makes a branch to an undefined symbol be a branch to the
-	 current location.  */
-      return 4;
+      if (mips_pic == EMBEDDED_PIC)
+	{
+	  /* This makes a branch to an undefined symbol be a branch to the
+	     current location.  */
+	  return 4;
+	}
+      else
+	{
+	  return 1;
+	}
     }
 
   /* return the address of the delay slot */
@@ -9666,7 +10102,8 @@ md_apply_fix (fixP, valueP)
 	  /* BFD's REL handling, for MIPS, is _very_ weird.
 	     This gives the right results, but it can't possibly
 	     be the way things are supposed to work.  */
-	  if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
+	  if ((fixP->fx_r_type != BFD_RELOC_16_PCREL
+	       && fixP->fx_r_type != BFD_RELOC_16_PCREL_S2)
 	      || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
 	    value += fixP->fx_frag->fr_address + fixP->fx_where;
 	}
@@ -9812,15 +10268,18 @@ md_apply_fix (fixP, valueP)
       break;
 
     case BFD_RELOC_16_PCREL_S2:
+      if ((value & 0x3) != 0)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("Branch to odd address (%lx)"), (long) value);
+
+      /* Fall through.  */
+
+    case BFD_RELOC_16_PCREL:
       /*
        * We need to save the bits in the instruction since fixup_segment()
        * might be deleting the relocation entry (i.e., a branch within
        * the current segment).
        */
-      if ((value & 0x3) != 0)
-	as_bad_where (fixP->fx_file, fixP->fx_line,
-		      _("Branch to odd address (%lx)"), (long) value);
-
       if (!fixP->fx_done && value != 0)
 	break;
       /* If 'value' is zero, the remaining reloc code won't actually
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/beq.d src/gas/testsuite/gas/mips/beq.d
--- src-orig/gas/testsuite/gas/mips/beq.d	Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/beq.d	Fri Aug 31 23:01:41 2001
@@ -37,4 +37,10 @@ Disassembly of section .text:
 0+2006c <[^>]*> nop
 0+20070 <[^>]*> jal	0+0000 <text_label>
 [ 	]*20070: (MIPS_JMP|JMPADDR|R_MIPS_26)	.text
+0+20074 <[^>]*> nop
+0+20078 <[^>]*> b	0+20078 <text_label\+0x20078>
+[ 	]*20078: R_MIPS_PC16	external_label
+0+2007c <[^>]*> nop
+0+20080 <[^>]*> bal	0+20080 <text_label\+0x20080>
+[ 	]*20080: R_MIPS_PC16	external_label
 	...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/beq.s src/gas/testsuite/gas/mips/beq.s
--- src-orig/gas/testsuite/gas/mips/beq.s	Mon May  3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/beq.s	Fri Aug 31 23:01:41 2001
@@ -22,7 +22,9 @@ text_label:	
 	b	text_label
 	bal	text_label
 
+# Branch to an external label.
+	b	external_label
+	bal	external_label
+
 # Round to a 16 byte boundary, for ease in testing multiple targets.
-	nop
-	nop
 	nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bge.d src/gas/testsuite/gas/mips/bge.d
--- src-orig/gas/testsuite/gas/mips/bge.d	Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/bge.d	Fri Aug 31 23:01:41 2001
@@ -50,4 +50,20 @@ Disassembly of section .text:
 0+00a4 <[^>]*> nop
 0+00a8 <[^>]*> slt	at,a1,a0
 0+00ac <[^>]*> bnezl	at,0+0000 <text_label>
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> slt	at,a0,a1
+0+00b8 <[^>]*> beqz	at,000000b8 <text_label\+0xb8>
+[ 	]*b8: R_MIPS_PC16	external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> slt	at,a1,a0
+0+00c4 <[^>]*> bnez	at,000000c4 <text_label\+0xc4>
+[ 	]*c4: R_MIPS_PC16	external_label
+0+00c8 <[^>]*> nop
+0+00cc <[^>]*> slt	at,a0,a1
+0+00d0 <[^>]*> beqzl	at,000000d0 <text_label\+0xd0>
+[ 	]*d0: R_MIPS_PC16	external_label
+0+00d4 <[^>]*> nop
+0+00d8 <[^>]*> slt	at,a1,a0
+0+00dc <[^>]*> bnezl	at,000000dc <text_label\+0xdc>
+[ 	]*dc: R_MIPS_PC16	external_label
 	...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bge.s src/gas/testsuite/gas/mips/bge.s
--- src-orig/gas/testsuite/gas/mips/bge.s	Mon May  3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/bge.s	Fri Aug 31 23:01:41 2001
@@ -24,6 +24,12 @@ text_label:	
 	bgel	$4,$5,text_label
 	bgtl	$4,$5,text_label
 
+# Branch to an external label.
+	bge	$4,$5,external_label
+	bgt	$4,$5,external_label
+	bgel	$4,$5,external_label
+	bgtl	$4,$5,external_label
+
 # Round to a 16 byte boundary, for ease in testing multiple targets.
 	nop
 	nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bgeu.d src/gas/testsuite/gas/mips/bgeu.d
--- src-orig/gas/testsuite/gas/mips/bgeu.d	Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/bgeu.d	Fri Aug 31 23:01:41 2001
@@ -44,4 +44,20 @@ Disassembly of section .text:
 0+008c <[^>]*> nop
 0+0090 <[^>]*> sltu	at,a1,a0
 0+0094 <[^>]*> bnezl	at,0+0000 <text_label>
+0+0098 <[^>]*> nop
+0+009c <[^>]*> sltu	at,a0,a1
+0+00a0 <[^>]*> beqz	at,000000a0 <text_label\+0xa0>
+[ 	]*a0: R_MIPS_PC16	external_label
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> sltu	at,a1,a0
+0+00ac <[^>]*> bnez	at,000000ac <text_label\+0xac>
+[ 	]*ac: R_MIPS_PC16	external_label
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> sltu	at,a0,a1
+0+00b8 <[^>]*> beqzl	at,000000b8 <text_label\+0xb8>
+[ 	]*b8: R_MIPS_PC16	external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> sltu	at,a1,a0
+0+00c4 <[^>]*> bnezl	at,000000c4 <text_label\+0xc4>
+[ 	]*c4: R_MIPS_PC16	external_label
 	...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bgeu.s src/gas/testsuite/gas/mips/bgeu.s
--- src-orig/gas/testsuite/gas/mips/bgeu.s	Mon May  3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/bgeu.s	Fri Aug 31 23:01:41 2001
@@ -22,6 +22,12 @@ text_label:	
 	bgeul	$4,$5,text_label
 	bgtul	$4,$5,text_label
 
+# Branch to an external label.
+	bgeu	$4,$5,external_label
+	bgtu	$4,$5,external_label
+	bgeul	$4,$5,external_label
+	bgtul	$4,$5,external_label
+
 # Round to a 16 byte boundary, for ease in testing multiple targets.
 	nop
 	nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/blt.d src/gas/testsuite/gas/mips/blt.d
--- src-orig/gas/testsuite/gas/mips/blt.d	Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/blt.d	Fri Aug 31 23:01:41 2001
@@ -50,4 +50,20 @@ Disassembly of section .text:
 0+00a4 <[^>]*> nop
 0+00a8 <[^>]*> slt	at,a1,a0
 0+00ac <[^>]*> beqzl	at,0+0000 <text_label>
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> slt	at,a0,a1
+0+00b8 <[^>]*> bnez	at,000000b8 <text_label\+0xb8>
+[ 	]*b8: R_MIPS_PC16	external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> slt	at,a1,a0
+0+00c4 <[^>]*> beqz	at,000000c4 <text_label\+0xc4>
+[ 	]*c4: R_MIPS_PC16	external_label
+0+00c8 <[^>]*> nop
+0+00cc <[^>]*> slt	at,a0,a1
+0+00d0 <[^>]*> bnezl	at,000000d0 <text_label\+0xd0>
+[ 	]*d0: R_MIPS_PC16	external_label
+0+00d4 <[^>]*> nop
+0+00d8 <[^>]*> slt	at,a1,a0
+0+00dc <[^>]*> beqzl	at,000000dc <text_label\+0xdc>
+[ 	]*dc: R_MIPS_PC16	external_label
 	...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/blt.s src/gas/testsuite/gas/mips/blt.s
--- src-orig/gas/testsuite/gas/mips/blt.s	Mon May  3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/blt.s	Fri Aug 31 23:01:41 2001
@@ -24,6 +24,12 @@ text_label:	
 	bltl	$4,$5,text_label
 	blel	$4,$5,text_label
 
+# Branch to an external label.
+	blt	$4,$5,external_label
+	ble	$4,$5,external_label
+	bltl	$4,$5,external_label
+	blel	$4,$5,external_label
+
 # Round to a 16 byte boundary, for ease in testing multiple targets.
 	nop
 	nop
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bltu.d src/gas/testsuite/gas/mips/bltu.d
--- src-orig/gas/testsuite/gas/mips/bltu.d	Tue May 15 16:33:52 2001
+++ src/gas/testsuite/gas/mips/bltu.d	Fri Aug 31 23:01:41 2001
@@ -44,4 +44,20 @@ Disassembly of section .text:
 0+008c <[^>]*> nop
 0+0090 <[^>]*> sltu	at,a1,a0
 0+0094 <[^>]*> beqzl	at,0+0000 <text_label>
+0+0098 <[^>]*> nop
+0+009c <[^>]*> sltu	at,a0,a1
+0+00a0 <[^>]*> bnez	at,000000a0 <text_label\+0xa0>
+[ 	]*a0: R_MIPS_PC16	external_label
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> sltu	at,a1,a0
+0+00ac <[^>]*> beqz	at,000000ac <text_label\+0xac>
+[ 	]*ac: R_MIPS_PC16	external_label
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> sltu	at,a0,a1
+0+00b8 <[^>]*> bnezl	at,000000b8 <text_label\+0xb8>
+[ 	]*b8: R_MIPS_PC16	external_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> sltu	at,a1,a0
+0+00c4 <[^>]*> beqzl	at,000000c4 <text_label\+0xc4>
+[ 	]*c4: R_MIPS_PC16	external_label
 	...
diff -BurpNX /bigdisk/src/binutils-exclude src-orig/gas/testsuite/gas/mips/bltu.s src/gas/testsuite/gas/mips/bltu.s
--- src-orig/gas/testsuite/gas/mips/bltu.s	Mon May  3 09:28:50 1999
+++ src/gas/testsuite/gas/mips/bltu.s	Fri Aug 31 23:01:41 2001
@@ -22,6 +22,12 @@ text_label:	
 	bltul	$4,$5,text_label
 	bleul	$4,$5,text_label
 
+# Branch to an external label.
+	bltu	$4,$5,external_label
+	bleu	$4,$5,external_label
+	bltul	$4,$5,external_label
+	bleul	$4,$5,external_label
+
 # Round to a 16 byte boundary, for ease in testing multiple targets.
 	nop
 	nop


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