Blame SOURCES/gdb-rhbz1320945-power9-04of38.patch

a094f6
commit 86c9573369616e7437481b6e5533aef3a435cdcf
a094f6
Author: Alan Modra <amodra@gmail.com>
a094f6
Date:   Sat Mar 8 13:05:06 2014 +1030
a094f6
a094f6
    Better overflow checking for powerpc32 relocations
a094f6
    
a094f6
    Similar to the powerpc64 patch, this improves overflow checking in
a094f6
    elf32-ppc.c.  Many reloc "howto" entries needed fixes, some just
a094f6
    cosmetic.
a094f6
    
a094f6
    The patch also fixes the R_PPC_VLE_SDA21 reloc application code, which
a094f6
    was horribly broken.  In fact, it may still be broken since Power ISA
a094f6
    2.07 says e_li behaves as
a094f6
       RT <- EXTS(li20 1:4 || li20 5:8 || li20 0 || li20 9:19)
a094f6
    where li20 is a field taken from bits 17..20, 11..15, 21..31 of the
a094f6
    instruction.  Freescale VLEPEM says differently, and I assume
a094f6
    correctly, that
a094f6
       RT <- EXTS(li20 0:3 || li20 4:8 || li20 9:19)
a094f6
    The VLE_SDA21 relocation description matches this too.
a094f6
    
a094f6
    Now the VLE_SDA21 relocation specifies in the case where e_addi16 is
a094f6
    converted to e_li for symbols in .PPC.EMB.sdata0 or .PPC.EMB.sbss0
a094f6
    (no base register), that the field is restricted to 16 bits, with the
a094f6
    sign bit being propagated to the top 4 bits.  I don't see the sense in
a094f6
    restricting the value like this, so have allowed the full 20 bit
a094f6
    signed value.  This of course is compatible with the reloc description
a094f6
    in that values in the 16 bit signed range will result in exactly the
a094f6
    same insn field as when the reloc description is followed to the
a094f6
    letter.
a094f6
    
a094f6
            * elf32-ppc.c (ppc_elf_howto_raw): Correct overflow check for
a094f6
            many relocations.  Correct bitsize and rightshift too for a number
a094f6
            of VLE relocs.  Describe R_PPC_VLE_SDA21 and R_PPC_VLE_SDA21_LO.
a094f6
            Correct dst_mask on R_PPC_VLE_SDA21_LO.
a094f6
            (ppc_elf_vle_split16): Tidy, delete unnecessary prototype.
a094f6
            (ppc_elf_relocate_section): Modify overflow test for 16-bit
a094f6
            fields in instructions to signed/unsigned according to whether
a094f6
            the field takes a signed or unsigned value.  Tidy vle split16 code.
a094f6
            Correct R_PPC_VLE_SDA21 and R_PPC_VLE_SDA21_LO handling.
a094f6
a094f6
### a/bfd/ChangeLog
a094f6
### b/bfd/ChangeLog
a094f6
## -1,5 +1,17 @@
a094f6
 2014-03-08  Alan Modra  <amodra@gmail.com>
a094f6
 
a094f6
+	* elf32-ppc.c (ppc_elf_howto_raw): Correct overflow check for
a094f6
+	many relocations.  Correct bitsize and rightshift too for a number
a094f6
+	of VLE relocs.  Describe R_PPC_VLE_SDA21 and R_PPC_VLE_SDA21_LO.
a094f6
+	Correct dst_mask on R_PPC_VLE_SDA21_LO.
a094f6
+	(ppc_elf_vle_split16): Tidy, delete unnecessary prototype.
a094f6
+	(ppc_elf_relocate_section): Modify overflow test for 16-bit
a094f6
+	fields in instructions to signed/unsigned according to whether
a094f6
+	the field takes a signed or unsigned value.  Tidy vle split16 code.
a094f6
+	Correct R_PPC_VLE_SDA21 and R_PPC_VLE_SDA21_LO handling.
a094f6
+
a094f6
+2014-03-08  Alan Modra  <amodra@gmail.com>
a094f6
+
a094f6
 	* elf64-ppc.c (ppc64_elf_howto_raw): Use complain_overflow_signed
a094f6
 	for R_PPC64_ADDR14, R_PPC64_ADDR14_BRTAKEN, R_PPC64_ADDR14_BRNTAKEN,
a094f6
 	R_PPC64_SECTOFF, R_PPC64_ADDR16_DS, R_PPC64_SECTOFF_DS,
a094f6
--- a/bfd/elf32-ppc.c
a094f6
+++ b/bfd/elf32-ppc.c
a094f6
@@ -50,8 +50,6 @@ static bfd_reloc_status_type ppc_elf_addr16_ha_reloc
a094f6
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
a094f6
 static bfd_reloc_status_type ppc_elf_unhandled_reloc
a094f6
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
a094f6
-static void ppc_elf_vle_split16
a094f6
-  (bfd *, bfd_byte *, bfd_vma, bfd_vma, split16_format_type);
a094f6
 
a094f6
 /* Branch prediction bit for branch taken relocs.  */
a094f6
 #define BRANCH_PREDICT_BIT 0x200000
a094f6
@@ -192,7 +190,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_NONE",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -207,7 +205,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_ADDR32",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -223,7 +221,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 26,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_ADDR24",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -300,7 +298,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_ADDR14",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -317,7 +315,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_ADDR14_BRTAKEN",/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -334,7 +332,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_ADDR14_BRNTAKEN",/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -446,7 +444,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_GOT16_HI",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -462,7 +460,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 ppc_elf_addr16_ha_reloc, /* special_function */
a094f6
 	 "R_PPC_GOT16_HA",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -497,7 +495,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_COPY",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -513,7 +511,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_GLOB_DAT",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -528,7 +526,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_JMP_SLOT",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -545,7 +543,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_RELATIVE",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -577,7 +575,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_UADDR32",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -607,7 +605,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 TRUE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_REL32",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -623,7 +621,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_PLT32",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -639,7 +637,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 TRUE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_PLTREL32",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -671,7 +669,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_PLT16_HI",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -687,7 +685,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 ppc_elf_addr16_ha_reloc, /* special_function */
a094f6
 	 "R_PPC_PLT16_HA",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -718,7 +716,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_SECTOFF",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -748,7 +746,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_SECTOFF_HI",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -763,7 +761,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 ppc_elf_addr16_ha_reloc, /* special_function */
a094f6
 	 "R_PPC_SECTOFF_HA",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1239,7 +1237,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_EMB_NADDR32",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1254,7 +1252,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_EMB_NADDR16",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1449,10 +1447,10 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
   HOWTO (R_PPC_VLE_LO16A,	/* type */
a094f6
 	 0,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_LO16A",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1464,10 +1462,10 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
   HOWTO (R_PPC_VLE_LO16D,	/* type */
a094f6
 	 0,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_LO16D",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1477,12 +1475,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 split16a format.  */
a094f6
   HOWTO (R_PPC_VLE_HI16A,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_HI16A",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1492,12 +1490,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 split16d format.  */
a094f6
   HOWTO (R_PPC_VLE_HI16D,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_HI16D",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1507,12 +1505,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 (High Adjusted) in split16a format.  */
a094f6
   HOWTO (R_PPC_VLE_HA16A,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_HA16A",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1522,12 +1520,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 (High Adjusted) in split16d format.  */
a094f6
   HOWTO (R_PPC_VLE_HA16D,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_HA16D",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1535,14 +1533,16 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 0x1f07ff,		/* dst_mask */
a094f6
 	 FALSE),		/* pcrel_offset */
a094f6
 
a094f6
-  /* This reloc does nothing.  */
a094f6
-  HOWTO (R_PPC_VLE_SDA21,		/* type */
a094f6
+  /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i
a094f6
+     instructions.  If the register base is 0 then the linker changes
a094f6
+     the e_add16i to an e_li instruction.  */
a094f6
+  HOWTO (R_PPC_VLE_SDA21,	/* type */
a094f6
 	 0,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_VLE_SDA21",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1550,29 +1550,29 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 0xffff,		/* dst_mask */
a094f6
 	 FALSE),		/* pcrel_offset */
a094f6
 
a094f6
-  /* This reloc does nothing.  */
a094f6
+  /* Like R_PPC_VLE_SDA21 but ignore overflow.  */
a094f6
   HOWTO (R_PPC_VLE_SDA21_LO,	/* type */
a094f6
 	 0,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_VLE_SDA21_LO",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
 	 0,			/* src_mask */
a094f6
-	 0,			/* dst_mask */
a094f6
+	 0xffff,		/* dst_mask */
a094f6
 	 FALSE),		/* pcrel_offset */
a094f6
 
a094f6
   /* The 16 LSBS relative to _SDA_BASE_ in split16a format.  */
a094f6
   HOWTO (R_PPC_VLE_SDAREL_LO16A,/* type */
a094f6
 	 0,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield,	/* complain_on_overflow */
a094f6
+	 complain_overflow_dont,	/* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_SDAREL_LO16A",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1581,14 +1581,13 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 FALSE),		/* pcrel_offset */
a094f6
 
a094f6
   /* The 16 LSBS relative to _SDA_BASE_ in split16d format.  */
a094f6
-  /* This reloc does nothing.  */
a094f6
   HOWTO (R_PPC_VLE_SDAREL_LO16D, /* type */
a094f6
 	 0,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield,	/* complain_on_overflow */
a094f6
+	 complain_overflow_dont,	/* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_SDAREL_LO16D",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1598,12 +1597,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 relative to _SDA_BASE_ in split16a format.  */
a094f6
   HOWTO (R_PPC_VLE_SDAREL_HI16A,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield,	/* complain_on_overflow */
a094f6
+	 complain_overflow_dont,	/* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_SDAREL_HI16A",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1613,12 +1612,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 relative to _SDA_BASE_ in split16d format.  */
a094f6
   HOWTO (R_PPC_VLE_SDAREL_HI16D,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield,	/* complain_on_overflow */
a094f6
+	 complain_overflow_dont,	/* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_SDAREL_HI16D",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1628,12 +1627,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 (HA) relative to _SDA_BASE split16a format.  */
a094f6
   HOWTO (R_PPC_VLE_SDAREL_HA16A,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield,	/* complain_on_overflow */
a094f6
+	 complain_overflow_dont,	/* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_SDAREL_HA16A",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1643,12 +1642,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 
a094f6
   /* Bits 16-31 (HA) relative to _SDA_BASE split16d format.  */
a094f6
   HOWTO (R_PPC_VLE_SDAREL_HA16D,	/* type */
a094f6
-	 0,			/* rightshift */
a094f6
+	 16,			/* rightshift */
a094f6
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
a094f6
-	 32,			/* bitsize */
a094f6
+	 16,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield,	/* complain_on_overflow */
a094f6
+	 complain_overflow_dont,	/* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_VLE_SDAREL_HA16D",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1662,7 +1661,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 32,			/* bitsize */
a094f6
 	 FALSE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_dont, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	 /* special_function */
a094f6
 	 "R_PPC_IRELATIVE",	/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -1677,7 +1676,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
a094f6
 	 16,			/* bitsize */
a094f6
 	 TRUE,			/* pc_relative */
a094f6
 	 0,			/* bitpos */
a094f6
-	 complain_overflow_bitfield, /* complain_on_overflow */
a094f6
+	 complain_overflow_signed, /* complain_on_overflow */
a094f6
 	 bfd_elf_generic_reloc,	/* special_function */
a094f6
 	 "R_PPC_REL16",		/* name */
a094f6
 	 FALSE,			/* partial_inplace */
a094f6
@@ -4790,20 +4789,19 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
a094f6
 }
a094f6
 
a094f6
 static void
a094f6
-ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *contents,
a094f6
-                 bfd_vma offset, bfd_vma relocation,
a094f6
-		 split16_format_type split16_format)
a094f6
+ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *loc,
a094f6
+		     bfd_vma value,
a094f6
+		     split16_format_type split16_format)
a094f6
 
a094f6
 {
a094f6
-  bfd_vma insn, top5, bottom11;
a094f6
+  unsigned int insn, top5;
a094f6
 
a094f6
-  insn = bfd_get_32 (output_bfd, contents + offset);
a094f6
-  top5 = relocation >> 11;
a094f6
-  top5 = top5 << (split16_format == split16a_type ? 20 : 16);
a094f6
-  bottom11 = relocation & 0x7ff;
a094f6
+  insn = bfd_get_32 (output_bfd, loc);
a094f6
+  top5 = value & 0xf800;
a094f6
+  top5 = top5 << (split16_format == split16a_type ? 9 : 5);
a094f6
   insn |= top5;
a094f6
-  insn |= bottom11;
a094f6
-  bfd_put_32 (output_bfd, insn, contents + offset);
a094f6
+  insn |= value & 0x7ff;
a094f6
+  bfd_put_32 (output_bfd, insn, loc);
a094f6
 }
a094f6
 
a094f6
 
a094f6
@@ -7570,6 +7568,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
a094f6
       bfd_boolean warned;
a094f6
       unsigned int tls_type, tls_mask, tls_gd;
a094f6
       struct plt_entry **ifunc;
a094f6
+      struct reloc_howto_struct alt_howto;
a094f6
 
a094f6
       r_type = ELF32_R_TYPE (rel->r_info);
a094f6
       sym = NULL;
a094f6
@@ -8252,9 +8251,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
a094f6
 		 howto->name,
a094f6
 		 sym_name);
a094f6
 	  }
a094f6
-	break;
a094f6
+	  break;
a094f6
 
a094f6
-	/* Relocations that need no special processing.  */
a094f6
+	  /* Relocations that need no special processing.  */
a094f6
 	case R_PPC_LOCAL24PC:
a094f6
 	  /* It makes no sense to point a local relocation
a094f6
 	     at a symbol not in this object.  */
a094f6
@@ -8743,45 +8742,39 @@ ppc_elf_relocate_section (bfd *output_bfd,
a094f6
 	  break;
a094f6
 
a094f6
 	case R_PPC_VLE_LO16A:
a094f6
-	  relocation = (relocation + addend) & 0xffff;
a094f6
-	  ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                               relocation, split16a_type);
a094f6
+	  relocation = relocation + addend;
a094f6
+	  ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+			       relocation, split16a_type);
a094f6
 	  continue;
a094f6
 
a094f6
 	case R_PPC_VLE_LO16D:
a094f6
-	  relocation = (relocation + addend) & 0xffff;
a094f6
-	  ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                               relocation, split16d_type);
a094f6
+	  relocation = relocation + addend;
a094f6
+	  ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+			       relocation, split16d_type);
a094f6
 	  continue;
a094f6
 
a094f6
 	case R_PPC_VLE_HI16A:
a094f6
-	  relocation = ((relocation + addend) >> 16) & 0xffff;
a094f6
-	  ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                               relocation, split16a_type);
a094f6
+	  relocation = (relocation + addend) >> 16;
a094f6
+	  ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+			       relocation, split16a_type);
a094f6
 	  continue;
a094f6
 
a094f6
 	case R_PPC_VLE_HI16D:
a094f6
-	  relocation = ((relocation + addend) >> 16) & 0xffff;
a094f6
-	  ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                               relocation, split16d_type);
a094f6
+	  relocation = (relocation + addend) >> 16;
a094f6
+	  ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+			       relocation, split16d_type);
a094f6
 	  continue;
a094f6
 
a094f6
 	case R_PPC_VLE_HA16A:
a094f6
-	  {
a094f6
-	    bfd_vma value = relocation + addend;
a094f6
-	    value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
a094f6
-	    ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                 value, split16a_type);
a094f6
-	  }
a094f6
+	  relocation = (relocation + addend + 0x8000) >> 16;
a094f6
+	  ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+			       relocation, split16a_type);
a094f6
 	  continue;
a094f6
 
a094f6
 	case R_PPC_VLE_HA16D:
a094f6
-	  {
a094f6
-	    bfd_vma value = relocation + addend;
a094f6
-	    value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
a094f6
-	    ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                 value, split16d_type);
a094f6
-	  }
a094f6
+	  relocation = (relocation + addend + 0x8000) >> 16;
a094f6
+	  ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+			       relocation, split16d_type);
a094f6
 	  continue;
a094f6
 
a094f6
 	  /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0.  */
a094f6
@@ -8792,6 +8785,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
a094f6
 	  {
a094f6
 	    const char *name;
a094f6
 	    int reg;
a094f6
+	    unsigned int insn;
a094f6
 	    struct elf_link_hash_entry *sda = NULL;
a094f6
 
a094f6
 	    if (sec == NULL || sec->output_section == NULL)
a094f6
@@ -8845,32 +8839,40 @@ ppc_elf_relocate_section (bfd *output_bfd,
a094f6
 		addend -= SYM_VAL (sda);
a094f6
 	      }
a094f6
 
a094f6
+	    insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
a094f6
 	    if (reg == 0
a094f6
 		&& (r_type == R_PPC_VLE_SDA21
a094f6
 		    || r_type == R_PPC_VLE_SDA21_LO))
a094f6
 	      {
a094f6
-		/* Use the split20 format.  */
a094f6
-		bfd_vma insn, bits12to15, bits21to31;
a094f6
-		bfd_vma value  = (relocation + rel->r_offset) & 0xffff;
a094f6
-		/* Propagate sign bit, if necessary.  */
a094f6
-		insn = (value & 0x8000) ? 0x70107800 : 0x70000000;
a094f6
-		bits12to15 = value & 0x700;
a094f6
-		bits21to31 = value & 0x7ff;
a094f6
-		insn |= bits12to15;
a094f6
-		insn |= bits21to31;
a094f6
-  		bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
a094f6
-		continue;
a094f6
+		relocation = relocation + addend;
a094f6
+		addend = 0;
a094f6
+
a094f6
+		/* Force e_li insn, keeping RT from original insn.  */
a094f6
+		insn &= 0x1f << 21;
a094f6
+		insn |= 28u << 26;
a094f6
+
a094f6
+		/* We have an li20 field, bits 17..20, 11..15, 21..31.  */
a094f6
+		/* Top 4 bits of value to 17..20.  */
a094f6
+		insn |= (relocation & 0xf0000) >> 5;
a094f6
+		/* Next 5 bits of the value to 11..15.  */
a094f6
+		insn |= (relocation & 0xf800) << 5;
a094f6
+		/* And the final 11 bits of the value to bits 21 to 31.  */
a094f6
+		insn |= relocation & 0x7ff;
a094f6
+
a094f6
+		/* Use _bfd_final_link_relocate to report overflow,
a094f6
+		   but do so with a value that won't modify the insn.  */
a094f6
+		if (relocation + 0x80000 > 0x100000)
a094f6
+		  addend = 0x100000;
a094f6
+		relocation = 0;
a094f6
 	      }
a094f6
 	    else if (r_type == R_PPC_EMB_SDA21
a094f6
 		     || r_type == R_PPC_VLE_SDA21
a094f6
 		     || r_type == R_PPC_VLE_SDA21_LO)
a094f6
 	      {
a094f6
-		bfd_vma insn;  /* Fill in register field.  */
a094f6
-
a094f6
-		insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
a094f6
+		/* Fill in register field.  */
a094f6
 		insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
a094f6
-		bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
a094f6
 	      }
a094f6
+	    bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
a094f6
 	  }
a094f6
 	  break;
a094f6
 
a094f6
@@ -8931,46 +8933,39 @@ ppc_elf_relocate_section (bfd *output_bfd,
a094f6
 		  }
a094f6
 	      }
a094f6
 
a094f6
-	   value = sda->root.u.def.section->output_section->vma
a094f6
-   		   + sda->root.u.def.section->output_offset;
a094f6
-
a094f6
-	   if (r_type == R_PPC_VLE_SDAREL_LO16A)
a094f6
-	      {
a094f6
-		value = (value + addend) & 0xffff;
a094f6
-	        ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                     value, split16a_type);
a094f6
-	      }
a094f6
-	   else if (r_type == R_PPC_VLE_SDAREL_LO16D)
a094f6
-	      {
a094f6
-		value = (value + addend) & 0xffff;
a094f6
-	        ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                     value, split16d_type);
a094f6
-	      }
a094f6
-	   else if (r_type == R_PPC_VLE_SDAREL_HI16A)
a094f6
+	    value = (sda->root.u.def.section->output_section->vma
a094f6
+		     + sda->root.u.def.section->output_offset
a094f6
+		     + addend);
a094f6
+
a094f6
+	    if (r_type == R_PPC_VLE_SDAREL_LO16A)
a094f6
+	      ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+				   value, split16a_type);
a094f6
+	    else if (r_type == R_PPC_VLE_SDAREL_LO16D)
a094f6
+	      ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+				   value, split16d_type);
a094f6
+	    else if (r_type == R_PPC_VLE_SDAREL_HI16A)
a094f6
 	      {
a094f6
-		value = ((value + addend) >> 16) & 0xffff;
a094f6
-	        ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                     value, split16a_type);
a094f6
+		value = value >> 16;
a094f6
+		ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+				     value, split16a_type);
a094f6
 	      }
a094f6
-	   else if (r_type == R_PPC_VLE_SDAREL_HI16D)
a094f6
+	    else if (r_type == R_PPC_VLE_SDAREL_HI16D)
a094f6
 	      {
a094f6
-		value = ((value + addend) >> 16) & 0xffff;
a094f6
-	        ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                     value, split16d_type);
a094f6
+		value = value >> 16;
a094f6
+		ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+				     value, split16d_type);
a094f6
 	      }
a094f6
-	   else if (r_type == R_PPC_VLE_SDAREL_HA16A)
a094f6
+	    else if (r_type == R_PPC_VLE_SDAREL_HA16A)
a094f6
 	      {
a094f6
-		value += addend;
a094f6
-		value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
a094f6
-	        ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                     value, split16a_type);
a094f6
+		value = (value + 0x8000) >> 16;
a094f6
+		ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+				     value, split16a_type);
a094f6
 	      }
a094f6
-	   else if (r_type == R_PPC_VLE_SDAREL_HA16D)
a094f6
+	    else if (r_type == R_PPC_VLE_SDAREL_HA16D)
a094f6
 	      {
a094f6
-		value += addend;
a094f6
-		value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
a094f6
-	        ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
a094f6
-                                     value, split16d_type);
a094f6
+		value = (value + 0x8000) >> 16;
a094f6
+		ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
a094f6
+				     value, split16d_type);
a094f6
 	      }
a094f6
 	  }
a094f6
 	  continue;
a094f6
@@ -9130,13 +9125,36 @@ ppc_elf_relocate_section (bfd *output_bfd,
a094f6
 	  ret = FALSE;
a094f6
 	}
a094f6
 
a094f6
-      r = _bfd_final_link_relocate (howto,
a094f6
-				    input_bfd,
a094f6
-				    input_section,
a094f6
-				    contents,
a094f6
-				    rel->r_offset,
a094f6
-				    relocation,
a094f6
-				    addend);
a094f6
+      /* 16-bit fields in insns mostly have signed values, but a
a094f6
+	 few insns have 16-bit unsigned values.  Really, we should
a094f6
+	 have different reloc types.  */
a094f6
+      if (howto->complain_on_overflow != complain_overflow_dont
a094f6
+	  && howto->dst_mask == 0xffff
a094f6
+	  && (input_section->flags & SEC_CODE) != 0)
a094f6
+	{
a094f6
+	  enum complain_overflow complain = complain_overflow_signed;
a094f6
+
a094f6
+	  if ((elf_section_flags (input_section) & SHF_PPC_VLE) == 0)
a094f6
+	    {
a094f6
+	      unsigned int insn;
a094f6
+
a094f6
+	      insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
a094f6
+	      if ((insn & (0x3f << 26)) == 28u << 26 /* andi */
a094f6
+		  || (insn & (0x3f << 26)) == 24u << 26 /* ori */
a094f6
+		  || (insn & (0x3f << 26)) == 26u << 26 /* xori */
a094f6
+		  || (insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
a094f6
+		complain = complain_overflow_unsigned;
a094f6
+	    }
a094f6
+	  if (howto->complain_on_overflow != complain)
a094f6
+	    {
a094f6
+	      alt_howto = *howto;
a094f6
+	      alt_howto.complain_on_overflow = complain;
a094f6
+	      howto = &alt_howto;
a094f6
+	    }
a094f6
+	}
a094f6
+
a094f6
+      r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
a094f6
+				    rel->r_offset, relocation, addend);
a094f6
 
a094f6
       if (r != bfd_reloc_ok)
a094f6
 	{