* Makefile.am: Remove all mention of elflink.h.
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
index 518073644e61c0c1cd9b730b214e97d08e5fb7b9..b9dcf3c5ae72a1cdba8d3d71a3d18a71f2ea243b 100644 (file)
@@ -1,25 +1,25 @@
 /* V850-specific support for 32-bit ELF
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char
-   dependencies.  As is the gas & simulator code or the v850.  */
+   dependencies.  As is the gas & simulator code for the v850.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -30,65 +30,69 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "libiberty.h"
 
 /* Sign-extend a 24-bit number.  */
-#define SEXT24(x)      ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
+#define SEXT24(x)      ((((x) & 0xffffff) ^ 0x800000) - 0x800000)
 
 static reloc_howto_type *v850_elf_reloc_type_lookup
   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
 static void v850_elf_info_to_howto_rel
-  PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
 static void v850_elf_info_to_howto_rela
-  PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
+  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
 static bfd_reloc_status_type v850_elf_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static boolean v850_elf_is_local_label_name
+static bfd_boolean v850_elf_is_local_label_name
   PARAMS ((bfd *, const char *));
-static boolean v850_elf_relocate_section
+static bfd_boolean v850_elf_relocate_section
   PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 static bfd_reloc_status_type v850_elf_perform_relocation
-  PARAMS ((bfd *, int, bfd_vma, bfd_byte *));
-static boolean v850_elf_check_relocs
+  PARAMS ((bfd *, unsigned int, bfd_vma, bfd_byte *));
+static bfd_boolean v850_elf_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
 static void remember_hi16s_reloc
   PARAMS ((bfd *, bfd_vma, bfd_byte *));
 static bfd_byte * find_remembered_hi16s_reloc
-  PARAMS ((bfd_vma, boolean *));
+  PARAMS ((bfd_vma, bfd_boolean *));
 static bfd_reloc_status_type v850_elf_final_link_relocate
   PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma,
           bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int));
-static boolean v850_elf_object_p
+static bfd_boolean v850_elf_object_p
   PARAMS ((bfd *));
-static boolean v850_elf_fake_sections
-  PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
+static bfd_boolean v850_elf_fake_sections
+  PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
 static void v850_elf_final_write_processing
-  PARAMS ((bfd *, boolean));
-static boolean v850_elf_set_private_flags
+  PARAMS ((bfd *, bfd_boolean));
+static bfd_boolean v850_elf_set_private_flags
   PARAMS ((bfd *, flagword));
-static boolean v850_elf_copy_private_bfd_data
+static bfd_boolean v850_elf_merge_private_bfd_data
   PARAMS ((bfd *, bfd *));
-static boolean v850_elf_merge_private_bfd_data
-  PARAMS ((bfd *, bfd *));
-static boolean v850_elf_print_private_bfd_data
+static bfd_boolean v850_elf_print_private_bfd_data
   PARAMS ((bfd *, PTR));
-static boolean v850_elf_section_from_bfd_section
-  PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *));
+static bfd_boolean v850_elf_section_from_bfd_section
+  PARAMS ((bfd *, asection *, int *));
 static void v850_elf_symbol_processing
   PARAMS ((bfd *, asymbol *));
-static boolean v850_elf_add_symbol_hook
-  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+static bfd_boolean v850_elf_add_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
           const char **, flagword *, asection **, bfd_vma *));
-static boolean v850_elf_link_output_symbol_hook
-  PARAMS ((bfd *, struct bfd_link_info *, const char *,
-          Elf_Internal_Sym *, asection *));
-static boolean v850_elf_section_from_shdr
-  PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
-static boolean v850_elf_gc_sweep_hook
+static bfd_boolean v850_elf_link_output_symbol_hook
+  PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
+          asection *, struct elf_link_hash_entry *));
+static bfd_boolean v850_elf_section_from_shdr
+  PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
+static bfd_boolean v850_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
 static asection * v850_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *,
+  PARAMS ((asection *, struct bfd_link_info *,
           Elf_Internal_Rela *, struct elf_link_hash_entry *,
           Elf_Internal_Sym *));
+static bfd_reloc_status_type v850_elf_ignore_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_boolean v850_elf_relax_delete_bytes
+  PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int));
+static bfd_boolean v850_elf_relax_section
+  PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
 
 /* Note: It is REQUIRED that the 'type' value of each entry
    in this array match the index of the entry in the array.  */
@@ -99,376 +103,436 @@ static reloc_howto_type v850_elf_howto_table[] =
         0,                             /* rightshift */
         2,                             /* size (0 = byte, 1 = short, 2 = long) */
         32,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_bitfield,    /* complain_on_overflow */
         bfd_elf_generic_reloc,         /* special_function */
         "R_V850_NONE",                 /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0,                             /* src_mask */
         0,                             /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* A PC relative 9 bit branch.  */
   HOWTO (R_V850_9_PCREL,               /* type */
         2,                             /* rightshift */
         2,                             /* size (0 = byte, 1 = short, 2 = long) */
         26,                            /* bitsize */
-        true,                          /* pc_relative */
+        TRUE,                          /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_bitfield,    /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_9_PCREL",              /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x00ffffff,                    /* src_mask */
         0x00ffffff,                    /* dst_mask */
-        true),                         /* pcrel_offset */
+        TRUE),                         /* pcrel_offset */
 
   /* A PC relative 22 bit branch.  */
   HOWTO (R_V850_22_PCREL,              /* type */
         2,                             /* rightshift */
         2,                             /* size (0 = byte, 1 = short, 2 = long) */
         22,                            /* bitsize */
-        true,                          /* pc_relative */
+        TRUE,                          /* pc_relative */
         7,                             /* bitpos */
         complain_overflow_signed,      /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_22_PCREL",             /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x07ffff80,                    /* src_mask */
         0x07ffff80,                    /* dst_mask */
-        true),                         /* pcrel_offset */
+        TRUE),                         /* pcrel_offset */
 
   /* High 16 bits of symbol value.  */
   HOWTO (R_V850_HI16_S,                        /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_HI16_S",               /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xffff,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* High 16 bits of symbol value.  */
   HOWTO (R_V850_HI16,                  /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_HI16",                 /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xffff,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* Low 16 bits of symbol value.  */
   HOWTO (R_V850_LO16,                  /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_LO16",                 /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xffff,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* Simple 32bit reloc.  */
-  HOWTO (R_V850_32,                    /* type */
+  HOWTO (R_V850_ABS32,                 /* type */
         0,                             /* rightshift */
         2,                             /* size (0 = byte, 1 = short, 2 = long) */
         32,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
-        "R_V850_32",                   /* name */
-        false,                         /* partial_inplace */
+        "R_V850_ABS32",                /* name */
+        FALSE,                         /* partial_inplace */
         0xffffffff,                    /* src_mask */
         0xffffffff,                    /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* Simple 16bit reloc.  */
   HOWTO (R_V850_16,                    /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         bfd_elf_generic_reloc,         /* special_function */
         "R_V850_16",                   /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xffff,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* Simple 8bit reloc.         */
   HOWTO (R_V850_8,                     /* type */
         0,                             /* rightshift */
         0,                             /* size (0 = byte, 1 = short, 2 = long) */
         8,                             /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         bfd_elf_generic_reloc,         /* special_function */
         "R_V850_8",                    /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xff,                          /* src_mask */
         0xff,                          /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 16 bit offset from the short data area pointer.  */
   HOWTO (R_V850_SDA_16_16_OFFSET,      /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_SDA_16_16_OFFSET",     /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xffff,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 15 bit offset from the short data area pointer.  */
   HOWTO (R_V850_SDA_15_16_OFFSET,      /* type */
         1,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         1,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_SDA_15_16_OFFSET",     /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xfffe,                        /* src_mask */
         0xfffe,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 16 bit offset from the zero data area pointer.  */
   HOWTO (R_V850_ZDA_16_16_OFFSET,      /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_ZDA_16_16_OFFSET",     /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xffff,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 15 bit offset from the zero data area pointer.  */
   HOWTO (R_V850_ZDA_15_16_OFFSET,      /* type */
         1,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         1,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_ZDA_15_16_OFFSET",     /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xfffe,                        /* src_mask */
         0xfffe,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 6 bit offset from the tiny data area pointer.  */
   HOWTO (R_V850_TDA_6_8_OFFSET,                /* type */
         2,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         8,                             /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         1,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_TDA_6_8_OFFSET",       /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x7e,                          /* src_mask */
         0x7e,                          /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 8 bit offset from the tiny data area pointer.  */
   HOWTO (R_V850_TDA_7_8_OFFSET,                /* type */
         1,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         8,                             /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_TDA_7_8_OFFSET",       /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x7f,                          /* src_mask */
         0x7f,                          /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 7 bit offset from the tiny data area pointer.  */
   HOWTO (R_V850_TDA_7_7_OFFSET,                /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         7,                             /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_TDA_7_7_OFFSET",       /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x7f,                          /* src_mask */
         0x7f,                          /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 16 bit offset from the tiny data area pointer!  */
   HOWTO (R_V850_TDA_16_16_OFFSET,      /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_TDA_16_16_OFFSET",     /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xfff,                         /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 5 bit offset from the tiny data area pointer.  */
   HOWTO (R_V850_TDA_4_5_OFFSET,                /* type */
         1,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         5,                             /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_TDA_4_5_OFFSET",       /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x0f,                          /* src_mask */
         0x0f,                          /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 4 bit offset from the tiny data area pointer.  */
   HOWTO (R_V850_TDA_4_4_OFFSET,                /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         4,                             /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_TDA_4_4_OFFSET",       /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x0f,                          /* src_mask */
         0x0f,                          /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 16 bit offset from the short data area pointer.  */
   HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET,        /* type */
         0,                             /* rightshift */
         2,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_SDA_16_16_SPLIT_OFFSET",/* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xfffe0020,                    /* src_mask */
         0xfffe0020,                    /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 16 bit offset from the zero data area pointer.  */
   HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET,        /* type */
         0,                             /* rightshift */
         2,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_ZDA_16_16_SPLIT_OFFSET",/* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xfffe0020,                    /* src_mask */
         0xfffe0020,                    /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 6 bit offset from the call table base pointer.  */
   HOWTO (R_V850_CALLT_6_7_OFFSET,      /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         7,                             /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_CALLT_6_7_OFFSET",     /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0x3f,                          /* src_mask */
         0x3f,                          /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 16 bit offset from the call table base pointer.  */
   HOWTO (R_V850_CALLT_16_16_OFFSET,    /* type */
         0,                             /* rightshift */
         1,                             /* size (0 = byte, 1 = short, 2 = long) */
         16,                            /* bitsize */
-        false,                         /* pc_relative */
+        FALSE,                         /* pc_relative */
         0,                             /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         v850_elf_reloc,                /* special_function */
         "R_V850_CALLT_16_16_OFFSET",   /* name */
-        false,                         /* partial_inplace */
+        FALSE,                         /* partial_inplace */
         0xffff,                        /* src_mask */
         0xffff,                        /* dst_mask */
-        false),                        /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* GNU extension to record C++ vtable hierarchy */
   HOWTO (R_V850_GNU_VTINHERIT, /* type */
          0,                     /* rightshift */
          2,                     /* size (0 = byte, 1 = short, 2 = long) */
          0,                     /* bitsize */
-         false,                 /* pc_relative */
+         FALSE,                 /* pc_relative */
          0,                     /* bitpos */
          complain_overflow_dont, /* complain_on_overflow */
          NULL,                  /* special_function */
          "R_V850_GNU_VTINHERIT", /* name */
-         false,                 /* partial_inplace */
+         FALSE,                 /* partial_inplace */
          0,                     /* src_mask */
          0,                     /* dst_mask */
-         false),                /* pcrel_offset */
+         FALSE),                /* pcrel_offset */
 
   /* GNU extension to record C++ vtable member usage */
   HOWTO (R_V850_GNU_VTENTRY,     /* type */
          0,                     /* rightshift */
          2,                     /* size (0 = byte, 1 = short, 2 = long) */
          0,                     /* bitsize */
-         false,                 /* pc_relative */
+         FALSE,                 /* pc_relative */
          0,                     /* bitpos */
          complain_overflow_dont, /* complain_on_overflow */
          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
          "R_V850_GNU_VTENTRY",   /* name */
-         false,                 /* partial_inplace */
+         FALSE,                 /* partial_inplace */
          0,                     /* src_mask */
          0,                     /* dst_mask */
-         false),                /* pcrel_offset */
-
+         FALSE),                /* pcrel_offset */
+
+  /* Indicates a .longcall pseudo-op.  The compiler will generate a .longcall
+     pseudo-op when it finds a function call which can be relaxed.  */
+  HOWTO (R_V850_LONGCALL,     /* type */
+       0,                     /* rightshift */
+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
+       32,                    /* bitsize */
+       TRUE,                  /* pc_relative */
+       0,                     /* bitpos */
+       complain_overflow_signed, /* complain_on_overflow */
+       v850_elf_ignore_reloc, /* special_function */
+       "R_V850_LONGCALL",     /* name */
+       FALSE,                 /* partial_inplace */
+       0,                     /* src_mask */
+       0,                     /* dst_mask */
+       TRUE),                 /* pcrel_offset */
+
+  /* Indicates a .longjump pseudo-op.  The compiler will generate a
+     .longjump pseudo-op when it finds a branch which can be relaxed.  */
+  HOWTO (R_V850_LONGJUMP,     /* type */
+       0,                     /* rightshift */
+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
+       32,                    /* bitsize */
+       TRUE,                  /* pc_relative */
+       0,                     /* bitpos */
+       complain_overflow_signed, /* complain_on_overflow */
+       v850_elf_ignore_reloc, /* special_function */
+       "R_V850_LONGJUMP",     /* name */
+       FALSE,                 /* partial_inplace */
+       0,                     /* src_mask */
+       0,                     /* dst_mask */
+       TRUE),                 /* pcrel_offset */
+
+  HOWTO (R_V850_ALIGN,        /* type */
+       0,                     /* rightshift */
+       1,                     /* size (0 = byte, 1 = short, 2 = long) */
+       0,                     /* bitsize */
+       FALSE,                 /* pc_relative */
+       0,                     /* bitpos */
+       complain_overflow_unsigned, /* complain_on_overflow */
+       v850_elf_ignore_reloc, /* special_function */
+       "R_V850_ALIGN",        /* name */
+       FALSE,                 /* partial_inplace */
+       0,                     /* src_mask */
+       0,                     /* dst_mask */
+       TRUE),                 /* pcrel_offset */
+  
+  /* Simple pc-relative 32bit reloc.  */
+  HOWTO (R_V850_REL32,                 /* type */
+        0,                             /* rightshift */
+        2,                             /* size (0 = byte, 1 = short, 2 = long) */
+        32,                            /* bitsize */
+        TRUE,                          /* pc_relative */
+        0,                             /* bitpos */
+        complain_overflow_dont,        /* complain_on_overflow */
+        v850_elf_reloc,                /* special_function */
+        "R_V850_REL32",                /* name */
+        FALSE,                         /* partial_inplace */
+        0xffffffff,                    /* src_mask */
+        0xffffffff,                    /* dst_mask */
+        FALSE),                        /* pcrel_offset */
 };
 
 /* Map BFD reloc types to V850 ELF reloc types.  */
@@ -483,31 +547,35 @@ struct v850_elf_reloc_map
 
 static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
 {
-  { BFD_RELOC_NONE,            R_V850_NONE },
-  { BFD_RELOC_V850_9_PCREL,    R_V850_9_PCREL },
-  { BFD_RELOC_V850_22_PCREL,   R_V850_22_PCREL },
-  { BFD_RELOC_HI16_S,          R_V850_HI16_S },
-  { BFD_RELOC_HI16,            R_V850_HI16 },
-  { BFD_RELOC_LO16,            R_V850_LO16 },
-  { BFD_RELOC_32,              R_V850_32 },
-  { BFD_RELOC_16,              R_V850_16 },
-  { BFD_RELOC_8,               R_V850_8 },
-  { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET },
-  { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET },
-  { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET },
-  { BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET },
-  { BFD_RELOC_V850_TDA_6_8_OFFSET,   R_V850_TDA_6_8_OFFSET   },
-  { BFD_RELOC_V850_TDA_7_8_OFFSET,   R_V850_TDA_7_8_OFFSET   },
-  { BFD_RELOC_V850_TDA_7_7_OFFSET,   R_V850_TDA_7_7_OFFSET   },
-  { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
+  { BFD_RELOC_NONE,                       R_V850_NONE                   },
+  { BFD_RELOC_V850_9_PCREL,               R_V850_9_PCREL                },
+  { BFD_RELOC_V850_22_PCREL,              R_V850_22_PCREL               },
+  { BFD_RELOC_HI16_S,                     R_V850_HI16_S                 },
+  { BFD_RELOC_HI16,                       R_V850_HI16                   },
+  { BFD_RELOC_LO16,                       R_V850_LO16                   },
+  { BFD_RELOC_32,                         R_V850_ABS32                  },
+  { BFD_RELOC_32_PCREL,                           R_V850_REL32                  },
+  { BFD_RELOC_16,                         R_V850_16                     },
+  { BFD_RELOC_8,                          R_V850_8                      },
+  { BFD_RELOC_V850_SDA_16_16_OFFSET,       R_V850_SDA_16_16_OFFSET       },
+  { BFD_RELOC_V850_SDA_15_16_OFFSET,       R_V850_SDA_15_16_OFFSET       },
+  { BFD_RELOC_V850_ZDA_16_16_OFFSET,       R_V850_ZDA_16_16_OFFSET       },
+  { BFD_RELOC_V850_ZDA_15_16_OFFSET,       R_V850_ZDA_15_16_OFFSET       },
+  { BFD_RELOC_V850_TDA_6_8_OFFSET,         R_V850_TDA_6_8_OFFSET         },
+  { BFD_RELOC_V850_TDA_7_8_OFFSET,         R_V850_TDA_7_8_OFFSET         },
+  { BFD_RELOC_V850_TDA_7_7_OFFSET,         R_V850_TDA_7_7_OFFSET         },
+  { BFD_RELOC_V850_TDA_16_16_OFFSET,       R_V850_TDA_16_16_OFFSET       },
   { BFD_RELOC_V850_TDA_4_5_OFFSET,         R_V850_TDA_4_5_OFFSET         },
   { BFD_RELOC_V850_TDA_4_4_OFFSET,         R_V850_TDA_4_4_OFFSET         },
   { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
   { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
   { BFD_RELOC_V850_CALLT_6_7_OFFSET,       R_V850_CALLT_6_7_OFFSET       },
   { BFD_RELOC_V850_CALLT_16_16_OFFSET,     R_V850_CALLT_16_16_OFFSET     },
-  { BFD_RELOC_VTABLE_INHERIT,               R_V850_GNU_VTINHERIT },
-  { BFD_RELOC_VTABLE_ENTRY,                 R_V850_GNU_VTENTRY },
+  { BFD_RELOC_VTABLE_INHERIT,              R_V850_GNU_VTINHERIT          },
+  { BFD_RELOC_VTABLE_ENTRY,                R_V850_GNU_VTENTRY            },
+  { BFD_RELOC_V850_LONGCALL,               R_V850_LONGCALL               },
+  { BFD_RELOC_V850_LONGJUMP,               R_V850_LONGJUMP               },
+  { BFD_RELOC_V850_ALIGN,                  R_V850_ALIGN                  },
 
 };
 \f
@@ -515,8 +583,8 @@ static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
 
 static reloc_howto_type *
 v850_elf_reloc_type_lookup (abfd, code)
-     bfd *                     abfd ATTRIBUTE_UNUSED;
-     bfd_reloc_code_real_type  code;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     bfd_reloc_code_real_type code;
 {
   unsigned int i;
 
@@ -524,7 +592,7 @@ v850_elf_reloc_type_lookup (abfd, code)
     if (v850_elf_reloc_map[i].bfd_reloc_val == code)
       {
        unsigned int elf_reloc_val = v850_elf_reloc_map[i].elf_reloc_val;
-       
+
        BFD_ASSERT (v850_elf_howto_table[elf_reloc_val].type == elf_reloc_val);
 
        return v850_elf_howto_table + elf_reloc_val;
@@ -537,9 +605,9 @@ v850_elf_reloc_type_lookup (abfd, code)
 
 static void
 v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
-     bfd *                 abfd ATTRIBUTE_UNUSED;
-     arelent *             cache_ptr;
-     Elf32_Internal_Rel *  dst;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *cache_ptr;
+     Elf_Internal_Rela *dst;
 {
   unsigned int r_type;
 
@@ -551,9 +619,9 @@ v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
 /* Set the howto pointer for a V850 ELF reloc (type RELA).  */
 static void
 v850_elf_info_to_howto_rela (abfd, cache_ptr, dst)
-     bfd *                 abfd ATTRIBUTE_UNUSED;
-     arelent *             cache_ptr;
-     Elf32_Internal_Rela   *dst;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent * cache_ptr;
+     Elf_Internal_Rela *dst;
 {
   unsigned int r_type;
 
@@ -566,14 +634,14 @@ v850_elf_info_to_howto_rela (abfd, cache_ptr, dst)
    allocate space in the global offset table or procedure linkage
    table.  */
 
-static boolean
+static bfd_boolean
 v850_elf_check_relocs (abfd, info, sec, relocs)
-     bfd *                      abfd;
-     struct bfd_link_info *     info;
-     asection *                 sec;
-     const Elf_Internal_Rela *  relocs;
+     bfd *abfd;
+     struct bfd_link_info *info;
+     asection *sec;
+     const Elf_Internal_Rela *relocs;
 {
-  boolean ret = true;
+  bfd_boolean ret = TRUE;
   bfd *dynobj;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -584,13 +652,13 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
   int other = 0;
   const char *common = (const char *)0;
 
-  if (info->relocateable)
-    return true;
+  if (info->relocatable)
+    return TRUE;
 
 #ifdef DEBUG
   fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
           bfd_get_section_name (abfd, sec),
-          bfd_get_filename (abfd));
+          bfd_archive_filename (abfd));
 #endif
 
   dynobj = elf_hash_table (info)->dynobj;
@@ -620,7 +688,8 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
        case R_V850_HI16_S:
        case R_V850_HI16:
        case R_V850_LO16:
-       case R_V850_32:
+       case R_V850_ABS32:
+       case R_V850_REL32:
        case R_V850_16:
        case R_V850_8:
        case R_V850_CALLT_6_7_OFFSET:
@@ -630,15 +699,15 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
         /* This relocation describes the C++ object vtable hierarchy.
            Reconstruct it for later use during GC.  */
         case R_V850_GNU_VTINHERIT:
-          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-            return false;
+          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+            return FALSE;
           break;
 
         /* This relocation describes which C++ vtable entries
           are actually used.  Record for later use during GC.  */
         case R_V850_GNU_VTENTRY:
-          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-            return false;
+          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+            return FALSE;
           break;
 
        case R_V850_SDA_16_16_SPLIT_OFFSET:
@@ -699,11 +768,12 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
 
                  sprintf (buff, msg, h->root.root.string);
                  info->callbacks->warning (info, buff, h->root.root.string,
-                                           abfd, h->root.u.def.section, 0);
+                                           abfd, h->root.u.def.section,
+                                           (bfd_vma) 0);
 
                  bfd_set_error (bfd_error_bad_value);
                  h->other |= V850_OTHER_ERROR;
-                 ret = false;
+                 ret = FALSE;
                }
            }
 
@@ -735,7 +805,7 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
    more than once, as the second attempted retry failed.
 
    In the current version, the entry is not deleted, instead we set
-   the field 'found' to true.  If a second lookup matches the same
+   the field 'found' to TRUE.  If a second lookup matches the same
    entry, then we know that the hi16s reloc has already been updated
    and does not need to be updated a second time.
 
@@ -745,29 +815,30 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
 
 typedef struct hi16s_location
 {
-  bfd_vma       addend;
-  bfd_byte *    address;
+  bfd_vma addend;
+  bfd_byte *address;
   unsigned long counter;
-  boolean       found;
-  struct hi16s_location * next;
+  bfd_boolean found;
+  struct hi16s_location *next;
 }
 hi16s_location;
 
-static hi16s_location *  previous_hi16s;
-static hi16s_location *  free_hi16s;
-static unsigned long     hi16s_counter;
+static hi16s_location *previous_hi16s;
+static hi16s_location *free_hi16s;
+static unsigned long hi16s_counter;
 
 static void
 remember_hi16s_reloc (abfd, addend, address)
-     bfd *      abfd;
-     bfd_vma    addend;
-     bfd_byte * address;
+     bfd *abfd;
+     bfd_vma addend;
+     bfd_byte *address;
 {
   hi16s_location * entry = NULL;
+  bfd_size_type amt = sizeof (* free_hi16s);
 
   /* Find a free structure.  */
   if (free_hi16s == NULL)
-    free_hi16s = (hi16s_location *) bfd_zalloc (abfd, sizeof (* free_hi16s));
+    free_hi16s = (hi16s_location *) bfd_zalloc (abfd, amt);
 
   entry      = free_hi16s;
   free_hi16s = free_hi16s->next;
@@ -775,7 +846,7 @@ remember_hi16s_reloc (abfd, addend, address)
   entry->addend  = addend;
   entry->address = address;
   entry->counter = hi16s_counter ++;
-  entry->found   = false;
+  entry->found   = FALSE;
   entry->next    = previous_hi16s;
   previous_hi16s = entry;
 
@@ -794,14 +865,14 @@ remember_hi16s_reloc (abfd, addend, address)
 
 static bfd_byte *
 find_remembered_hi16s_reloc (addend, already_found)
-     bfd_vma   addend;
-     boolean * already_found;
+     bfd_vma addend;
+     bfd_boolean *already_found;
 {
-  hi16s_location * match = NULL;
-  hi16s_location * entry;
-  hi16s_location * previous = NULL;
-  hi16s_location * prev;
-  bfd_byte *       addr;
+  hi16s_location *match = NULL;
+  hi16s_location *entry;
+  hi16s_location *previous = NULL;
+  hi16s_location *prev;
+  bfd_byte *addr;
 
   /* Search the table.  Record the most recent entry that matches.  */
   for (entry = previous_hi16s; entry; entry = entry->next)
@@ -822,25 +893,25 @@ find_remembered_hi16s_reloc (addend, already_found)
   /* Extract the address.  */
   addr = match->address;
 
-  /* Remeber if this entry has already been used before.  */
+  /* Remember if this entry has already been used before.  */
   if (already_found)
     * already_found = match->found;
 
   /* Note that this entry has now been used.  */
-  match->found = true;
+  match->found = TRUE;
 
   return addr;
 }
 
 /* FIXME:  The code here probably ought to be removed and the code in reloc.c
-   allowed to do its  stuff instead.  At least for most of the relocs, anwyay.  */
+   allowed to do its stuff instead.  At least for most of the relocs, anyway.  */
 
 static bfd_reloc_status_type
 v850_elf_perform_relocation (abfd, r_type, addend, address)
-     bfd *      abfd;
-     int        r_type;
-     bfd_vma    addend;
-     bfd_byte * address;
+     bfd *abfd;
+     unsigned int r_type;
+     bfd_vma addend;
+     bfd_byte *address;
 {
   unsigned long insn;
   bfd_signed_vma saddend = (bfd_signed_vma) addend;
@@ -851,7 +922,8 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
       /* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */
       return bfd_reloc_notsupported;
 
-    case R_V850_32:
+    case R_V850_REL32:
+    case R_V850_ABS32:
       bfd_put_32 (abfd, addend, address);
       return bfd_reloc_ok;
 
@@ -865,7 +937,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
       insn  = bfd_get_32 (abfd, address);
       insn &= ~0xfffe003f;
       insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16));
-      bfd_put_32 (abfd, insn, address);
+      bfd_put_32 (abfd, (bfd_vma) insn, address);
       return bfd_reloc_ok;
 
     case R_V850_9_PCREL:
@@ -1053,8 +1125,8 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
            || (OVERFLOWS (addend, insn)
                && ((! BIT15_SET (insn)) || (BIT15_SET (addend)))))
          {
-           boolean already_updated;
-           bfd_byte * hi16s_address = find_remembered_hi16s_reloc
+           bfd_boolean already_updated;
+           bfd_byte *hi16s_address = find_remembered_hi16s_reloc
              (addend, & already_updated);
 
            /* Amend the matching HI16_S relocation.  */
@@ -1064,7 +1136,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
                  {
                    insn = bfd_get_16 (abfd, hi16s_address);
                    insn += 1;
-                   bfd_put_16 (abfd, insn, hi16s_address);
+                   bfd_put_16 (abfd, (bfd_vma) insn, hi16s_address);
                  }
              }
            else
@@ -1130,7 +1202,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
       if (addend & 1)
         return bfd_reloc_dangerous;
 
-      insn = (addend & ~1) | (insn & 1);
+      insn = (addend &~ (bfd_vma) 1) | (insn & 1);
       break;
 
     case R_V850_TDA_6_8_OFFSET:
@@ -1219,9 +1291,9 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
 
       insn &= 0x0001ffdf;
       insn |= (addend & 1) << 5;
-      insn |= (addend & ~1) << 16;
+      insn |= (addend &~ (bfd_vma) 1) << 16;
 
-      bfd_put_32 (abfd, insn, address);
+      bfd_put_32 (abfd, (bfd_vma) insn, address);
       return bfd_reloc_ok;
 
     case R_V850_CALLT_6_7_OFFSET:
@@ -1246,7 +1318,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
 
     }
 
-  bfd_put_16 (abfd, insn, address);
+  bfd_put_16 (abfd, (bfd_vma) insn, address);
   return bfd_reloc_ok;
 }
 \f
@@ -1254,13 +1326,13 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
 
 static bfd_reloc_status_type
 v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
-     bfd *       abfd ATTRIBUTE_UNUSED;
-     arelent *   reloc;
-     asymbol *   symbol;
-     PTR         data ATTRIBUTE_UNUSED;
-     asection *  isection;
-     bfd *       obfd;
-     char **     err ATTRIBUTE_UNUSED;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *reloc;
+     asymbol *symbol;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *isection;
+     bfd *obfd;
+     char **err ATTRIBUTE_UNUSED;
 {
   long relocation;
 
@@ -1277,10 +1349,6 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
       reloc->address += isection->output_offset;
       return bfd_reloc_ok;
     }
-#if 0
-  else if (obfd != NULL)
-    return bfd_reloc_continue;
-#endif
 
   /* Catch relocs involving undefined symbols.  */
   if (bfd_is_und_section (symbol->section)
@@ -1294,9 +1362,12 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
   if (reloc->address > isection->_cooked_size)
     return bfd_reloc_outofrange;
 
-  /* Work out which section the relocation is targetted at and the
+  /* Work out which section the relocation is targeted at and the
      initial relocation command value.  */
 
+  if (reloc->howto->pc_relative)
+    return bfd_reloc_ok;
+
   /* Get symbol value.  (Common symbols are special.)  */
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
@@ -1315,14 +1386,14 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
                .text
                .globl _start
                nop
-       _start:         
+       _start:
                jr foo
 
                .section ".foo","ax"
                nop
        foo:
                nop      */
-  if (reloc->howto->pc_relative == true)
+  if (reloc->howto->pc_relative)
     {
       /* Here the variable relocation holds the final address of the
         symbol we are relocating against, plus any addend.  */
@@ -1335,36 +1406,61 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
   reloc->addend = relocation;
   return bfd_reloc_ok;
 }
+
+/* This function is used for relocs which are only used
+   for relaxing, which the linker should otherwise ignore.  */
+
+static bfd_reloc_status_type
+v850_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
+                       output_bfd, error_message)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *reloc_entry;
+     asymbol *symbol ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message ATTRIBUTE_UNUSED;
+{
+  if (output_bfd != NULL)
+    reloc_entry->address += input_section->output_offset;
+
+  return bfd_reloc_ok;
+}
 \f
-static boolean
+static bfd_boolean
 v850_elf_is_local_label_name (abfd, name)
-     bfd *         abfd ATTRIBUTE_UNUSED;
-     const char *  name;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     const char *name;
 {
   return (   (name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
          || (name[0] == '_' &&  name[1] == '.' && name[2] == 'L' && name[3] == '_'));
 }
 \f
+/* We overload some of the bfd_reloc error codes for own purposes.  */
+#define bfd_reloc_gp_not_found         bfd_reloc_other
+#define bfd_reloc_ep_not_found         bfd_reloc_continue
+#define bfd_reloc_ctbp_not_found       (bfd_reloc_dangerous + 1)
+
 /* Perform a relocation as part of a final link.  */
 
 static bfd_reloc_status_type
 v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
-                                   input_section, contents, offset, value,
-                                   addend, info, sym_sec, is_local)
-     reloc_howto_type *      howto;
-     bfd *                   input_bfd;
-     bfd *                   output_bfd ATTRIBUTE_UNUSED;
-     asection *              input_section;
-     bfd_byte *              contents;
-     bfd_vma                 offset;
-     bfd_vma                 value;
-     bfd_vma                 addend;
-     struct bfd_link_info *  info;
-     asection *              sym_sec;
-     int                     is_local ATTRIBUTE_UNUSED;
+                             input_section, contents, offset, value,
+                             addend, info, sym_sec, is_local)
+     reloc_howto_type *howto;
+     bfd *input_bfd;
+     bfd *output_bfd ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd_byte *contents;
+     bfd_vma offset;
+     bfd_vma value;
+     bfd_vma addend;
+     struct bfd_link_info *info;
+     asection *sym_sec;
+     int is_local ATTRIBUTE_UNUSED;
 {
-  unsigned long  r_type   = howto->type;
-  bfd_byte *     hit_data = contents + offset;
+  unsigned int r_type = howto->type;
+  bfd_byte *hit_data = contents + offset;
 
   /* Adjust the value according to the relocation.  */
   switch (r_type)
@@ -1388,11 +1484,17 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
       value = SEXT24 (value);
       break;
 
+    case R_V850_REL32:
+      value -= (input_section->output_section->vma
+               + input_section->output_offset
+               + offset);
+      break;
+
     case R_V850_HI16_S:
     case R_V850_HI16:
     case R_V850_LO16:
     case R_V850_16:
-    case R_V850_32:
+    case R_V850_ABS32:
     case R_V850_8:
       break;
 
@@ -1416,10 +1518,10 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
          return bfd_reloc_undefined;
 
        /* Get the value of __gp.  */
-       h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
+       h = bfd_link_hash_lookup (info->hash, "__gp", FALSE, FALSE, TRUE);
        if (h == (struct bfd_link_hash_entry *) NULL
            || h->type != bfd_link_hash_defined)
-         return bfd_reloc_other;
+         return bfd_reloc_gp_not_found;
 
        gp = (h->u.def.value
              + h->u.def.section->output_section->vma
@@ -1441,11 +1543,10 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
        struct bfd_link_hash_entry * h;
 
        /* Get the value of __ep.  */
-       h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
+       h = bfd_link_hash_lookup (info->hash, "__ep", FALSE, FALSE, TRUE);
        if (h == (struct bfd_link_hash_entry *) NULL
            || h->type != bfd_link_hash_defined)
-         /* Actually this indicates that __ep could not be found.  */
-         return bfd_reloc_continue;
+         return bfd_reloc_ep_not_found;
 
        ep = (h->u.def.value
              + h->u.def.section->output_section->vma
@@ -1461,11 +1562,10 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
        struct bfd_link_hash_entry * h;
 
        /* Get the value of __ctbp.  */
-       h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
+       h = bfd_link_hash_lookup (info->hash, "__ctbp", FALSE, FALSE, TRUE);
        if (h == (struct bfd_link_hash_entry *) NULL
            || h->type != bfd_link_hash_defined)
-         /* Actually this indicates that __ctbp could not be found.  */
-         return bfd_reloc_dangerous + 1;
+         return bfd_reloc_ctbp_not_found;
 
        ctbp = (h->u.def.value
              + h->u.def.section->output_section->vma
@@ -1483,10 +1583,10 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
          return bfd_reloc_undefined;
 
        /* Get the value of __ctbp.  */
-       h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
+       h = bfd_link_hash_lookup (info->hash, "__ctbp", FALSE, FALSE, TRUE);
        if (h == (struct bfd_link_hash_entry *) NULL
            || h->type != bfd_link_hash_defined)
-         return (bfd_reloc_dangerous + 1);
+         return bfd_reloc_ctbp_not_found;
 
        ctbp = (h->u.def.value
              + h->u.def.section->output_section->vma
@@ -1500,6 +1600,9 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
     case R_V850_NONE:
     case R_V850_GNU_VTINHERIT:
     case R_V850_GNU_VTENTRY:
+    case R_V850_LONGCALL:
+    case R_V850_LONGJUMP:
+    case R_V850_ALIGN:
       return bfd_reloc_ok;
 
     default:
@@ -1512,22 +1615,25 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
 \f
 /* Relocate an V850 ELF section.  */
 
-static boolean
+static bfd_boolean
 v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                           contents, relocs, local_syms, local_sections)
-     bfd *                  output_bfd;
-     struct bfd_link_info * info;
-     bfd *                  input_bfd;
-     asection *             input_section;
-     bfd_byte *             contents;
-     Elf_Internal_Rela *    relocs;
-     Elf_Internal_Sym *     local_syms;
-     asection **            local_sections;
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     bfd_byte *contents;
+     Elf_Internal_Rela *relocs;
+     Elf_Internal_Sym *local_syms;
+     asection **local_sections;
 {
-  Elf_Internal_Shdr *           symtab_hdr;
-  struct elf_link_hash_entry ** sym_hashes;
-  Elf_Internal_Rela *           rel;
-  Elf_Internal_Rela *           relend;
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  Elf_Internal_Rela *rel;
+  Elf_Internal_Rela *relend;
+
+  if (info->relocatable)
+    return TRUE;
 
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
@@ -1535,9 +1641,10 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   if (sym_hashes == NULL)
     {
       info->callbacks->warning
-       (info, "no hash table available", NULL, input_bfd, input_section, 0);
+       (info, "no hash table available",
+        NULL, input_bfd, input_section, (bfd_vma) 0);
 
-      return false;
+      return FALSE;
     }
 
   /* Reset the list of remembered HI16S relocs to empty.  */
@@ -1549,14 +1656,14 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; rel++)
     {
-      int                          r_type;
-      reloc_howto_type *           howto;
-      unsigned long                r_symndx;
-      Elf_Internal_Sym *           sym;
-      asection *                   sec;
-      struct elf_link_hash_entry * h;
-      bfd_vma                      relocation;
-      bfd_reloc_status_type        r;
+      int r_type;
+      reloc_howto_type *howto;
+      unsigned long r_symndx;
+      Elf_Internal_Sym *sym;
+      asection *sec;
+      struct elf_link_hash_entry *h;
+      bfd_vma relocation;
+      bfd_reloc_status_type r;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type   = ELF32_R_TYPE (rel->r_info);
@@ -1565,28 +1672,8 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
           || r_type == R_V850_GNU_VTINHERIT)
         continue;
 
-      howto = v850_elf_howto_table + r_type;
-
-      if (info->relocateable)
-       {
-         /* This is a relocateable link.  We don't have to change
-             anything, unless the reloc is against a section symbol,
-             in which case we have to adjust according to where the
-             section symbol winds up in the output section.  */
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             sym = local_syms + r_symndx;
-             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               {
-                 sec = local_sections[r_symndx];
-                 rel->r_addend += sec->output_offset + sym->st_value;
-               }
-           }
-
-         continue;
-       }
-
       /* This is a final link.  */
+      howto = v850_elf_howto_table + r_type;
       h = NULL;
       sym = NULL;
       sec = NULL;
@@ -1594,9 +1681,7 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        {
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
-         relocation = (sec->output_section->vma
-                       + sec->output_offset
-                       + sym->st_value);
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
 #if 0
          {
            char * name;
@@ -1611,43 +1696,12 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        }
       else
        {
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+         bfd_boolean unresolved_reloc, warned;
 
-         if (h->root.type == bfd_link_hash_defined
-             || h->root.type == bfd_link_hash_defweak)
-           {
-             sec = h->root.u.def.section;
-             relocation = (h->root.u.def.value
-                           + sec->output_section->vma
-                           + sec->output_offset);
-#if 0
-             fprintf (stderr, "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
-                      sec->name, h->root.root.string, h->root.u.def.value, sec->output_section->vma, sec->output_offset, relocation);
-#endif
-           }
-         else if (h->root.type == bfd_link_hash_undefweak)
-           {
-#if 0
-             fprintf (stderr, "undefined: sec: %s, name: %s\n",
-                      sec->name, h->root.root.string);
-#endif
-             relocation = 0;
-           }
-         else
-           {
-             if (! ((*info->callbacks->undefined_symbol)
-                    (info, h->root.root.string, input_bfd,
-                     input_section, rel->r_offset, true)))
-               return false;
-#if 0
-             fprintf (stderr, "unknown: name: %s\n", h->root.root.string);
-#endif
-             relocation = 0;
-           }
+         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                  r_symndx, symtab_hdr, sym_hashes,
+                                  h, sec, relocation,
+                                  unresolved_reloc, warned);
        }
 
       /* FIXME: We should use the addend, but the COFF relocations don't.  */
@@ -1678,14 +1732,14 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              if (! ((*info->callbacks->reloc_overflow)
                     (info, name, howto->name, (bfd_vma) 0,
                      input_bfd, input_section, rel->r_offset)))
-               return false;
+               return FALSE;
              break;
 
            case bfd_reloc_undefined:
              if (! ((*info->callbacks->undefined_symbol)
                     (info, name, input_bfd, input_section,
-                     rel->r_offset, true)))
-               return false;
+                     rel->r_offset, TRUE)))
+               return FALSE;
              break;
 
            case bfd_reloc_outofrange:
@@ -1700,15 +1754,15 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              msg = _("internal error: dangerous relocation");
              goto common_error;
 
-           case bfd_reloc_other:
+           case bfd_reloc_gp_not_found:
              msg = _("could not locate special linker symbol __gp");
              goto common_error;
 
-           case bfd_reloc_continue:
+           case bfd_reloc_ep_not_found:
              msg = _("could not locate special linker symbol __ep");
              goto common_error;
 
-           case (bfd_reloc_dangerous + 1):
+           case bfd_reloc_ctbp_not_found:
              msg = _("could not locate special linker symbol __ctbp");
              goto common_error;
 
@@ -1720,16 +1774,16 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              if (!((*info->callbacks->warning)
                    (info, msg, name, input_bfd, input_section,
                     rel->r_offset)))
-               return false;
+               return FALSE;
              break;
            }
        }
     }
 
-  return true;
+  return TRUE;
 }
 
-static boolean
+static bfd_boolean
 v850_elf_gc_sweep_hook (abfd, info, sec, relocs)
      bfd *abfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -1737,12 +1791,12 @@ v850_elf_gc_sweep_hook (abfd, info, sec, relocs)
      const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
 {
   /* No got and plt entries for v850-elf.  */
-  return true;
+  return TRUE;
 }
 
 static asection *
-v850_elf_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
+v850_elf_gc_mark_hook (sec, info, rel, h, sym)
+       asection *sec;
        struct bfd_link_info *info ATTRIBUTE_UNUSED;
        Elf_Internal_Rela *rel;
        struct elf_link_hash_entry *h;
@@ -1772,49 +1826,48 @@ v850_elf_gc_mark_hook (abfd, info, rel, h, sym)
        }
      }
    else
-     {
-       if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-          {
-            return bfd_section_from_elf_index (abfd, sym->st_shndx);
-          }
-      }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
   return NULL;
 }
 
 /* Set the right machine number.  */
 
-static boolean
+static bfd_boolean
 v850_elf_object_p (abfd)
      bfd *abfd;
 {
   switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
     {
     default:
-    case E_V850_ARCH:   (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
-    case E_V850E_ARCH:  (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
-    case E_V850EA_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850ea); break;
+    case E_V850_ARCH:
+      bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850);
+      break;
+    case E_V850E_ARCH:
+      bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e);
+      break;
+    case E_V850E1_ARCH:
+      bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e1);
+      break;
     }
-  return true;
+  return TRUE;
 }
 
 /* Store the machine number in the flags field.  */
 
 static void
 v850_elf_final_write_processing (abfd, linker)
-     bfd *   abfd;
-     boolean linker ATTRIBUTE_UNUSED;
+     bfd *abfd;
+     bfd_boolean linker ATTRIBUTE_UNUSED;
 {
   unsigned long val;
 
   switch (bfd_get_mach (abfd))
     {
     default:
-    case 0: val = E_V850_ARCH; break;
-    case bfd_mach_v850e:  val = E_V850E_ARCH; break;
-    case bfd_mach_v850ea: val = E_V850EA_ARCH;  break;
+    case bfd_mach_v850:  val = E_V850_ARCH; break;
+    case bfd_mach_v850e: val = E_V850E_ARCH; break;
+    case bfd_mach_v850e1: val = E_V850E1_ARCH;  break;
     }
 
   elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
@@ -1823,54 +1876,32 @@ v850_elf_final_write_processing (abfd, linker)
 
 /* Function to keep V850 specific file flags.  */
 
-static boolean
+static bfd_boolean
 v850_elf_set_private_flags (abfd, flags)
-     bfd *    abfd;
+     bfd *abfd;
      flagword flags;
 {
   BFD_ASSERT (!elf_flags_init (abfd)
              || elf_elfheader (abfd)->e_flags == flags);
 
   elf_elfheader (abfd)->e_flags = flags;
-  elf_flags_init (abfd) = true;
-  return true;
-}
-
-/* Copy backend specific data from one object module to another.  */
-
-static boolean
-v850_elf_copy_private_bfd_data (ibfd, obfd)
-     bfd * ibfd;
-     bfd * obfd;
-{
-  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
-
-  BFD_ASSERT (!elf_flags_init (obfd)
-             || (elf_elfheader (obfd)->e_flags
-                 == elf_elfheader (ibfd)->e_flags));
-
-  elf_gp (obfd) = elf_gp (ibfd);
-  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
-  elf_flags_init (obfd) = true;
-
-  return true;
+  elf_flags_init (abfd) = TRUE;
+  return TRUE;
 }
 
 /* Merge backend specific data from an object file
    to the output object file when linking.  */
-static boolean
+static bfd_boolean
 v850_elf_merge_private_bfd_data (ibfd, obfd)
-     bfd * ibfd;
-     bfd * obfd;
+     bfd *ibfd;
+     bfd *obfd;
 {
   flagword out_flags;
   flagword in_flags;
 
   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
   in_flags = elf_elfheader (ibfd)->e_flags;
   out_flags = elf_elfheader (obfd)->e_flags;
@@ -1884,36 +1915,52 @@ v850_elf_merge_private_bfd_data (ibfd, obfd)
         unitialised values, which surprise surprise, correspond
         to the default values.  */
       if (bfd_get_arch_info (ibfd)->the_default)
-       return true;
+       return TRUE;
 
-      elf_flags_init (obfd) = true;
+      elf_flags_init (obfd) = TRUE;
       elf_elfheader (obfd)->e_flags = in_flags;
 
       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
          && bfd_get_arch_info (obfd)->the_default)
        return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
 
-      return true;
+      return TRUE;
     }
 
   /* Check flag compatibility.  */
   if (in_flags == out_flags)
-    return true;
+    return TRUE;
 
   if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH)
       && (in_flags & EF_V850_ARCH) != E_V850_ARCH)
-    _bfd_error_handler (_("%s: Architecture mismatch with previous modules"),
-                       bfd_get_filename (ibfd));
+    {
+      /* Allow v850e1 binaries to be linked with v850e binaries.
+        Set the output binary to v850e.  */
+      if ((in_flags & EF_V850_ARCH) == E_V850E1_ARCH
+         && (out_flags & EF_V850_ARCH) == E_V850E_ARCH)
+       return TRUE;
+
+      if ((in_flags & EF_V850_ARCH) == E_V850E_ARCH
+         && (out_flags & EF_V850_ARCH) == E_V850E1_ARCH)
+       {
+         elf_elfheader (obfd)->e_flags =
+           ((out_flags & ~ EF_V850_ARCH) | E_V850E_ARCH);
+         return TRUE;
+       }
+
+      _bfd_error_handler (_("%s: Architecture mismatch with previous modules"),
+                         bfd_archive_filename (ibfd));
+    }
 
-  return true;
+  return TRUE;
 }
 
 /* Display the flags field.  */
 
-static boolean
+static bfd_boolean
 v850_elf_print_private_bfd_data (abfd, ptr)
-     bfd *   abfd;
-     PTR     ptr;
+     bfd *abfd;
+     PTR ptr;
 {
   FILE * file = (FILE *) ptr;
 
@@ -1929,12 +1976,12 @@ v850_elf_print_private_bfd_data (abfd, ptr)
     default:
     case E_V850_ARCH: fprintf (file, _("v850 architecture")); break;
     case E_V850E_ARCH:  fprintf (file, _("v850e architecture")); break;
-    case E_V850EA_ARCH: fprintf (file, _("v850ea architecture")); break;
+    case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break;
     }
 
   fputc ('\n', file);
 
-  return true;
+  return TRUE;
 }
 
 /* V850 ELF uses four common sections.  One is the usual one, and the
@@ -1957,12 +2004,11 @@ static asymbol * v850_elf_zcom_symbol_ptr;
 /* Given a BFD section, try to locate the
    corresponding ELF section index.  */
 
-static boolean
-v850_elf_section_from_bfd_section (abfd, hdr, sec, retval)
-     bfd *                 abfd ATTRIBUTE_UNUSED;
-     Elf32_Internal_Shdr * hdr ATTRIBUTE_UNUSED;
-     asection *            sec;
-     int *                 retval;
+static bfd_boolean
+v850_elf_section_from_bfd_section (abfd, sec, retval)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec;
+     int *retval;
 {
   if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
     *retval = SHN_V850_SCOMMON;
@@ -1971,22 +2017,22 @@ v850_elf_section_from_bfd_section (abfd, hdr, sec, retval)
   else if (strcmp (bfd_get_section_name (abfd, sec), ".zcommon") == 0)
     *retval = SHN_V850_ZCOMMON;
   else
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 /* Handle the special V850 section numbers that a symbol may use.  */
 
 static void
 v850_elf_symbol_processing (abfd, asym)
-     bfd *     abfd;
-     asymbol * asym;
+     bfd *abfd;
+     asymbol *asym;
 {
   elf_symbol_type * elfsym = (elf_symbol_type *) asym;
-  unsigned short index;
+  unsigned int indx;
 
-  index = elfsym->internal_elf_sym.st_shndx;
+  indx = elfsym->internal_elf_sym.st_shndx;
 
   /* If the section index is an "ordinary" index, then it may
      refer to a v850 specific section created by the assembler.
@@ -1994,26 +2040,26 @@ v850_elf_symbol_processing (abfd, asym)
 
      FIXME: Should we alter the st_shndx field as well ?  */
 
-  if (index < elf_elfheader(abfd)[0].e_shnum)
-    switch (elf_elfsections(abfd)[index]->sh_type)
+  if (indx < elf_numsections (abfd))
+    switch (elf_elfsections(abfd)[indx]->sh_type)
       {
       case SHT_V850_SCOMMON:
-       index = SHN_V850_SCOMMON;
+       indx = SHN_V850_SCOMMON;
        break;
 
       case SHT_V850_TCOMMON:
-       index = SHN_V850_TCOMMON;
+       indx = SHN_V850_TCOMMON;
        break;
 
       case SHT_V850_ZCOMMON:
-       index = SHN_V850_ZCOMMON;
+       indx = SHN_V850_ZCOMMON;
        break;
 
       default:
        break;
       }
 
-  switch (index)
+  switch (indx)
     {
     case SHN_V850_SCOMMON:
       if (v850_elf_scom_section.name == NULL)
@@ -2074,17 +2120,17 @@ v850_elf_symbol_processing (abfd, asym)
 /* Hook called by the linker routine which adds symbols from an object
    file.  We must handle the special v850 section numbers here.  */
 
-static boolean
+static bfd_boolean
 v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
-     bfd *                    abfd;
-     struct bfd_link_info *   info ATTRIBUTE_UNUSED;
-     const Elf_Internal_Sym * sym;
-     const char **            namep ATTRIBUTE_UNUSED;
-     flagword *               flagsp ATTRIBUTE_UNUSED;
-     asection **              secp;
-     bfd_vma *                valp;
+     bfd *abfd;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     Elf_Internal_Sym *sym;
+     const char **namep ATTRIBUTE_UNUSED;
+     flagword *flagsp ATTRIBUTE_UNUSED;
+     asection **secp;
+     bfd_vma *valp;
 {
-  int index = sym->st_shndx;
+  unsigned int indx = sym->st_shndx;
 
   /* If the section index is an "ordinary" index, then it may
      refer to a v850 specific section created by the assembler.
@@ -2092,26 +2138,26 @@ v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
      FIXME: Should we alter the st_shndx field as well ?  */
 
-  if (index < elf_elfheader(abfd)[0].e_shnum)
-    switch (elf_elfsections(abfd)[index]->sh_type)
+  if (indx < elf_numsections (abfd))
+    switch (elf_elfsections(abfd)[indx]->sh_type)
       {
       case SHT_V850_SCOMMON:
-       index = SHN_V850_SCOMMON;
+       indx = SHN_V850_SCOMMON;
        break;
 
       case SHT_V850_TCOMMON:
-       index = SHN_V850_TCOMMON;
+       indx = SHN_V850_TCOMMON;
        break;
 
       case SHT_V850_ZCOMMON:
-       index = SHN_V850_ZCOMMON;
+       indx = SHN_V850_ZCOMMON;
        break;
 
       default:
        break;
       }
 
-  switch (index)
+  switch (indx)
     {
     case SHN_V850_SCOMMON:
       *secp = bfd_make_section_old_way (abfd, ".scommon");
@@ -2132,16 +2178,16 @@ v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
       break;
     }
 
-  return true;
+  return TRUE;
 }
 
-static boolean
-v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
-     bfd *                  abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info * info ATTRIBUTE_UNUSED;
-     const char *           name ATTRIBUTE_UNUSED;
-     Elf_Internal_Sym *     sym;
-     asection *             input_sec;
+static bfd_boolean
+v850_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     const char *name ATTRIBUTE_UNUSED;
+     Elf_Internal_Sym *sym;
+     asection *input_sec;
+     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED;
 {
   /* If we see a common symbol, which implies a relocatable link, then
      if a symbol was in a special common section in an input file, mark
@@ -2157,21 +2203,21 @@ v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
        sym->st_shndx = SHN_V850_ZCOMMON;
     }
 
-  return true;
+  return TRUE;
 }
 
-static boolean
+static bfd_boolean
 v850_elf_section_from_shdr (abfd, hdr, name)
-     bfd *               abfd;
-     Elf_Internal_Shdr * hdr;
-     char *              name;
+     bfd *abfd;
+     Elf_Internal_Shdr *hdr;
+     const char *name;
 {
   /* There ought to be a place to keep ELF backend specific flags, but
      at the moment there isn't one.  We just keep track of the
      sections by their name, instead.  */
 
   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
-    return false;
+    return FALSE;
 
   switch (hdr->sh_type)
     {
@@ -2182,20 +2228,20 @@ v850_elf_section_from_shdr (abfd, hdr, name)
                                   (bfd_get_section_flags (abfd,
                                                           hdr->bfd_section)
                                    | SEC_IS_COMMON)))
-       return false;
+       return FALSE;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Set the correct type for a V850 ELF section.  We do this
    by the section name, which is a hack, but ought to work.  */
 
-static boolean
+static bfd_boolean
 v850_elf_fake_sections (abfd, hdr, sec)
-     bfd *                 abfd ATTRIBUTE_UNUSED;
-     Elf32_Internal_Shdr * hdr;
-     asection *            sec;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     Elf_Internal_Shdr *hdr;
+     asection *sec;
 {
   register const char * name;
 
@@ -2212,13 +2258,914 @@ v850_elf_fake_sections (abfd, hdr, sec)
   else if (strcmp (name, ".zcommon") == 0)
     hdr->sh_type = SHT_V850_ZCOMMON;
 
-  return true;
+  return TRUE;
+}
+
+/* Delete some bytes from a section while relaxing.  */
+
+static bfd_boolean
+v850_elf_relax_delete_bytes (abfd, sec, addr, toaddr, count)
+     bfd *abfd;
+     asection *sec;
+     bfd_vma addr;
+     bfd_vma toaddr;
+     int count;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf32_External_Sym *extsyms;
+  Elf32_External_Sym *esym;
+  Elf32_External_Sym *esymend;
+  int index;
+  unsigned int sec_shndx;
+  bfd_byte *contents;
+  Elf_Internal_Rela *irel;
+  Elf_Internal_Rela *irelend;
+  struct elf_link_hash_entry *sym_hash;
+  Elf_Internal_Shdr *shndx_hdr;
+  Elf_External_Sym_Shndx *shndx;
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
+
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+
+  contents = elf_section_data (sec)->this_hdr.contents;
+
+  /* The deletion must stop at the next ALIGN reloc for an alignment
+     power larger than the number of bytes we are deleting.  */
+
+  /* Actually delete the bytes.  */
+#if (DEBUG_RELAX & 2)
+  fprintf (stderr, "relax_delete: contents: sec: %s  %p .. %p %x\n",
+          sec->name, addr, toaddr, count );
+#endif
+  memmove (contents + addr, contents + addr + count,
+          toaddr - addr - count);
+  memset (contents + toaddr-count, 0, count);
+
+  /* Adjust all the relocs.  */
+  irel = elf_section_data (sec)->relocs;
+  irelend = irel + sec->reloc_count;
+  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
+
+  for (; irel < irelend; irel++)
+    {
+      bfd_vma raddr, paddr, symval;
+      Elf_Internal_Sym isym;
+
+      /* Get the new reloc address.  */
+      raddr = irel->r_offset;
+      if ((raddr >= (addr + count) && raddr < toaddr))
+       irel->r_offset -= count;
+
+      if (raddr >= addr && raddr < addr + count)
+       {
+         irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                      (int) R_V850_NONE);
+         continue;
+       }
+
+      if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN)
+       continue;
+
+      bfd_elf32_swap_symbol_in (abfd,
+                               extsyms + ELF32_R_SYM (irel->r_info),
+                               shndx ? shndx + ELF32_R_SYM (irel->r_info) : NULL,
+                               & isym);
+
+      if (isym.st_shndx != sec_shndx)
+       continue;
+
+      /* Get the value of the symbol referred to by the reloc.  */
+      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+       {
+         symval = isym.st_value;
+#if (DEBUG_RELAX & 2)
+         {
+           char * name = bfd_elf_string_from_elf_section
+                          (abfd, symtab_hdr->sh_link, isym.st_name);
+           fprintf (stderr,
+              "relax_delete: local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
+              sec->name, name, isym.st_name,
+              sec->output_section->vma, sec->output_offset,
+              isym.st_value, irel->r_addend);
+         }
+#endif
+       }
+      else
+       {
+         unsigned long indx;
+         struct elf_link_hash_entry * h;
+
+         /* An external symbol.  */
+         indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+
+         h = elf_sym_hashes (abfd) [indx];
+         BFD_ASSERT (h != NULL);
+
+         symval = h->root.u.def.value;
+#if (DEBUG_RELAX & 2)
+         fprintf (stderr,
+                  "relax_delete: defined: sec: %s, name: %s, value: %x + %x + %x addend %x\n",
+                  sec->name, h->root.root.string, h->root.u.def.value,
+                  sec->output_section->vma, sec->output_offset, irel->r_addend);
+#endif
+       }
+
+      paddr = symval + irel->r_addend;
+
+      if ( (symval >= addr + count && symval < toaddr)
+         && (paddr < addr + count || paddr >= toaddr))
+       irel->r_addend += count;
+      else if (    (symval < addr + count || symval >= toaddr)
+               && (paddr >= addr + count && paddr < toaddr))
+       irel->r_addend -= count;
+    }
+
+  /* Adjust the local symbols defined in this section.  */
+  esym = extsyms;
+  esymend = esym + symtab_hdr->sh_info;
+
+  for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
+    {
+      Elf_Internal_Sym isym;
+
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
+
+      if (isym.st_shndx == sec_shndx
+         && isym.st_value >= addr + count
+         && isym.st_value < toaddr)
+       {
+         isym.st_value -= count;
+
+         if (isym.st_value + isym.st_size >= toaddr)
+           isym.st_size += count;
+
+         bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
+       }
+      else if (isym.st_shndx == sec_shndx
+              && isym.st_value < addr + count)
+       {
+         if (isym.st_value+isym.st_size >= addr + count
+             && isym.st_value+isym.st_size < toaddr)
+           isym.st_size -= count;
+
+         if (isym.st_value >= addr
+             && isym.st_value <  addr + count)
+           isym.st_value = addr;
+
+         bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
+       }
+    }
+
+  /* Now adjust the global symbols defined in this section.  */
+  esym = extsyms + symtab_hdr->sh_info;
+  esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
+
+  for (index = 0; esym < esymend; esym ++, index ++)
+    {
+      Elf_Internal_Sym isym;
+
+      bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
+      sym_hash = elf_sym_hashes (abfd) [index];
+
+      if (isym.st_shndx == sec_shndx
+         && ((sym_hash)->root.type == bfd_link_hash_defined
+             || (sym_hash)->root.type == bfd_link_hash_defweak)
+         && (sym_hash)->root.u.def.section == sec
+         && (sym_hash)->root.u.def.value >= addr + count
+         && (sym_hash)->root.u.def.value < toaddr)
+       {
+         if ((sym_hash)->root.u.def.value + isym.st_size >= toaddr)
+           {
+             isym.st_size += count;
+             bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
+           }
+
+         (sym_hash)->root.u.def.value -= count;
+       }
+      else if (isym.st_shndx == sec_shndx
+              && ((sym_hash)->root.type == bfd_link_hash_defined
+                  || (sym_hash)->root.type == bfd_link_hash_defweak)
+              && (sym_hash)->root.u.def.section == sec
+              && (sym_hash)->root.u.def.value < addr + count)
+       {
+         if ((sym_hash)->root.u.def.value+isym.st_size >= addr + count
+             && (sym_hash)->root.u.def.value+isym.st_size < toaddr)
+           isym.st_size -= count;
+
+         if ((sym_hash)->root.u.def.value >= addr
+             && (sym_hash)->root.u.def.value < addr + count)
+           (sym_hash)->root.u.def.value = addr;
+
+         bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
+       }
+
+      if (shndx)
+       ++ shndx;
+    }
+
+  return TRUE;
 }
+
+#define NOP_OPCODE     (0x0000)
+#define MOVHI          0x0640                          /* 4byte */
+#define MOVHI_MASK     0x07e0
+#define MOVHI_R1(insn) ((insn) & 0x1f)                 /* 4byte */
+#define MOVHI_R2(insn) ((insn) >> 11)
+#define MOVEA          0x0620                          /* 2byte */
+#define MOVEA_MASK     0x07e0
+#define MOVEA_R1(insn) ((insn) & 0x1f)
+#define MOVEA_R2(insn) ((insn) >> 11)
+#define JARL_4         0x00040780                              /* 4byte */
+#define JARL_4_MASK    0xFFFF07FF
+#define JARL_R2(insn)  (int)(((insn) & (~JARL_4_MASK)) >> 11)
+#define ADD_I          0x0240                                  /* 2byte */
+#define ADD_I_MASK     0x07e0
+#define ADD_I5(insn)   ((((insn) & 0x001f) << 11) >> 11)       /* 2byte */
+#define ADD_R2(insn)   ((insn) >> 11)
+#define JMP_R          0x0060                                  /* 2byte */
+#define JMP_R_MASK     0xFFE0
+#define JMP_R1(insn)   ((insn) & 0x1f)
+
+static bfd_boolean
+v850_elf_relax_section (abfd, sec, link_info, again)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+     bfd_boolean *again;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Rela *internal_relocs;
+  Elf_Internal_Rela *irel;
+  Elf_Internal_Rela *irelend;
+  Elf_Internal_Rela *irelalign = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
+  bfd_byte *contents = NULL;
+  bfd_vma addr = 0;
+  bfd_vma toaddr;
+  int align_pad_size = 0;
+  bfd_boolean result = TRUE;
+
+  *again = FALSE;
+
+  if (link_info->relocatable
+      || (sec->flags & SEC_RELOC) == 0
+      || sec->reloc_count == 0)
+    return TRUE;
+
+  /* If this is the first time we have been called
+     for this section, initialize the cooked size.  */
+  if (sec->_cooked_size == 0)
+    sec->_cooked_size = sec->_raw_size;
+
+  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
+
+  internal_relocs = (_bfd_elf_link_read_relocs
+                    (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+                     link_info->keep_memory));
+  if (internal_relocs == NULL)
+    goto error_return;
+
+  irelend = internal_relocs + sec->reloc_count;
+
+  while (addr < sec->_cooked_size)
+    {
+      toaddr = sec->_cooked_size;
+
+      for (irel = internal_relocs; irel < irelend; irel ++)
+       if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN
+           && irel->r_offset > addr
+           && irel->r_offset < toaddr)
+         toaddr = irel->r_offset;
+
+#ifdef DEBUG_RELAX
+      fprintf (stderr, "relax region 0x%x to 0x%x align pad %d\n",
+              addr, toaddr, align_pad_size);
+#endif
+      if (irelalign)
+       {
+         bfd_vma alignto;
+         bfd_vma alignmoveto;
+
+         alignmoveto = BFD_ALIGN (addr - align_pad_size, 1 << irelalign->r_addend);
+         alignto = BFD_ALIGN (addr, 1 << irelalign->r_addend);
+
+         if (alignmoveto < alignto)
+           {
+             unsigned int i;
+
+             align_pad_size = alignto - alignmoveto;
+#ifdef DEBUG_RELAX
+             fprintf (stderr, "relax move region 0x%x to 0x%x delete size 0x%x\n",
+                      alignmoveto, toaddr, align_pad_size);
+#endif
+             if (!v850_elf_relax_delete_bytes (abfd, sec, alignmoveto,
+                                               toaddr, align_pad_size))
+               goto error_return;
+
+             for (i  = BFD_ALIGN (toaddr - align_pad_size, 1);
+                  (i + 1) < toaddr; i += 2)
+               bfd_put_16 (abfd, NOP_OPCODE, contents + i);
+
+             addr = alignmoveto;
+           }
+         else
+           align_pad_size = 0;
+       }
+
+      for (irel = internal_relocs; irel < irelend; irel++)
+       {
+         bfd_vma laddr;
+         bfd_vma addend;
+         bfd_vma symval;
+         int insn[5];
+         int no_match = -1;
+         Elf_Internal_Rela *hi_irelfn;
+         Elf_Internal_Rela *lo_irelfn;
+         Elf_Internal_Rela *irelcall;
+         bfd_signed_vma foff;
+
+         if (! (irel->r_offset >= addr && irel->r_offset < toaddr
+                && (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL
+                    || ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGJUMP)))
+           continue;
+
+#ifdef DEBUG_RELAX
+         fprintf (stderr, "relax check r_info 0x%x r_offset 0x%x r_addend 0x%x\n",
+                  irel->r_info,
+                  irel->r_offset,
+                  irel->r_addend );
+#endif
+
+         /* Get the section contents.  */
+         if (contents == NULL)
+           {
+             if (elf_section_data (sec)->this_hdr.contents != NULL)
+               contents = elf_section_data (sec)->this_hdr.contents;
+             else
+               {
+                 contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
+                 if (contents == NULL)
+                   goto error_return;
+
+                 if (! bfd_get_section_contents (abfd, sec, contents,
+                                                 (file_ptr) 0, sec->_raw_size))
+                   goto error_return;
+               }
+           }
+
+         /* Read this BFD's local symbols if we haven't done so already.  */
+         if (isymbuf == NULL && symtab_hdr->sh_info != 0)
+           {
+             isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+             if (isymbuf == NULL)
+               isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+                                               symtab_hdr->sh_info, 0,
+                                               NULL, NULL, NULL);
+             if (isymbuf == NULL)
+               goto error_return;
+           }
+
+         laddr = irel->r_offset;
+
+         if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL)
+           {
+             /* Check code for -mlong-calls output. */
+             if (laddr + 16 <= (bfd_vma) sec->_raw_size)
+               {
+                 insn[0] = bfd_get_16 (abfd, contents + laddr);
+                 insn[1] = bfd_get_16 (abfd, contents + laddr + 4);
+                 insn[2] = bfd_get_32 (abfd, contents + laddr + 8);
+                 insn[3] = bfd_get_16 (abfd, contents + laddr + 12);
+                 insn[4] = bfd_get_16 (abfd, contents + laddr + 14);
+
+                 if ((insn[0] & MOVHI_MASK) != MOVHI
+                      || MOVHI_R1 (insn[0]) != 0)
+                   no_match = 0;
+
+                 if (no_match < 0
+                     && ((insn[1] & MOVEA_MASK) != MOVEA
+                          || MOVHI_R2 (insn[0]) != MOVEA_R1 (insn[1])))
+                   no_match = 1;
+
+                 if (no_match < 0
+                     && (insn[2] & JARL_4_MASK) != JARL_4)
+                   no_match = 2;
+
+                 if (no_match < 0
+                     && ((insn[3] & ADD_I_MASK) != ADD_I
+                          || ADD_I5 (insn[3]) != 4
+                          || JARL_R2 (insn[2]) != ADD_R2 (insn[3])))
+                   no_match = 3;
+
+                 if (no_match < 0
+                     && ((insn[4] & JMP_R_MASK) != JMP_R
+                          || MOVEA_R2 (insn[1]) != JMP_R1 (insn[4])))
+                   no_match = 4;
+               }
+             else
+               {
+                 ((*_bfd_error_handler)
+                  ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized insns",
+                   bfd_get_filename (abfd), (unsigned long) irel->r_offset));
+
+                 continue;
+               }
+
+             if (no_match >= 0)
+               {
+                 ((*_bfd_error_handler)
+                  ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized insn 0x%x",
+                   bfd_get_filename (abfd), (unsigned long) irel->r_offset+no_match, insn[no_match]));
+
+                 continue;
+               }
+
+             /* Get the reloc for the address from which the register is
+                being loaded.  This reloc will tell us which function is
+                actually being called.  */
+             for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++)
+               if (hi_irelfn->r_offset == laddr + 2
+                   && ELF32_R_TYPE (hi_irelfn->r_info)
+                       == (int) R_V850_HI16_S)
+                 break;
+
+             for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++)
+               if (lo_irelfn->r_offset == laddr + 6
+                   && ELF32_R_TYPE (lo_irelfn->r_info)
+                       == (int) R_V850_LO16)
+                 break;
+
+             for (irelcall = internal_relocs; irelcall < irelend; irelcall ++)
+               if (irelcall->r_offset == laddr + 8
+                   && ELF32_R_TYPE (irelcall->r_info)
+                        == (int) R_V850_22_PCREL)
+                 break;
+
+             if (   hi_irelfn == irelend
+                 || lo_irelfn == irelend
+                 || irelcall  == irelend)
+               {
+                 ((*_bfd_error_handler)
+                  ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized reloc",
+                   bfd_get_filename (abfd), (unsigned long) irel->r_offset ));
+
+                 continue;
+               }
+
+             if (ELF32_R_SYM (irelcall->r_info) < symtab_hdr->sh_info)
+               {
+                 Elf_Internal_Sym *  isym;
+
+                 /* A local symbol.  */
+                 isym = isymbuf + ELF32_R_SYM (irelcall->r_info);
+
+                 symval = isym->st_value;
+               }
+             else
+               {
+                 unsigned long indx;
+                 struct elf_link_hash_entry * h;
+
+                 /* An external symbol.  */
+                 indx = ELF32_R_SYM (irelcall->r_info) - symtab_hdr->sh_info;
+                 h = elf_sym_hashes (abfd)[indx];
+                 BFD_ASSERT (h != NULL);
+
+                 if (   h->root.type != bfd_link_hash_defined
+                     && h->root.type != bfd_link_hash_defweak)
+                   /* This appears to be a reference to an undefined
+                      symbol.  Just ignore it--it will be caught by the
+                      regular reloc processing.  */
+                   continue;
+
+                 symval = h->root.u.def.value;
+               }
+
+             if (symval + irelcall->r_addend != irelcall->r_offset + 4)
+               {
+                 ((*_bfd_error_handler)
+                  ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized reloc 0x%lx",
+                   bfd_get_filename (abfd), (unsigned long) irel->r_offset, irelcall->r_offset ));
+
+                 continue;
+               }
+
+             /* Get the value of the symbol referred to by the reloc.  */
+             if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
+               {
+                 Elf_Internal_Sym *isym;
+                 asection *sym_sec;
+
+                 /* A local symbol.  */
+                 isym = isymbuf + ELF32_R_SYM (hi_irelfn->r_info);
+
+                 if (isym->st_shndx == SHN_UNDEF)
+                   sym_sec = bfd_und_section_ptr;
+                 else if (isym->st_shndx == SHN_ABS)
+                   sym_sec = bfd_abs_section_ptr;
+                 else if (isym->st_shndx == SHN_COMMON)
+                   sym_sec = bfd_com_section_ptr;
+                 else
+                   sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+                 symval = (isym->st_value
+                           + sym_sec->output_section->vma
+                           + sym_sec->output_offset);
+               }
+             else
+               {
+                 unsigned long indx;
+                 struct elf_link_hash_entry *h;
+
+                 /* An external symbol.  */
+                 indx = ELF32_R_SYM (hi_irelfn->r_info) - symtab_hdr->sh_info;
+                 h = elf_sym_hashes (abfd)[indx];
+                 BFD_ASSERT (h != NULL);
+
+                 if (   h->root.type != bfd_link_hash_defined
+                     && h->root.type != bfd_link_hash_defweak)
+                   /* This appears to be a reference to an undefined
+                      symbol.  Just ignore it--it will be caught by the
+                      regular reloc processing.  */
+                   continue;
+
+                 symval = (h->root.u.def.value
+                           + h->root.u.def.section->output_section->vma
+                           + h->root.u.def.section->output_offset);
+               }
+
+             addend = irel->r_addend;
+
+             foff = (symval + addend
+                     - (irel->r_offset
+                        + sec->output_section->vma
+                        + sec->output_offset
+                        + 4));
+#ifdef DEBUG_RELAX
+             fprintf (stderr, "relax longcall r_offset 0x%x ptr 0x%x symbol 0x%x addend 0x%x distance 0x%x\n",
+                      irel->r_offset,
+                      (irel->r_offset
+                       + sec->output_section->vma
+                       + sec->output_offset),
+                      symval, addend, foff);
+#endif
+
+             if (foff < -0x100000 || foff >= 0x100000)
+               /* After all that work, we can't shorten this function call.  */
+               continue;
+
+             /* For simplicity of coding, we are going to modify the section
+                contents, the section relocs, and the BFD symbol table.  We
+                must tell the rest of the code not to free up this
+                information.  It would be possible to instead create a table
+                of changes which have to be made, as is done in coff-mips.c;
+                that would be more work, but would require less memory when
+                the linker is run.  */
+             elf_section_data (sec)->relocs = internal_relocs;
+             elf_section_data (sec)->this_hdr.contents = contents;
+             symtab_hdr->contents = (bfd_byte *) isymbuf;
+
+             /* Replace the long call with a jarl.  */
+             irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_22_PCREL);
+
+             addend = 0;
+
+             if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
+               /* If this needs to be changed because of future relaxing,
+                  it will be handled here like other internal IND12W
+                  relocs.  */
+               bfd_put_32 (abfd,
+                           0x00000780 | (JARL_R2 (insn[2])<<11) | ((addend << 16) & 0xffff) | ((addend >> 16) & 0xf),
+                           contents + irel->r_offset);
+             else
+               /* We can't fully resolve this yet, because the external
+                  symbol value may be changed by future relaxing.
+                  We let the final link phase handle it.  */
+               bfd_put_32 (abfd, 0x00000780 | (JARL_R2 (insn[2])<<11),
+                           contents + irel->r_offset);
+
+             hi_irelfn->r_info =
+               ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE);
+             lo_irelfn->r_info =
+               ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE);
+             irelcall->r_info =
+               ELF32_R_INFO (ELF32_R_SYM (irelcall->r_info), R_V850_NONE);
+
+             if (! v850_elf_relax_delete_bytes (abfd, sec,
+                                                irel->r_offset + 4, toaddr, 12))
+               goto error_return;
+
+             align_pad_size += 12;
+           }
+         else if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGJUMP)
+           {
+             /* Check code for -mlong-jumps output.  */
+             if (laddr + 10 <= (bfd_vma) sec->_raw_size)
+               {
+                 insn[0] = bfd_get_16 (abfd, contents + laddr);
+                 insn[1] = bfd_get_16 (abfd, contents + laddr + 4);
+                 insn[2] = bfd_get_16 (abfd, contents + laddr + 8);
+
+                 if ((insn[0] & MOVHI_MASK) != MOVHI
+                      || MOVHI_R1 (insn[0]) != 0)
+                   no_match = 0;
+
+                 if (no_match < 0
+                     && ((insn[1] & MOVEA_MASK) != MOVEA
+                          || MOVHI_R2 (insn[0]) != MOVEA_R1 (insn[1])))
+                   no_match = 1;
+
+                 if (no_match < 0
+                     && ((insn[2] & JMP_R_MASK) != JMP_R
+                          || MOVEA_R2 (insn[1]) != JMP_R1 (insn[2])))
+                   no_match = 4;
+               }
+             else
+               {
+                 ((*_bfd_error_handler)
+                  ("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized insns",
+                   bfd_get_filename (abfd), (unsigned long) irel->r_offset));
+
+                 continue;
+               }
+
+             if (no_match >= 0)
+               {
+                 ((*_bfd_error_handler)
+                  ("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized insn 0x%x",
+                   bfd_get_filename (abfd), (unsigned long) irel->r_offset+no_match, insn[no_match]));
+
+                 continue;
+               }
+
+             /* Get the reloc for the address from which the register is
+                being loaded.  This reloc will tell us which function is
+                actually being called.  */
+             for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++)
+               if (hi_irelfn->r_offset == laddr + 2
+                   && ELF32_R_TYPE (hi_irelfn->r_info) == (int) R_V850_HI16_S)
+                 break;
+
+             for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++)
+               if (lo_irelfn->r_offset == laddr + 6
+                   && ELF32_R_TYPE (lo_irelfn->r_info) == (int) R_V850_LO16)
+                 break;
+
+             if (   hi_irelfn == irelend
+                 || lo_irelfn == irelend)
+               {
+                 ((*_bfd_error_handler)
+                  ("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized reloc",
+                   bfd_get_filename (abfd), (unsigned long) irel->r_offset ));
+
+                 continue;
+               }
+
+             /* Get the value of the symbol referred to by the reloc.  */
+             if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
+               {
+                 Elf_Internal_Sym *  isym;
+                 asection *          sym_sec;
+
+                 /* A local symbol.  */
+                 isym = isymbuf + ELF32_R_SYM (hi_irelfn->r_info);
+
+                 if (isym->st_shndx == SHN_UNDEF)
+                   sym_sec = bfd_und_section_ptr;
+                 else if (isym->st_shndx == SHN_ABS)
+                   sym_sec = bfd_abs_section_ptr;
+                 else if (isym->st_shndx == SHN_COMMON)
+                   sym_sec = bfd_com_section_ptr;
+                 else
+                   sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+                 symval = (isym->st_value
+                           + sym_sec->output_section->vma
+                           + sym_sec->output_offset);
+#ifdef DEBUG_RELAX
+                 {
+                   char * name = bfd_elf_string_from_elf_section
+                     (abfd, symtab_hdr->sh_link, isym->st_name);
+
+                   fprintf (stderr, "relax long jump local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
+                            sym_sec->name, name, isym->st_name,
+                            sym_sec->output_section->vma,
+                            sym_sec->output_offset,
+                            isym->st_value, irel->r_addend);
+                 }
+#endif
+               }
+             else
+               {
+                 unsigned long indx;
+                 struct elf_link_hash_entry * h;
+
+                 /* An external symbol.  */
+                 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+                 h = elf_sym_hashes (abfd)[indx];
+                 BFD_ASSERT (h != NULL);
+
+                 if (   h->root.type != bfd_link_hash_defined
+                     && h->root.type != bfd_link_hash_defweak)
+                   /* This appears to be a reference to an undefined
+                      symbol.  Just ignore it--it will be caught by the
+                      regular reloc processing.  */
+                   continue;
+
+                 symval = (h->root.u.def.value
+                           + h->root.u.def.section->output_section->vma
+                           + h->root.u.def.section->output_offset);
+#ifdef DEBUG_RELAX
+                 fprintf (stderr,
+                          "relax longjump defined: sec: %s, name: %s, value: %x + %x + %x addend %x\n",
+                          sec->name, h->root.root.string, h->root.u.def.value,
+                          sec->output_section->vma, sec->output_offset, irel->r_addend);
+#endif
+               }
+
+             addend = irel->r_addend;
+
+             foff = (symval + addend
+                     - (irel->r_offset
+                        + sec->output_section->vma
+                        + sec->output_offset
+                        + 4));
+#ifdef DEBUG_RELAX
+             fprintf (stderr, "relax longjump r_offset 0x%x ptr 0x%x symbol 0x%x addend 0x%x distance 0x%x\n",
+                      irel->r_offset,
+                      (irel->r_offset
+                       + sec->output_section->vma
+                       + sec->output_offset),
+                      symval, addend, foff);
+#endif
+             if (foff < -0x100000 || foff >= 0x100000)
+               /* After all that work, we can't shorten this function call.  */
+               continue;
+
+             /* For simplicity of coding, we are going to modify the section
+                contents, the section relocs, and the BFD symbol table.  We
+                must tell the rest of the code not to free up this
+                information.  It would be possible to instead create a table
+                of changes which have to be made, as is done in coff-mips.c;
+                that would be more work, but would require less memory when
+                the linker is run.  */
+             elf_section_data (sec)->relocs = internal_relocs;
+             elf_section_data (sec)->this_hdr.contents = contents;
+             symtab_hdr->contents = (bfd_byte *) isymbuf;
+
+             if (foff < -0x100 || foff >= 0x100)
+               {
+                 /* Replace the long jump with a jr.  */
+
+                 irel->r_info =
+                   ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_22_PCREL);
+
+                 irel->r_addend = addend;
+                 addend = 0;
+
+                 if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
+                   /* If this needs to be changed because of future relaxing,
+                      it will be handled here like other internal IND12W
+                      relocs.  */
+                   bfd_put_32 (abfd,
+                               0x00000780 | ((addend << 15) & 0xffff0000) | ((addend >> 17) & 0xf),
+                               contents + irel->r_offset);
+                 else
+                   /* We can't fully resolve this yet, because the external
+                      symbol value may be changed by future relaxing.
+                      We let the final link phase handle it.  */
+                   bfd_put_32 (abfd, 0x00000780, contents + irel->r_offset);
+
+                 hi_irelfn->r_info =
+                       ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE);
+                 lo_irelfn->r_info =
+                       ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE);
+                 if (!v850_elf_relax_delete_bytes (abfd, sec,
+                                                   irel->r_offset + 4, toaddr, 6))
+                   goto error_return;
+
+                 align_pad_size += 6;
+               }
+             else
+               {
+                 /* Replace the long jump with a br.  */
+
+                 irel->r_info =
+                       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_9_PCREL);
+
+                 irel->r_addend = addend;
+                 addend = 0;
+
+                 if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
+                   /* If this needs to be changed because of future relaxing,
+                      it will be handled here like other internal IND12W
+                      relocs.  */
+                   bfd_put_16 (abfd,
+                               0x0585 | ((addend << 10) & 0xf800) | ((addend << 3) & 0x0070),
+                               contents + irel->r_offset);
+                 else
+                   /* We can't fully resolve this yet, because the external
+                      symbol value may be changed by future relaxing.
+                      We let the final link phase handle it.  */
+                   bfd_put_16 (abfd, 0x0585, contents + irel->r_offset);
+
+                 hi_irelfn->r_info =
+                       ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE);
+                 lo_irelfn->r_info =
+                       ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE);
+                 if (!v850_elf_relax_delete_bytes (abfd, sec,
+                                                   irel->r_offset + 2, toaddr, 8))
+                   goto error_return;
+
+                 align_pad_size += 8;
+               }
+           }
+       }
+
+      irelalign = NULL;
+      for (irel = internal_relocs; irel < irelend; irel++)
+       {
+         if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN
+             && irel->r_offset == toaddr)
+           {
+             irel->r_offset -= align_pad_size;
+
+             if (irelalign == NULL || irelalign->r_addend > irel->r_addend)
+               irelalign = irel;
+           }
+       }
+
+      addr = toaddr;
+    }
+
+  if (!irelalign)
+    {
+#ifdef DEBUG_RELAX
+      fprintf (stderr, "relax pad %d shorten %d -> %d\n",
+              align_pad_size,
+              sec->_cooked_size,
+              sec->_cooked_size - align_pad_size);
+#endif
+      sec->_cooked_size -= align_pad_size;
+    }
+
+ finish:
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != (unsigned char *) contents)
+    free (contents);
+
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (bfd_byte *) isymbuf)
+    free (isymbuf);
+
+  return result;
+
+ error_return:
+  result = FALSE;
+  goto finish;
+}
+
+static struct bfd_elf_special_section const v850_elf_special_sections[]=
+{
+  { ".sdata",            6, -2, SHT_PROGBITS,     (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_GPREL) },
+  { ".rosdata",          8, -2, SHT_PROGBITS,     (SHF_ALLOC
+                                                   + SHF_V850_GPREL) },
+  { ".sbss",             5, -2, SHT_NOBITS,       (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_GPREL) },
+  { ".scommon",          8, -2, SHT_V850_SCOMMON, (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_GPREL) },
+  { ".tdata",            6, -2, SHT_PROGBITS,     (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_EPREL) },
+  { ".tbss",             5, -2, SHT_NOBITS,       (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_EPREL) },
+  { ".tcommon",          8, -2, SHT_V850_TCOMMON, (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_R0REL) },
+  { ".zdata",            6, -2, SHT_PROGBITS,     (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_R0REL) },
+  { ".rozdata",          8, -2, SHT_PROGBITS,     (SHF_ALLOC
+                                                   + SHF_V850_R0REL) },
+  { ".zbss",             5, -2, SHT_NOBITS,       (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_R0REL) },
+  { ".zcommon",          8, -2, SHT_V850_ZCOMMON, (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_V850_R0REL) },
+  { ".call_table_data", 16,  0, SHT_PROGBITS,     (SHF_ALLOC
+                                                   + SHF_WRITE) },
+  { ".call_table_text", 16,  0, SHT_PROGBITS,     (SHF_ALLOC + SHF_WRITE
+                                                   + SHF_EXECINSTR) },
+  { NULL,               0,   0, 0,                0 }
+};
 \f
 #define TARGET_LITTLE_SYM                      bfd_elf32_v850_vec
 #define TARGET_LITTLE_NAME                     "elf32-v850"
 #define ELF_ARCH                               bfd_arch_v850
-#define ELF_MACHINE_CODE                       EM_CYGNUS_V850
+#define ELF_MACHINE_CODE                       EM_V850
+#define ELF_MACHINE_ALT1                       EM_CYGNUS_V850
 #define ELF_MAXPAGESIZE                                0x1000
 
 #define elf_info_to_howto                      v850_elf_info_to_howto_rela
@@ -2236,15 +3183,17 @@ v850_elf_fake_sections (abfd, hdr, sec)
 #define elf_backend_fake_sections              v850_elf_fake_sections
 #define elf_backend_gc_mark_hook                v850_elf_gc_mark_hook
 #define elf_backend_gc_sweep_hook               v850_elf_gc_sweep_hook
+#define elf_backend_special_sections           v850_elf_special_sections
 
 #define elf_backend_can_gc_sections 1
+#define elf_backend_rela_normal 1
 
 #define bfd_elf32_bfd_is_local_label_name      v850_elf_is_local_label_name
 #define bfd_elf32_bfd_reloc_type_lookup                v850_elf_reloc_type_lookup
-#define bfd_elf32_bfd_copy_private_bfd_data    v850_elf_copy_private_bfd_data
 #define bfd_elf32_bfd_merge_private_bfd_data   v850_elf_merge_private_bfd_data
 #define bfd_elf32_bfd_set_private_flags                v850_elf_set_private_flags
 #define bfd_elf32_bfd_print_private_bfd_data   v850_elf_print_private_bfd_data
+#define bfd_elf32_bfd_relax_section            v850_elf_relax_section
 
 #define elf_symbol_leading_char                        '_'
 
This page took 0.080604 seconds and 4 git commands to generate.