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]

[PATCH] MIPS gas/bfd: Relocation handling cleanup


Hello All,

this patch sanitizes the MIPS relocation handling, specifically the
zero-addend workarounds, the pcrel/gprel specialcases and some minor
fixes for cornercases.

It enables also sane overflow checking from md_apply_fix3, the current
version checks the old addend value.

Tested for mips-linux, mips64-linux, mips-sgi-irix6, mips-elf, mips-ecoff.


Thiemo


2003-05-27  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>

	/bfd/ChangeLog
	* elf32-mips.c (mips_elf_generic_reloc): New Function.
	(elf_mips_howto_table_rel): Use it.
	(gprel32_with_gp): Move prototype.
	(mips_elf_hi16_reloc): Check for ! BSF_LOCAL instead of zero addend.
	Use mips_elf_generic_reloc.
	(mips_elf_got16_reloc): Check for ! BSF_LOCAL instead of zero addend.
	Code cleanup.
	(_bfd_mips_elf32_gprel16_reloc): Check for ! BSF_LOCAL instead of
	zero addend.
	(mips_elf_gprel32_reloc): Likewise. Use the same GP assignment logic
	as in the other *_gprel*_reloc functions.
	(gprel32_with_gp): Handle partial_inplace properly.
	(mips32_64bit_reloc): Use mips_elf_generic_reloc.
	(mips16_gprel_reloc): Check for ! BSF_LOCAL instead of zero addend.
	Do addend handling directly instead of calling
	_bfd_mips_elf_gprel16_with_gp. Handle partial_inplace properly.
	* elf64-mips.c (mips_elf64_hi16_reloc): Check for ! BSF_LOCAL instead
	of zero addend. Handle partial_inplace properly.
	(mips_elf64_got16_reloc): Check for ! BSF_LOCAL instead of zero
	addend.
	(mips_elf64_gprel16_reloc): Likewise.
	(mips_elf64_literal_reloc): Likewise.
	(mips_elf64_gprel32_reloc): Likewise. Use the same GP assignment
	logic as in the other *_gprel*_reloc functions. Handle
	partial_inplace properly.
	(mips_elf64_shift6_reloc): Check for ! BSF_LOCAL instead of zero
	addend. Handle partial_inplace properly.
	(mips16_gprel_reloc): Likewise. Do addend handling directly instead
	of calling _bfd_mips_elf_gprel16_with_gp.
	* elfn32-mips.c (mips_elf_got16_reloc): Check for BSF_LOCAL.
	(mips_elf_gprel32_reloc): Check for ! BSF_LOCAL instead
	of zero addend.
	(mips_elf_shift6_reloc): Handle partial_inplace properly.
	(mips16_gprel_reloc): Likewise. Do addend handling directly instead
	of calling _bfd_mips_elf_gprel16_with_gp.
	* elfxx-mips.c (_bfd_mips_elf_gprel16_with_gp): Handle
	partial_inplace properly. Fix wrong addend handling. Fix overflow
	check.
	(_bfd_mips_elf_sign_extend): Renamed from mips_elf_sign_extend and
	exported.
	(mips_elf_calculate_relocation): Use _bfd_mips_elf_sign_extend.
	(_bfd_mips_elf_relocate_section): Likewise.
	(mips_elf_create_dynamic_relocation): Update sec_info_type access.
	* elfxx-mips.h (_bfd_mips_relax_section): Fix prototype declaration.
	(_bfd_mips_elf_sign_extend): New prototype.

	/gas/ChangeLog
	* config/tc-mips.c (md_pcrel_from): Return actual pcrel address.
	(md_apply_fix3): Ignore non-special relocations. Remove superfluous
	exceptions from size assert. Remove most of the addend fixup
	specialcasing. Remove value, use valP directly. simplify fx_addnumber
	handling. Remove zero addend specialcases.
	(tc_gen_reloc): Use appropriate value for reloc2 addend. Remove
	the addend fixup specialcase.
	* config/tc-mips.h (MD_APPLY_SYM_VALUE): Define as 0.


diff -BurpNX /bigdisk/src/gcc-exclude source-orig/bfd/elf32-mips.c source/bfd/elf32-mips.c
--- source-orig/bfd/elf32-mips.c	Sun May 25 09:20:20 2003
+++ source/bfd/elf32-mips.c	Sun May 25 10:02:13 2003
@@ -47,12 +47,17 @@ Foundation, Inc., 59 Temple Place - Suit
 #define ECOFF_SIGNED_32
 #include "ecoffswap.h"
 
+static bfd_reloc_status_type mips_elf_generic_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf_hi16_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf_lo16_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf_got16_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type gprel32_with_gp
+  PARAMS ((bfd *, asymbol *, arelent *, asection *, bfd_boolean, PTR,
+	   bfd_vma));
 static bfd_reloc_status_type mips_elf_gprel32_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips32_64bit_reloc
@@ -116,7 +121,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_NONE",		/* name */
 	 FALSE,			/* partial_inplace */
 	 0,			/* src_mask */
@@ -131,7 +136,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_16",		/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -146,7 +151,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_32",		/* name */
 	 TRUE,			/* partial_inplace */
 	 0xffffffff,		/* src_mask */
@@ -161,7 +166,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_REL32",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0xffffffff,		/* src_mask */
@@ -179,7 +184,7 @@ static reloc_howto_type elf_mips_howto_t
 	 			/* This needs complex overflow
 				   detection, because the upper four
 				   bits must match the PC + 4.  */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_26",		/* name */
 	 TRUE,			/* partial_inplace */
 	 0x03ffffff,		/* src_mask */
@@ -269,7 +274,7 @@ static reloc_howto_type elf_mips_howto_t
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_PC16",		/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -284,7 +289,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_CALL16",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -320,7 +325,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 6,			/* bitpos */
 	 complain_overflow_bitfield, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_SHIFT5",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x000007c0,		/* src_mask */
@@ -337,7 +342,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 6,			/* bitpos */
 	 complain_overflow_bitfield, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_SHIFT6",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x000007c4,		/* src_mask */
@@ -367,7 +372,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_GOT_DISP",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -382,7 +387,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_GOT_PAGE",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -397,7 +402,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_GOT_OFST",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -412,7 +417,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_GOT_HI16",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -427,7 +432,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_GOT_LO16",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -442,7 +447,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_SUB",		/* name */
 	 TRUE,			/* partial_inplace */
 	 MINUS_ONE,		/* src_mask */
@@ -462,7 +467,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_HIGHER",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -477,7 +482,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_HIGHEST",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -492,7 +497,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_CALL_HI16",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -507,7 +512,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_CALL_LO16",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0x0000ffff,		/* src_mask */
@@ -522,7 +527,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_SCN_DISP",     /* name */
 	 TRUE,			/* partial_inplace */
 	 0xffffffff,		/* src_mask */
@@ -543,7 +548,7 @@ static reloc_howto_type elf_mips_howto_t
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_dont, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_JALR",	        /* name */
 	 FALSE,			/* partial_inplace */
 	 0x00000000,		/* src_mask */
@@ -645,7 +650,7 @@ static reloc_howto_type elf_mips_gnu_rel
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_GNU_REL16_S2",	/* name */
 	 TRUE,			/* partial_inplace */
 	 0xffff,		/* src_mask */
@@ -661,7 +666,7 @@ static reloc_howto_type elf_mips_gnu_pcr
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_PC64",		/* name */
 	 TRUE,			/* partial_inplace */
 	 MINUS_ONE,		/* src_mask */
@@ -677,7 +682,7 @@ static reloc_howto_type elf_mips_gnu_pcr
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf_generic_reloc, /* special_function */
 	 "R_MIPS_PC32",		/* name */
 	 TRUE,			/* partial_inplace */
 	 0xffffffff,		/* src_mask */
@@ -716,6 +721,33 @@ static reloc_howto_type elf_mips_gnu_vte
 	 0,			/* dst_mask */
 	 FALSE);		/* pcrel_offset */
 
+/* We use this instead of bfd_elf_generic_reloc because the latter
+   gets the handling of zero addends wrong. */
+static bfd_reloc_status_type
+mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section,
+			output_bfd, error_message)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message ATTRIBUTE_UNUSED;
+{
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
+  if (output_bfd != (bfd *) NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && (symbol->flags & BSF_LOCAL) != 0)
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  /* Just go on, nothing to see here.  */
+  return bfd_reloc_continue;
+}
+
 /* Do a R_MIPS_HI16 relocation.  This has to be done in combination
    with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to
    the HI16.  Here we just save the information we need; we do the
@@ -761,7 +793,7 @@ mips_elf_hi16_reloc (abfd, reloc_entry, 
      to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -923,8 +955,8 @@ mips_elf_lo16_reloc (abfd, reloc_entry, 
     }
 
   /* Now do the LO16 reloc in the usual way.  */
-  return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
-				input_section, output_bfd, error_message);
+  return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+				 input_section, output_bfd, error_message);
 }
 
 /* Do a R_MIPS_GOT16 reloc.  This is a reloc against the global offset
@@ -956,20 +988,14 @@ mips_elf_got16_reloc (abfd, reloc_entry,
      to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
 
-  /* If we're relocating, and this is a local symbol, we can handle it
-     just like HI16.  */
-  if (output_bfd != (bfd *) NULL
-      && (symbol->flags & BSF_SECTION_SYM) != 0)
-    return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
-				input_section, output_bfd, error_message);
-
-  abort ();
+  return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
+			      input_section, output_bfd, error_message);
 }
 
 /* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
@@ -1087,13 +1113,11 @@ _bfd_mips_elf32_gprel16_reloc (abfd, rel
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1120,10 +1144,6 @@ _bfd_mips_elf32_gprel16_reloc (abfd, rel
 /* Do a R_MIPS_GPREL32 relocation.  This is a 32 bit value which must
    become the offset from the gp register.  */
 
-static bfd_reloc_status_type gprel32_with_gp
-  PARAMS ((bfd *, asymbol *, arelent *, asection *, bfd_boolean, PTR,
-	   bfd_vma));
-
 static bfd_reloc_status_type
 mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
 			output_bfd, error_message)
@@ -1139,13 +1159,11 @@ mips_elf_gprel32_reloc (abfd, reloc_entr
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       *error_message = (char *)
 	_("32bits gp relative relocation occurs for an external symbol");
@@ -1153,21 +1171,18 @@ mips_elf_gprel32_reloc (abfd, reloc_entr
     }
 
   if (output_bfd != (bfd *) NULL)
-    {
-      relocateable = TRUE;
-      gp = _bfd_get_gp_value (output_bfd);
-    }
+    relocateable = TRUE;
   else
     {
       relocateable = FALSE;
       output_bfd = symbol->section->output_section->owner;
-
-      ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
-			       error_message, &gp);
-      if (ret != bfd_reloc_ok)
-	return ret;
     }
 
+  ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
+			   error_message, &gp);
+  if (ret != bfd_reloc_ok)
+    return ret;
+
   return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
 			  relocateable, data, gp);
 }
@@ -1184,7 +1199,7 @@ gprel32_with_gp (abfd, symbol, reloc_ent
      bfd_vma gp;
 {
   bfd_vma relocation;
-  unsigned long val;
+  bfd_vma val;
 
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
@@ -1197,10 +1212,11 @@ gprel32_with_gp (abfd, symbol, reloc_ent
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
   /* Set val to the offset into the section or symbol.  */
-  val += reloc_entry->addend;
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
+    val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
 
   /* Adjust val for the final section location and GP value.  If we
      are producing relocateable output, we don't want to do this for
@@ -1209,7 +1225,10 @@ gprel32_with_gp (abfd, symbol, reloc_ent
       || (symbol->flags & BSF_SECTION_SYM) != 0)
     val += relocation - gp;
 
-  bfd_put_32 (abfd, (bfd_vma) val, (bfd_byte *) data + reloc_entry->address);
+  if (reloc_entry->howto->partial_inplace)
+    bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
+  else
+    reloc_entry->addend = val;
 
   if (relocateable)
     reloc_entry->address += input_section->output_offset;
@@ -1237,8 +1256,8 @@ mips32_64bit_reloc (abfd, reloc_entry, s
   unsigned long val;
   bfd_size_type addr;
 
-  r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
-			     input_section, output_bfd, error_message);
+  r = mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+			      input_section, output_bfd, error_message);
   if (r != bfd_reloc_continue)
     return r;
 
@@ -1315,16 +1337,16 @@ mips16_gprel_reloc (abfd, reloc_entry, s
   bfd_boolean relocateable;
   bfd_reloc_status_type ret;
   bfd_vma gp;
-  unsigned short extend, insn;
-  unsigned long final;
+  unsigned short extend = 0;
+  unsigned short insn = 0;
+  bfd_signed_vma val;
+  bfd_vma relocation;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1346,33 +1368,55 @@ mips16_gprel_reloc (abfd, reloc_entry, s
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  /* Pick up the mips16 extend instruction and the real instruction.  */
-  extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
-  insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
-
-  /* Stuff the current addend back as a 32 bit value, do the usual
-     relocation, and then clean up.  */
-  bfd_put_32 (abfd,
-	      (bfd_vma) (((extend & 0x1f) << 11)
-			 | (extend & 0x7e0)
-			 | (insn & 0x1f)),
-	      (bfd_byte *) data + reloc_entry->address);
-
-  ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
-				       input_section, relocateable, data, gp);
-
-  final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-	      (bfd_vma) ((extend & 0xf800)
-			 | ((final >> 11) & 0x1f)
-			 | (final & 0x7e0)),
-	      (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-	      (bfd_vma) ((insn & 0xffe0)
-			 | (final & 0x1f)),
-	      (bfd_byte *) data + reloc_entry->address + 2);
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
 
-  return ret;
+  relocation += symbol->section->output_section->vma;
+  relocation += symbol->section->output_offset;
+
+  /* Set val to the offset into the section or symbol.  */
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      /* Pick up the mips16 extend instruction and the real instruction.  */
+      extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
+      insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
+      val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
+    }
+
+  _bfd_mips_elf_sign_extend(val, 16);
+
+  /* Adjust val for the final section location and GP value.  If we
+     are producing relocateable output, we don't want to do this for
+     an external symbol.  */
+  if (! relocateable
+      || (symbol->flags & BSF_SECTION_SYM) != 0)
+    val += relocation - gp;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      bfd_put_16 (abfd,
+		  (bfd_vma) ((extend & 0xf800)
+			     | ((val >> 11) & 0x1f)
+			     | (val & 0x7e0)),
+		  (bfd_byte *) data + reloc_entry->address);
+      bfd_put_16 (abfd,
+		  (bfd_vma) ((insn & 0xffe0)
+			     | (val & 0x1f)),
+		  (bfd_byte *) data + reloc_entry->address + 2);
+    }
+  else
+    reloc_entry->addend = val;
+
+  if (relocateable)
+    reloc_entry->address += input_section->output_offset;
+  else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
+    return bfd_reloc_overflow;
+
+  return bfd_reloc_ok;
 }
 
 /* A mapping from BFD reloc types to MIPS ELF reloc types.  */
diff -BurpNX /bigdisk/src/gcc-exclude source-orig/bfd/elf64-mips.c source/bfd/elf64-mips.c
--- source-orig/bfd/elf64-mips.c	Sun May 25 09:20:21 2003
+++ source/bfd/elf64-mips.c	Sun May 25 09:55:19 2003
@@ -1447,15 +1447,17 @@ mips_elf64_hi16_reloc (abfd, reloc_entry
      want to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && (! reloc_entry->howto->partial_inplace
-	  || reloc_entry->addend == 0))
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
 
-  if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
-    reloc_entry->addend += 0x8000;
+  if (reloc_entry->howto->partial_inplace)
+    {
+      if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
+	reloc_entry->addend += 0x8000;
+    }
 
   return bfd_reloc_continue;
 }
@@ -1486,9 +1488,10 @@ mips_elf64_got16_reloc (abfd, reloc_entr
      char **error_message;
 {
   /* If we're relocating, and this is a local symbol, we can handle it
      just like an R_MIPS_HI16.  */
   if (output_bfd != (bfd *) NULL
-      && (symbol->flags & BSF_SECTION_SYM) != 0)
+      && ((symbol->flags & BSF_SECTION_SYM) != 0
+	  || (symbol->flags & BSF_LOCAL) == 0))
     return mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data,
 				  input_section, output_bfd, error_message);
 
@@ -1610,14 +1612,11 @@ mips_elf64_gprel16_reloc (abfd, reloc_en
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && (! reloc_entry->howto->partial_inplace
-	  || reloc_entry->addend == 0))
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1662,8 +1661,7 @@ mips_elf64_literal_reloc (abfd, reloc_en
      want to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && (! reloc_entry->howto->partial_inplace
-	  || reloc_entry->addend == 0))
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1706,15 +1704,13 @@ mips_elf64_gprel32_reloc (abfd, reloc_en
   bfd_reloc_status_type ret;
   bfd_vma gp;
   bfd_vma relocation;
-  unsigned long val;
+  bfd_vma val;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       *error_message = (char *)
 	_("32bits gp relative relocation occurs for an external symbol");
@@ -1722,21 +1718,18 @@ mips_elf64_gprel32_reloc (abfd, reloc_en
     }
 
   if (output_bfd != (bfd *) NULL)
-    {
-      relocateable = TRUE;
-      gp = _bfd_get_gp_value (output_bfd);
-    }
+    relocateable = TRUE;
   else
     {
       relocateable = FALSE;
       output_bfd = symbol->section->output_section->owner;
-
-      ret = mips_elf64_final_gp (output_bfd, symbol, relocateable,
-				 error_message, &gp);
-      if (ret != bfd_reloc_ok)
-	return ret;
     }
 
+    ret = mips_elf64_final_gp (output_bfd, symbol, relocateable,
+			       error_message, &gp);
+    if (ret != bfd_reloc_ok)
+      return ret;
+
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
   else
@@ -1748,16 +1741,11 @@ mips_elf64_gprel32_reloc (abfd, reloc_en
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  if (reloc_entry->howto->src_mask == 0)
-    {
-      /* This case arises with the 64-bit MIPS ELF ABI.  */
-      val = 0;
-    }
-  else
-    val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
   /* Set val to the offset into the section or symbol.  */
-  val += reloc_entry->addend;
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
+    val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
 
   /* Adjust val for the final section location and GP value.  If we
      are producing relocateable output, we don't want to do this for
@@ -1766,7 +1754,10 @@ mips_elf64_gprel32_reloc (abfd, reloc_en
       || (symbol->flags & BSF_SECTION_SYM) != 0)
     val += relocation - gp;
 
-  bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
+  if (reloc_entry->howto->partial_inplace)
+    bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
+  else
+    reloc_entry->addend = val;
 
   if (relocateable)
     reloc_entry->address += input_section->output_offset;
@@ -1792,15 +1783,17 @@ mips_elf64_shift6_reloc (abfd, reloc_ent
      want to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && (! reloc_entry->howto->partial_inplace
-	  || reloc_entry->addend == 0))
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
 
-  reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
-			| (reloc_entry->addend & 0x00000800) >> 9;
+  if (reloc_entry->howto->partial_inplace)
+    {
+      reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
+			     | (reloc_entry->addend & 0x00000800) >> 9);
+    }
 
   return bfd_reloc_continue;
 }
@@ -1857,16 +1852,16 @@ mips16_gprel_reloc (abfd, reloc_entry, s
   bfd_boolean relocateable;
   bfd_reloc_status_type ret;
   bfd_vma gp;
-  unsigned short extend, insn;
-  unsigned long final;
+  unsigned short extend = 0;
+  unsigned short insn = 0;
+  bfd_signed_vma val;
+  bfd_vma relocation;
 
   /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+     addend, we don't want to change anything.  */
   if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1888,33 +1883,55 @@ mips16_gprel_reloc (abfd, reloc_entry, s
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  /* Pick up the mips16 extend instruction and the real instruction.  */
-  extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
-  insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
-
-  /* Stuff the current addend back as a 32 bit value, do the usual
-     relocation, and then clean up.  */
-  bfd_put_32 (abfd,
-	      (bfd_vma) (((extend & 0x1f) << 11)
-			 | (extend & 0x7e0)
-			 | (insn & 0x1f)),
-	      (bfd_byte *) data + reloc_entry->address);
-
-  ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
-				       input_section, relocateable, data, gp);
-
-  final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-	      (bfd_vma) ((extend & 0xf800)
-			 | ((final >> 11) & 0x1f)
-			 | (final & 0x7e0)),
-	      (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-	      (bfd_vma) ((insn & 0xffe0)
-			 | (final & 0x1f)),
-	      (bfd_byte *) data + reloc_entry->address + 2);
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  relocation += symbol->section->output_section->vma;
+  relocation += symbol->section->output_offset;
 
-  return ret;
+  /* Set val to the offset into the section or symbol.  */
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      /* Pick up the mips16 extend instruction and the real instruction.  */
+      extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
+      insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
+      val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
+    }
+
+  _bfd_mips_elf_sign_extend(val, 16);
+
+  /* Adjust val for the final section location and GP value.  If we
+     are producing relocateable output, we don't want to do this for
+     an external symbol.  */
+  if (! relocateable
+      || (symbol->flags & BSF_SECTION_SYM) != 0)
+    val += relocation - gp;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      bfd_put_16 (abfd,
+		  (bfd_vma) ((extend & 0xf800)
+			     | ((val >> 11) & 0x1f)
+			     | (val & 0x7e0)),
+		  (bfd_byte *) data + reloc_entry->address);
+      bfd_put_16 (abfd,
+		  (bfd_vma) ((insn & 0xffe0)
+			     | (val & 0x1f)),
+		  (bfd_byte *) data + reloc_entry->address + 2);
+    }
+  else
+    reloc_entry->addend = val;
+
+  if (relocateable)
+    reloc_entry->address += input_section->output_offset;
+  else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
+    return bfd_reloc_overflow;
+
+  return bfd_reloc_ok;
 }
 
 /* A mapping from BFD reloc types to MIPS ELF reloc types.  */
diff -BurpNX /bigdisk/src/gcc-exclude source-orig/bfd/elfn32-mips.c source/bfd/elfn32-mips.c
--- source-orig/bfd/elfn32-mips.c	Sun May 25 09:20:23 2003
+++ source/bfd/elfn32-mips.c	Sun May 25 09:55:19 2003
@@ -1455,7 +1455,8 @@ mips_elf_got16_reloc (abfd, reloc_entry,
   /* If we're relocating, and this is a local symbol, we can handle it
-     just like HI16.  */
+     just like an R_MIPS_HI16.  */
   if (output_bfd != (bfd *) NULL
-      && (symbol->flags & BSF_SECTION_SYM) != 0)
+      && ((symbol->flags & BSF_SECTION_SYM) != 0
+	  || (symbol->flags & BSF_LOCAL) == 0))
     return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
 				input_section, output_bfd, error_message);
 
@@ -1654,12 +1655,10 @@ mips_elf_gprel32_reloc (abfd, reloc_entr
 
   GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
 
-  /* R_MIPS_GPREL32 relocations are defined for local symbols only.
-     We will only have an addend if this is a newly created reloc,
-     not read from an ELF file.  */
+  /* R_MIPS_GPREL32 relocations are defined for local symbols only.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       *error_message = (char *)
 	_("32bits gp relative relocation occurs for an external symbol");
@@ -1750,8 +1749,11 @@ mips_elf_shift6_reloc (abfd, reloc_entry
 {
   GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
 
-  reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
-			| (reloc_entry->addend & 0x00000800) >> 9;
+  if (reloc_entry->howto->partial_inplace)
+    {
+      reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
+			     | (reloc_entry->addend & 0x00000800) >> 9);
+    }
 
   SET_RELOC_ADDEND (reloc_entry)
 
@@ -1801,8 +1814,10 @@ mips16_gprel_reloc (abfd, reloc_entry, s
   bfd_boolean relocateable;
   bfd_reloc_status_type ret;
   bfd_vma gp;
-  unsigned short extend, insn;
-  unsigned long final;
+  unsigned short extend = 0;
+  unsigned short insn = 0;
+  bfd_signed_vma val;
+  bfd_vma relocation;
 
   GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
 
@@ -1822,33 +1837,55 @@ mips16_gprel_reloc (abfd, reloc_entry, s
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  /* Pick up the mips16 extend instruction and the real instruction.  */
-  extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
-  insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
-
-  /* Stuff the current addend back as a 32 bit value, do the usual
-     relocation, and then clean up.  */
-  bfd_put_32 (abfd,
-	      (bfd_vma) (((extend & 0x1f) << 11)
-			 | (extend & 0x7e0)
-			 | (insn & 0x1f)),
-	      (bfd_byte *) data + reloc_entry->address);
-
-  ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
-				       input_section, relocateable, data, gp);
-
-  final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-	      (bfd_vma) ((extend & 0xf800)
-			 | ((final >> 11) & 0x1f)
-			 | (final & 0x7e0)),
-	      (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-	      (bfd_vma) ((insn & 0xffe0)
-			 | (final & 0x1f)),
-	      (bfd_byte *) data + reloc_entry->address + 2);
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  relocation += symbol->section->output_section->vma;
+  relocation += symbol->section->output_offset;
+
+  /* Set val to the offset into the section or symbol.  */
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      /* Pick up the mips16 extend instruction and the real instruction.  */
+      extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
+      insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
+      val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
+    }
 
-  return ret;
+  _bfd_mips_elf_sign_extend(val, 16);
+
+  /* Adjust val for the final section location and GP value.  If we
+     are producing relocateable output, we don't want to do this for
+     an external symbol.  */
+  if (! relocateable
+      || (symbol->flags & BSF_SECTION_SYM) != 0)
+    val += relocation - gp;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      bfd_put_16 (abfd,
+		  (bfd_vma) ((extend & 0xf800)
+			     | ((val >> 11) & 0x1f)
+			     | (val & 0x7e0)),
+		  (bfd_byte *) data + reloc_entry->address);
+      bfd_put_16 (abfd,
+		  (bfd_vma) ((insn & 0xffe0)
+			     | (val & 0x1f)),
+		  (bfd_byte *) data + reloc_entry->address + 2);
+    }
+  else
+    reloc_entry->addend = val;
+
+  if (relocateable)
+    reloc_entry->address += input_section->output_offset;
+  else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
+    return bfd_reloc_overflow;
+
+  return bfd_reloc_ok;
 }
 
 #undef GET_RELOC_ADDEND
diff -BurpNX /bigdisk/src/gcc-exclude source-orig/bfd/elfxx-mips.c source/bfd/elfxx-mips.c
--- source-orig/bfd/elfxx-mips.c	Sun May 25 09:20:23 2003
+++ source/bfd/elfxx-mips.c	Sun May 25 09:55:20 2003
@@ -433,7 +433,6 @@ static const Elf_Internal_Rela *mips_elf
 	   const Elf_Internal_Rela *));
 static bfd_boolean mips_elf_local_relocation_p
   PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, bfd_boolean));
-static bfd_vma mips_elf_sign_extend PARAMS ((bfd_vma, int));
 static bfd_boolean mips_elf_overflow_p PARAMS ((bfd_vma, int));
 static bfd_vma mips_elf_high PARAMS ((bfd_vma));
 static bfd_vma mips_elf_higher PARAMS ((bfd_vma));
@@ -1090,8 +1089,8 @@ _bfd_mips_elf_gprel16_with_gp (abfd, sym
      bfd_vma gp;
 {
   bfd_vma relocation;
-  unsigned long insn;
-  unsigned long val;
+  unsigned long insn = 0;
+  bfd_signed_vma val;
 
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
@@ -1104,21 +1103,17 @@ _bfd_mips_elf_gprel16_with_gp (abfd, sym
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
   /* Set val to the offset into the section or symbol.  */
-  if (reloc_entry->howto->src_mask == 0)
-    {
-      /* This case occurs with the 64-bit MIPS ELF ABI.  */
-      val = reloc_entry->addend;
-    }
-  else
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
     {
-      val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
-      if (val & 0x8000)
-	val -= 0x10000;
+      insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+      val += insn & 0xffff;
     }
 
+  _bfd_mips_elf_sign_extend(val, 16);
+
   /* Adjust val for the final section location and GP value.  If we
      are producing relocateable output, we don't want to do this for
      an external symbol.  */
@@ -1126,13 +1121,18 @@ _bfd_mips_elf_gprel16_with_gp (abfd, sym
       || (symbol->flags & BSF_SECTION_SYM) != 0)
     val += relocation - gp;
 
-  insn = (insn & ~0xffff) | (val & 0xffff);
-  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+  if (reloc_entry->howto->partial_inplace)
+    {
+      insn = (insn & ~0xffff) | (val & 0xffff);
+      bfd_put_32 (abfd, (bfd_vma) insn,
+		  (bfd_byte *) data + reloc_entry->address);
+    }
+  else
+    reloc_entry->addend = val;
 
   if (relocateable)
     reloc_entry->address += input_section->output_offset;
-
-  else if ((long) val >= 0x8000 || (long) val < -0x8000)
+  else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
     return bfd_reloc_overflow;
 
   return bfd_reloc_ok;
@@ -2740,8 +2740,8 @@ mips_elf_local_relocation_p (input_bfd, 
 
 /* Sign-extend VALUE, which has the indicated number of BITS.  */
 
-static bfd_vma
-mips_elf_sign_extend (value, bits)
+bfd_vma
+_bfd_mips_elf_sign_extend (value, bits)
      bfd_vma value;
      int bits;
 {
@@ -3304,7 +3304,7 @@ mips_elf_calculate_relocation (abfd, inp
       return bfd_reloc_continue;
 
     case R_MIPS_16:
-      value = symbol + mips_elf_sign_extend (addend, 16);
+      value = symbol + _bfd_mips_elf_sign_extend (addend, 16);
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
@@ -3355,7 +3355,7 @@ mips_elf_calculate_relocation (abfd, inp
       break;
 
     case R_MIPS_GNU_REL16_S2:
-      value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
+      value = symbol + _bfd_mips_elf_sign_extend (addend << 2, 18) - p;
       overflowed_p = mips_elf_overflow_p (value, 18);
       value = (value >> 2) & howto->dst_mask;
       break;
@@ -3380,7 +3380,7 @@ mips_elf_calculate_relocation (abfd, inp
       if (local_p)
 	value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
       else
-	value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
+	value = (_bfd_mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
       value &= howto->dst_mask;
       break;
 
@@ -3440,7 +3440,7 @@ mips_elf_calculate_relocation (abfd, inp
 	 instruction.  If the addend was separate, leave it alone,
 	 otherwise we may lose significant bits.  */
       if (howto->partial_inplace)
-	addend = mips_elf_sign_extend (addend, 16);
+	addend = _bfd_mips_elf_sign_extend (addend, 16);
       value = symbol + addend - gp;
       /* If the symbol was local, any earlier relocatable links will
 	 have adjusted its addend with the gp offset, so compensate
@@ -3489,7 +3489,7 @@ mips_elf_calculate_relocation (abfd, inp
       break;
 
     case R_MIPS_PC16:
-      value = mips_elf_sign_extend (addend, 16) + symbol - p;
+      value = _bfd_mips_elf_sign_extend (addend, 16) + symbol - p;
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
@@ -3852,7 +3852,7 @@ mips_elf_create_dynamic_relocation (outp
   /* We begin by assuming that the offset for the dynamic relocation
      is the same as for the original relocation.  We'll adjust this
      later to reflect the correct output offsets.  */
-  if (elf_section_data (input_section)->sec_info_type != ELF_INFO_TYPE_STABS)
+  if (input_section->sec_info_type != ELF_INFO_TYPE_STABS)
     {
       outrel[1].r_offset = rel[1].r_offset;
       outrel[2].r_offset = rel[2].r_offset;
@@ -6352,7 +6352,7 @@ _bfd_mips_elf_relocate_section (output_b
 						input_bfd, contents);
 		  l &= lo16_howto->src_mask;
 		  l <<= lo16_howto->rightshift;
-		  l = mips_elf_sign_extend (l, 16);
+		  l = _bfd_mips_elf_sign_extend (l, 16);
 
 		  addend <<= 16;
 
diff -BurpNX /bigdisk/src/gcc-exclude source-orig/bfd/elfxx-mips.h source/bfd/elfxx-mips.h
--- source-orig/bfd/elfxx-mips.h	Wed Mar 26 02:04:22 2003
+++ source/bfd/elfxx-mips.h	Thu May 15 17:31:37 2003
@@ -108,6 +108,7 @@ extern bfd_reloc_status_type _bfd_mips_e
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 extern unsigned long _bfd_elf_mips_mach
   PARAMS ((flagword));
-extern bfd_boolean _bfd_mips_relax_section (bfd *, asection *,
-					    struct bfd_link_info *,
-					    bfd_boolean *);
+extern bfd_boolean _bfd_mips_relax_section
+  PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
+extern bfd_vma _bfd_mips_elf_sign_extend
+  PARAMS ((bfd_vma, int));
diff -BurpNX /bigdisk/src/gcc-exclude source-orig/gas/config/tc-mips.c source/gas/config/tc-mips.c
--- source-orig/gas/config/tc-mips.c	Sun May 25 09:20:25 2003
+++ source/gas/config/tc-mips.c	Sun May 25 09:55:26 2003
@@ -11364,13 +11364,16 @@ long
 md_pcrel_from (fixP)
      fixS *fixP;
 {
-  if (OUTPUT_FLAVOR != bfd_target_aout_flavour
-      && fixP->fx_addsy != (symbolS *) NULL
-      && ! S_IS_DEFINED (fixP->fx_addsy))
-    return 4;
-
-  /* Return the address of the delay slot.  */
-  return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+  valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
+  switch (fixP->fx_r_type)
+    {
+    case BFD_RELOC_16_PCREL_S2:
+    case BFD_RELOC_MIPS_JMP:
+      /* Return the address of the delay slot.  */
+      return addr + 4;
+    default:
+      return addr;
+    }
 }
 
 /* This is called before the symbol table is processed.  In order to
@@ -11631,133 +11634,79 @@ md_apply_fix3 (fixP, valP, seg)
 {
   bfd_byte *buf;
   long insn;
-  valueT value;
   static int previous_fx_r_type = 0;
+  reloc_howto_type *howto;
 
-  /* FIXME: Maybe just return for all reloc types not listed below?
-     Eric Christopher says: "This is stupid, please rewrite md_apply_fix3. */
-  if (fixP->fx_r_type == BFD_RELOC_8)
-      return;
+  /* We ignore generic BFD relocations we don't know about.  */
+  howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+  if (! howto)
+    return;
 
   assert (fixP->fx_size == 4
 	  || fixP->fx_r_type == BFD_RELOC_16
-	  || fixP->fx_r_type == BFD_RELOC_32
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_JMP
-	  || fixP->fx_r_type == BFD_RELOC_HI16_S
-	  || fixP->fx_r_type == BFD_RELOC_LO16
-	  || fixP->fx_r_type == BFD_RELOC_GPREL16
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_LITERAL
-	  || fixP->fx_r_type == BFD_RELOC_GPREL32
 	  || fixP->fx_r_type == BFD_RELOC_64
 	  || fixP->fx_r_type == BFD_RELOC_CTOR
 	  || fixP->fx_r_type == BFD_RELOC_MIPS_SUB
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_HIGHEST
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_HIGHER
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_SCN_DISP
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_REL16
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_RELGOT
 	  || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-	  || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
-	  || fixP->fx_r_type == BFD_RELOC_MIPS_JALR);
+	  || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY);
 
-  value = *valP;
+  buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
 
   /* If we aren't adjusting this fixup to be against the section
      symbol, we need to adjust the value.  */
 #ifdef OBJ_ELF
   if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
     {
-      if (mips_need_elf_addend_fixup (fixP))
-	{
-	  reloc_howto_type *howto;
-	  valueT symval = S_GET_VALUE (fixP->fx_addsy);
-
-	  value -= symval;
-
-	  howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
-	  if (value != 0 && howto && howto->partial_inplace)
-	    {
-	      /* In this case, the bfd_install_relocation routine will
-		 incorrectly add the symbol value back in.  We just want
-		 the addend to appear in the object file.
-
-		 The condition above used to include
-		 "&& (! fixP->fx_pcrel || howto->pcrel_offset)".
-
-		 However, howto can't be trusted here, because we
-		 might change the reloc type in tc_gen_reloc.  We can
-		 check howto->partial_inplace because that conversion
-		 happens to preserve howto->partial_inplace; but it
-		 does not preserve howto->pcrel_offset.  I've just
-		 eliminated the check, because all MIPS PC-relative
-		 relocations are marked howto->pcrel_offset.
-
-		 howto->pcrel_offset was originally added for
-		 R_MIPS_PC16, which is generated for code like
-
-		 	globl g1 .text
-			.text
-			.space 20
-		 g1:
-		 x:
-		 	bal g1
-	       */
-	      value -= symval;
-
-	      /* Make sure the addend is still non-zero.  If it became zero
-		 after the last operation, set it to a spurious value and
-		 subtract the same value from the object file's contents.  */
-	      if (value == 0)
-		{
-		  value = 8;
-
-		  /* The in-place addends for LO16 relocations are signed;
-		     leave the matching HI16 in-place addends as zero.  */
-		  if (fixP->fx_r_type != BFD_RELOC_HI16_S)
-		    {
-		      bfd_vma contents, mask, field;
-
-		      contents = bfd_get_bits (fixP->fx_frag->fr_literal
-					       + fixP->fx_where,
-					       fixP->fx_size * 8,
-					       target_big_endian);
-
-		      /* MASK has bits set where the relocation should go.
-			 FIELD is -value, shifted into the appropriate place
-			 for this relocation.  */
-		      mask = 1 << (howto->bitsize - 1);
-		      mask = (((mask - 1) << 1) | 1) << howto->bitpos;
-		      field = (-value >> howto->rightshift) << howto->bitpos;
-
-		      bfd_put_bits ((field & mask) | (contents & ~mask),
-				    fixP->fx_frag->fr_literal + fixP->fx_where,
-				    fixP->fx_size * 8,
-				    target_big_endian);
-		    }
-		}
-	    }
+      if (mips_need_elf_addend_fixup (fixP)
+	  && howto->partial_inplace
+	  && fixP->fx_r_type != BFD_RELOC_GPREL16
+	  && fixP->fx_r_type != BFD_RELOC_GPREL32
+	  && fixP->fx_r_type != BFD_RELOC_MIPS16_GPREL)
+	{
+	  /* In this case, the bfd_install_relocation routine will
+	     incorrectly add the symbol value back in.  We just want
+	     the addend to appear in the object file.
+
+	     The condition above used to include
+	     "&& (! fixP->fx_pcrel || howto->pcrel_offset)".
+
+	     However, howto can't be trusted here, because we
+	     might change the reloc type in tc_gen_reloc.  We can
+	     check howto->partial_inplace because that conversion
+	     happens to preserve howto->partial_inplace; but it
+	     does not preserve howto->pcrel_offset.  I've just
+	     eliminated the check, because all MIPS PC-relative
+	     relocations are marked howto->pcrel_offset.
+
+	     howto->pcrel_offset was originally added for
+	     R_MIPS_PC16, which is generated for code like
+
+		    globl g1 .text
+		    .text
+		    .space 20
+	     g1:
+	     x:
+		    bal g1
+	   */
+	  *valP -= S_GET_VALUE (fixP->fx_addsy);
 	}
 
       /* This code was generated using trial and error and so is
 	 fragile and not trustworthy.  If you change it, you should
 	 rerun the elf-rel, elf-rel2, and empic testcases and ensure
 	 they still pass.  */
-      if (fixP->fx_pcrel || fixP->fx_subsy != NULL)
+      if (fixP->fx_pcrel)
 	{
-	  value += fixP->fx_frag->fr_address + fixP->fx_where;
+	  *valP += fixP->fx_frag->fr_address + fixP->fx_where;
 
 	  /* 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
-	      || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
-	    value += fixP->fx_frag->fr_address + fixP->fx_where;
+	  *valP += fixP->fx_frag->fr_address + fixP->fx_where;
 	}
     }
 #endif
 
-  fixP->fx_addnumber = value;	/* Remember value for tc_gen_reloc.  */
-
   /* We are not done if this is a composite relocation to set up gp.  */
   if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel
       && !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
@@ -11810,15 +11759,13 @@ md_apply_fix3 (fixP, valP, seg)
       /* We currently always generate a reloc against a symbol, which
          means that we don't want an addend even if the symbol is
          defined.  */
-      fixP->fx_addnumber = 0;
+      *valP = 0;
       break;
 
     case BFD_RELOC_PCREL_HI16_S:
       /* The addend for this is tricky if it is internal, so we just
 	 do everything here rather than in bfd_install_relocation.  */
-      if (OUTPUT_FLAVOR == bfd_target_elf_flavour
-	  && !fixP->fx_done
-	  && value != 0)
+      if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
 	break;
       if (fixP->fx_addsy
 	  && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
@@ -11826,30 +11773,26 @@ md_apply_fix3 (fixP, valP, seg)
 	  /* For an external symbol adjust by the address to make it
 	     pcrel_offset.  We use the address of the RELLO reloc
 	     which follows this one.  */
-	  value += (fixP->fx_next->fx_frag->fr_address
+	  *valP += (fixP->fx_next->fx_frag->fr_address
 		    + fixP->fx_next->fx_where);
 	}
-      value = ((value + 0x8000) >> 16) & 0xffff;
-      buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
+      *valP = ((*valP + 0x8000) >> 16) & 0xffff;
       if (target_big_endian)
 	buf += 2;
-      md_number_to_chars ((char *) buf, value, 2);
+      md_number_to_chars ((char *) buf, *valP, 2);
       break;
 
     case BFD_RELOC_PCREL_LO16:
       /* The addend for this is tricky if it is internal, so we just
 	 do everything here rather than in bfd_install_relocation.  */
-      if (OUTPUT_FLAVOR == bfd_target_elf_flavour
-	  && !fixP->fx_done
-	  && value != 0)
+      if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
 	break;
       if (fixP->fx_addsy
 	  && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
-	value += fixP->fx_frag->fr_address + fixP->fx_where;
-      buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
+	*valP += fixP->fx_frag->fr_address + fixP->fx_where;
       if (target_big_endian)
 	buf += 2;
-      md_number_to_chars ((char *) buf, value, 2);
+      md_number_to_chars ((char *) buf, *valP, 2);
       break;
 
     case BFD_RELOC_64:
@@ -11859,24 +11802,19 @@ md_apply_fix3 (fixP, valP, seg)
 	  || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
 	{
 	  if (8 <= sizeof (valueT))
-	    md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
-				value, 8);
+	    md_number_to_chars (buf, *valP, 8);
 	  else
 	    {
-	      long w1, w2;
-	      long hiv;
+	      valueT hiv;
 
-	      w1 = w2 = fixP->fx_where;
-	      if (target_big_endian)
-		w1 += 4;
-	      else
-		w2 += 4;
-	      md_number_to_chars (fixP->fx_frag->fr_literal + w1, value, 4);
-	      if ((value & 0x80000000) != 0)
+	      if ((*valP & 0x80000000) != 0)
 		hiv = 0xffffffff;
 	      else
 		hiv = 0;
-	      md_number_to_chars (fixP->fx_frag->fr_literal + w2, hiv, 4);
+	      md_number_to_chars ((char *)(buf + target_big_endian ? 4 : 0),
+				  *valP, 4);
+	      md_number_to_chars ((char *)(buf + target_big_endian ? 0 : 4),
+				  hiv, 4);
 	    }
 	}
       break;
@@ -11890,8 +11828,7 @@ md_apply_fix3 (fixP, valP, seg)
 	 entry.  */
       if (fixP->fx_done
 	  || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
-	md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
-			    value, 4);
+	md_number_to_chars (buf, *valP, 4);
       break;
 
     case BFD_RELOC_16:
@@ -11899,8 +11836,7 @@ md_apply_fix3 (fixP, valP, seg)
          value now.  */
       assert (fixP->fx_size == 2);
       if (fixP->fx_done)
-	md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
-			    value, 2);
+	md_number_to_chars (buf, *valP, 2);
       break;
 
     case BFD_RELOC_LO16:
@@ -11908,82 +11844,69 @@ md_apply_fix3 (fixP, valP, seg)
 	 up deleting a LO16 reloc.  See the 'o' case in mips_ip.  */
       if (fixP->fx_done)
 	{
-	  if (value + 0x8000 > 0xffff)
+	  if (*valP + 0x8000 > 0xffff)
 	    as_bad_where (fixP->fx_file, fixP->fx_line,
 			  _("relocation overflow"));
-	  buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
 	  if (target_big_endian)
 	    buf += 2;
-	  md_number_to_chars ((char *) buf, value, 2);
+	  md_number_to_chars ((char *) buf, *valP, 2);
 	}
       break;
 
     case BFD_RELOC_16_PCREL_S2:
-      if ((value & 0x3) != 0)
+      if ((*valP & 0x3) != 0)
 	as_bad_where (fixP->fx_file, fixP->fx_line,
-		      _("Branch to odd address (%lx)"), (long) value);
+		      _("Branch to odd address (%lx)"), (long) *valP);
 
       /*
        * 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 (!fixP->fx_done && (value != 0 || HAVE_NEWABI))
+      if (! fixP->fx_done)
 	break;
-      /* If 'value' is zero, the remaining reloc code won't actually
-	 do the store, so it must be done here.  This is probably
-	 a bug somewhere.  */
-      if (!fixP->fx_done
-	  && (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
-	      || fixP->fx_addsy == NULL			/* ??? */
-	      || ! S_IS_DEFINED (fixP->fx_addsy)))
-	value -= fixP->fx_frag->fr_address + fixP->fx_where;
-
-      value = (offsetT) value >> 2;
 
       /* update old instruction data */
-      buf = (bfd_byte *) (fixP->fx_where + fixP->fx_frag->fr_literal);
       if (target_big_endian)
 	insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
       else
 	insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
 
-      if (value + 0x8000 <= 0xffff)
-	insn |= value & 0xffff;
-      else
+      if (*valP + 0x20000 <= 0x3ffff)
+	{
+	  insn |= (*valP >> 2) & 0xffff;
+	  md_number_to_chars ((char *) buf, (valueT) insn, 4);
+	}
+      else if (mips_pic == NO_PIC
+	       && fixP->fx_done
+	       && fixP->fx_frag->fr_address >= text_section->vma
+	       && (fixP->fx_frag->fr_address
+		   < text_section->vma + text_section->_raw_size)
+	       && ((insn & 0xffff0000) == 0x10000000	 /* beq $0,$0 */
+		   || (insn & 0xffff0000) == 0x04010000	 /* bgez $0 */
+		   || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
 	{
 	  /* The branch offset is too large.  If this is an
              unconditional branch, and we are not generating PIC code,
              we can convert it to an absolute jump instruction.  */
-	  if (mips_pic == NO_PIC
-	      && fixP->fx_done
-	      && fixP->fx_frag->fr_address >= text_section->vma
-	      && (fixP->fx_frag->fr_address
-		  < text_section->vma + text_section->_raw_size)
-	      && ((insn & 0xffff0000) == 0x10000000	 /* beq $0,$0 */
-		  || (insn & 0xffff0000) == 0x04010000	 /* bgez $0 */
-		  || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
-	    {
-	      if ((insn & 0xffff0000) == 0x04110000)	 /* bgezal $0 */
-		insn = 0x0c000000;	/* jal */
-	      else
-		insn = 0x08000000;	/* j */
-	      fixP->fx_r_type = BFD_RELOC_MIPS_JMP;
-	      fixP->fx_done = 0;
-	      fixP->fx_addsy = section_symbol (text_section);
-	      fixP->fx_addnumber = (value << 2) + md_pcrel_from (fixP);
-	    }
+	  if ((insn & 0xffff0000) == 0x04110000)	 /* bgezal $0 */
+	    insn = 0x0c000000;	/* jal */
 	  else
-	    {
-	      /* If we got here, we have branch-relaxation disabled,
-		 and there's nothing we can do to fix this instruction
-		 without turning it into a longer sequence.  */
-	      as_bad_where (fixP->fx_file, fixP->fx_line,
-			    _("Branch out of range"));
-	    }
+	    insn = 0x08000000;	/* j */
+	  fixP->fx_r_type = BFD_RELOC_MIPS_JMP;
+	  fixP->fx_done = 0;
+	  fixP->fx_addsy = section_symbol (text_section);
+	  *valP += md_pcrel_from (fixP);
+	  md_number_to_chars ((char *) buf, (valueT) insn, 4);
+	}
+      else
+	{
+	  /* If we got here, we have branch-relaxation disabled,
+	     and there's nothing we can do to fix this instruction
+	     without turning it into a longer sequence.  */
+	  as_bad_where (fixP->fx_file, fixP->fx_line,
+			_("Branch out of range"));
 	}
-
-      md_number_to_chars ((char *) buf, (valueT) insn, 4);
       break;
 
     case BFD_RELOC_VTABLE_INHERIT:
@@ -12001,6 +11924,9 @@ md_apply_fix3 (fixP, valP, seg)
     default:
       internalError ();
     }
+
+  /* Remember value for tc_gen_reloc.  */
+  fixP->fx_addnumber = *valP;
 }
 
 #if 0
@@ -13847,7 +13773,7 @@ tc_gen_reloc (section, fixp)
       reloc2->address = (reloc->address
 			 + (RELAX_RELOC2 (fixp->fx_frag->fr_subtype)
 			    - RELAX_RELOC1 (fixp->fx_frag->fr_subtype)));
-      reloc2->addend = fixp->fx_addnumber
+      reloc2->addend = fixp->fx_addnumber - S_GET_VALUE (fixp->fx_addsy)
 	+ fixp->fx_frag->tc_frag_data.tc_fr_offset;
       reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
       assert (reloc2->howto != NULL);
@@ -13951,27 +13877,6 @@ tc_gen_reloc (section, fixp)
 			bfd_get_reloc_code_name (code));
 	}
     }
-
-#ifdef OBJ_ELF
-  /* md_apply_fix3 has a double-subtraction hack to get
-     bfd_install_relocation to behave nicely.  GPREL relocations are
-     handled correctly without this hack, so undo it here.  We can't
-     stop md_apply_fix3 from subtracting twice in the first place since
-     the fake addend is required for variant frags above.  */
-  if (fixp->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour
-      && (code == BFD_RELOC_GPREL16 || code == BFD_RELOC_MIPS16_GPREL)
-      && reloc->addend != 0
-      && mips_need_elf_addend_fixup (fixp))
-    {
-      /* If howto->partial_inplace is false, md_apply_fix3 will only
-	 subtract it once.  */
-      reloc_howto_type *howto;
-
-      howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
-      if (howto->partial_inplace)
-	reloc->addend += S_GET_VALUE (fixp->fx_addsy);
-    }
-#endif
 
   /* To support a PC relative reloc when generating embedded PIC code
      for ECOFF, we use a Cygnus extension.  We check for that here to
diff -BurpNX /bigdisk/src/gcc-exclude source-orig/gas/config/tc-mips.h source/gas/config/tc-mips.h
--- source-orig/gas/config/tc-mips.h	Sun May 25 09:20:25 2003
+++ source/gas/config/tc-mips.h	Sun May 25 09:55:26 2003
@@ -129,6 +129,9 @@ extern void mips_frob_file_after_relocs 
 #define tc_fix_adjustable(fixp) mips_fix_adjustable (fixp)
 extern int mips_fix_adjustable PARAMS ((struct fix *));
 
+/* Values passed to md_apply_fix3 don't include symbol values.  */
+#define MD_APPLY_SYM_VALUE(FIX) 0
+
 /* Global syms must not be resolved, to support ELF shared libraries.
    When generating embedded code, we don't have shared libs.  */
 #define EXTERN_FORCE_RELOC			\


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