summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2002-08-29 06:49:35 +0000
committerNick Clifton <nickc@redhat.com>2002-08-29 06:49:35 +0000
commit09b6c4211cb07c2acf50f66a56fd701487832abf (patch)
tree7d5a8c41c24caa3ce209b5560a1f20a76a546ef5
parent72e5270345d396e60f0d701339841e021d1fab68 (diff)
downloadbinutils-redhat-09b6c4211cb07c2acf50f66a56fd701487832abf.tar.gz
Add linker relaxation to v850 toolchain
-rw-r--r--bfd/ChangeLog18
-rw-r--r--bfd/archures.c1
-rw-r--r--bfd/bfd-in2.h10
-rw-r--r--bfd/cpu-v850.c30
-rw-r--r--bfd/elf32-v850.c1085
-rw-r--r--bfd/libbfd.h4
-rw-r--r--bfd/reloc.c14
-rw-r--r--gas/ChangeLog21
-rw-r--r--gas/config/tc-v850.c118
-rw-r--r--gas/config/tc-v850.h5
-rw-r--r--gas/doc/c-v850.texi23
-rw-r--r--include/elf/ChangeLog5
-rw-r--r--include/elf/v850.h47
13 files changed, 1274 insertions, 107 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 43a03634e4..b2869495ea 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,21 @@
+2002-08-28 Catherine Moore <clm@redhat.com>
+
+ * elf32-v850.c (v850_elf_reloc_map): Add new relocs.
+ (v850-elf-reloc): Don't resolve pc relative relocs.
+ (v850_elf_ignore_reloc): New routine.
+ (v850_elf_final_link_relocate): Handle new relocs.
+ (v850_elf_relax_delete_bytes ): New routine.
+ (v850_elf_relax_section): New routine.
+ (bfd_elf32_bfd_relax_section): Define.
+ (HOWTO): New entries for new relocs.
+ * reloc.c (BFD_RELOC_V850_LONGCALL): New reloc.
+ (BFD_RELOC_V850_LONGJUMP): New reloc.
+ (BFD_RELOC_V850_ALIGN): New reloc.
+ * archures.c: Remove redundant v850ea architecture.
+ * cpu-v850.c: Remove redundant v850ea support.
+ * libbfd.h: Regenerate.
+ * bfd-in2.h: Regenerated.
+
2002-08-28 Svein E. Seldal <Svein.Seldal@solidas.com>
* config.bfd: Add tic4x-*-*coff* and c4x-*-*coff* target.
diff --git a/bfd/archures.c b/bfd/archures.c
index f3ca094bcf..3f0ba7bb65 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -236,7 +236,6 @@ DESCRIPTION
. bfd_arch_v850, {* NEC V850 *}
.#define bfd_mach_v850 0
.#define bfd_mach_v850e 'E'
-.#define bfd_mach_v850ea 'A'
. bfd_arch_arc, {* ARC Cores *}
.#define bfd_mach_arc_5 0
.#define bfd_mach_arc_6 1
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 34fb98ed30..0ab4245202 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -274,7 +274,7 @@ bfd_format;
memory. If this is set, iostream points to a bfd_in_memory struct. */
#define BFD_IN_MEMORY 0x800
-/* The sections in this BFD specify a memory page */
+/* The sections in this BFD specify a memory page. */
#define HAS_LOAD_PAGE 0x1000
/* Symbols and relocation. */
@@ -2668,6 +2668,14 @@ bits placed non-contigously in the instruction. */
/* This is a 16 bit offset from the call table base pointer. */
BFD_RELOC_V850_CALLT_16_16_OFFSET,
+/* Used for relaxing indirect function calls. */
+ BFD_RELOC_V850_LONGCALL,
+
+/* Used for relaxing indirect jumps. */
+ BFD_RELOC_V850_LONGJUMP,
+
+/* Used to maintain alignment whilst relaxing. */
+ BFD_RELOC_V850_ALIGN,
/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
instruction. */
diff --git a/bfd/cpu-v850.c b/bfd/cpu-v850.c
index 8836362026..ce61caa756 100644
--- a/bfd/cpu-v850.c
+++ b/bfd/cpu-v850.c
@@ -1,21 +1,21 @@
/* BFD support for the NEC V850 processor
- Copyright 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 2000, 2001, 2002 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. */
#include "bfd.h"
#include "sysdep.h"
@@ -67,7 +67,6 @@ scan (info, string)
switch (number)
{
case bfd_mach_v850e: arch = bfd_arch_v850; break;
- case bfd_mach_v850ea: arch = bfd_arch_v850; break;
default:
return false;
}
@@ -89,8 +88,7 @@ scan (info, string)
static const bfd_arch_info_type arch_info_struct[] =
{
- N (bfd_mach_v850e, "v850e", false, & arch_info_struct[1]),
- N (bfd_mach_v850ea, "v850ea", false, NULL)
+ N (bfd_mach_v850e, "v850e", false, NULL)
};
#undef NEXT
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 07890c6a7c..193a0bf493 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -2,24 +2,24 @@
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
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"
@@ -87,6 +87,12 @@ static asection * v850_elf_gc_mark_hook
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 boolean v850_elf_relax_delete_bytes
+ PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int));
+static boolean v850_elf_relax_section
+ PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
/* Note: It is REQUIRED that the 'type' value of each entry
in this array match the index of the entry in the array. */
@@ -467,6 +473,51 @@ static reloc_howto_type v850_elf_howto_table[] =
0, /* dst_mask */
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 */
};
/* Map BFD reloc types to V850 ELF reloc types. */
@@ -481,31 +532,34 @@ 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_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_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 },
};
@@ -1297,6 +1351,9 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
/* Work out which section the relocation is targetted at and the
initial relocation command value. */
+ if (reloc->howto->pc_relative == true)
+ return bfd_reloc_ok;
+
/* Get symbol value. (Common symbols are special.) */
if (bfd_is_com_section (symbol->section))
relocation = 0;
@@ -1335,6 +1392,26 @@ 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;
+}
static boolean
v850_elf_is_local_label_name (abfd, name)
@@ -1349,8 +1426,8 @@ v850_elf_is_local_label_name (abfd, name)
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)
+ input_section, contents, offset, value,
+ addend, info, sym_sec, is_local)
reloc_howto_type * howto;
bfd * input_bfd;
bfd * output_bfd ATTRIBUTE_UNUSED;
@@ -1500,6 +1577,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:
@@ -1770,7 +1850,6 @@ v850_elf_object_p (abfd)
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;
}
return true;
}
@@ -1789,7 +1868,6 @@ v850_elf_final_write_processing (abfd, linker)
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;
}
elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
@@ -1882,7 +1960,6 @@ 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;
}
fputc ('\n', file);
@@ -2166,6 +2243,939 @@ v850_elf_fake_sections (abfd, hdr, sec)
return true;
}
+
+/* Delete some bytes from a section while relaxing. */
+
+static 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, shndx, esym);
+ }
+ 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, shndx, esym);
+ }
+ }
+
+ /* 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, shndx, esym);
+ }
+
+ (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, shndx, esym);
+ }
+
+ 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 boolean
+v850_elf_relax_section (abfd, sec, link_info, again)
+ bfd * abfd;
+ asection * sec;
+ struct bfd_link_info * link_info;
+ boolean * again;
+{
+ Elf_Internal_Shdr * symtab_hdr;
+ Elf_Internal_Rela * internal_relocs;
+ Elf_Internal_Rela * free_relocs = NULL;
+ Elf_Internal_Rela * irel;
+ Elf_Internal_Rela * irelend;
+ Elf_Internal_Rela * irelalign = NULL;
+ bfd_byte * contents = NULL;
+ bfd_byte * free_contents = NULL;
+ Elf32_External_Sym * extsyms = NULL;
+ Elf32_External_Sym * free_extsyms = NULL;
+ bfd_vma addr = 0;
+ bfd_vma toaddr;
+ int align_pad_size = 0;
+ Elf_Internal_Shdr * shndx_hdr = NULL;
+ Elf_External_Sym_Shndx * shndx_buf = NULL;
+
+ * again = false;
+
+ if (link_info->relocateable
+ || (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_elf32_link_read_relocs
+ (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+ link_info->keep_memory));
+ if (internal_relocs == NULL)
+ goto error_return;
+ if (! link_info->keep_memory)
+ free_relocs = internal_relocs;
+
+ 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;
+
+ free_contents = contents;
+
+ if (! bfd_get_section_contents (abfd, sec, contents,
+ (file_ptr) 0, sec->_raw_size))
+ goto error_return;
+ }
+ }
+
+ /* Read this BFD's symbols if we haven't done so already. */
+ if (extsyms == NULL)
+ {
+ /* Get cached copy if it exists. */
+ if (symtab_hdr->contents != NULL)
+ extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
+ else
+ {
+ /* Go get them off disk. */
+ bfd_size_type amt;
+
+ amt = symtab_hdr->sh_info;
+ amt *= sizeof (Elf32_External_Sym);
+ extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
+ if (extsyms == NULL)
+ goto error_return;
+ free_extsyms = extsyms;
+ if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+ || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
+ goto error_return;
+ }
+
+ if (shndx_hdr->sh_size != 0)
+ {
+ bfd_size_type amt;
+
+ amt = symtab_hdr->sh_info;
+ amt *= sizeof (Elf_External_Sym_Shndx);
+ shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+ if (shndx_buf == NULL)
+ goto error_return;
+ if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+ || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
+ 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)
+ {
+ unsigned int r_index;
+ Elf_Internal_Sym isym;
+ asection * sym_sec;
+ Elf32_External_Sym * esym;
+ Elf_External_Sym_Shndx * shndx;
+
+ /* A local symbol. */
+ r_index = ELF32_R_SYM (irelcall->r_info);
+ esym = extsyms + r_index;
+ shndx = shndx_buf + (shndx_buf ? r_index : 0);
+ bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
+
+ 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;
+ }
+ 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)
+ {
+ unsigned int r_index;
+ Elf_Internal_Sym isym;
+ asection * sym_sec;
+ Elf32_External_Sym * esym;
+ Elf_External_Sym_Shndx * shndx;
+
+ /* A local symbol. */
+ r_index = ELF32_R_SYM (irel->r_info);
+ esym = extsyms + r_index;
+ shndx = shndx_buf + (shndx_buf ? r_index : 0);
+ bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
+
+ 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 (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);
+ }
+
+ 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;
+ free_relocs = NULL;
+
+ elf_section_data (sec)->this_hdr.contents = contents;
+ free_contents = NULL;
+
+ symtab_hdr->contents = (bfd_byte *) extsyms;
+ free_extsyms = NULL;
+
+ /* 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)
+ {
+ unsigned int r_index;
+ Elf_Internal_Sym isym;
+ asection * sym_sec;
+ Elf32_External_Sym * esym;
+ Elf_External_Sym_Shndx * shndx;
+
+ /* A local symbol. */
+ r_index = ELF32_R_SYM (irel->r_info);
+ esym = extsyms + r_index;
+ shndx = shndx_buf + (shndx_buf ? r_index : 0);
+ bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
+
+ 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;
+ free_relocs = NULL;
+
+ elf_section_data (sec)->this_hdr.contents = contents;
+ free_contents = NULL;
+
+ symtab_hdr->contents = (bfd_byte *) extsyms;
+ free_extsyms = NULL;
+
+ 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;
+ }
+
+ return true;
+
+ error_return:
+ if (free_relocs != NULL)
+ free (free_relocs);
+
+ if (free_contents != NULL)
+ free (free_contents);
+
+ if (free_extsyms != NULL)
+ free (free_extsyms);
+
+ return false;
+}
#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
#define TARGET_LITTLE_NAME "elf32-v850"
@@ -2198,6 +3208,7 @@ v850_elf_fake_sections (abfd, hdr, sec)
#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 '_'
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 88beae8a9f..e855db196a 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1041,7 +1041,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET",
"BFD_RELOC_V850_CALLT_6_7_OFFSET",
"BFD_RELOC_V850_CALLT_16_16_OFFSET",
-
+ "BFD_RELOC_V850_LONGCALL",
+ "BFD_RELOC_V850_LONGJUMP",
+ "BFD_RELOC_V850_ALIGN",
"BFD_RELOC_MN10300_32_PCREL",
"BFD_RELOC_MN10300_16_PCREL",
"BFD_RELOC_TIC30_LDP",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index deba952832..e60c26e051 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2788,8 +2788,18 @@ ENUM
BFD_RELOC_V850_CALLT_16_16_OFFSET
ENUMDOC
This is a 16 bit offset from the call table base pointer.
-COMMENT
-
+ENUM
+ BFD_RELOC_V850_LONGCALL
+ENUMDOC
+ Used for relaxing indirect function calls.
+ENUM
+ BFD_RELOC_V850_LONGJUMP
+ENUMDOC
+ Used for relaxing indirect jumps.
+ENUM
+ BFD_RELOC_V850_ALIGN
+ENUMDOC
+ Used to maintain alignment whilst relaxing.
ENUM
BFD_RELOC_MN10300_32_PCREL
ENUMDOC
diff --git a/gas/ChangeLog b/gas/ChangeLog
index e8bf9fea53..a083a87cd3 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,24 @@
+2000-08-28 Catherine Moore <clm@redhat.com>
+
+ * tc-v850.c (v850_relax): Declare.
+ (v850_longcode): New routine.
+ (v850_handle_align): New routine.
+ (md_pseudo_table): Add longcall and longjump.
+ (md_parse_option): Check for relax option.
+ (tc_gen_reloc): Handle BFD_RELOC_V850_LONGCALL,
+ BFD_RELOC_V850_LONGJUMP, and BFD_RELOC_V850_ALIGN.
+ (md_apply_fix3): Likewise.
+ (v850_force_relocation): Likewise.
+ (v850_comm): Change the current section.
+ (md_assemble): Ensure that the correct value is put in the
+ fixup.
+ (v850_sdata, v850_tdata, v850_zdata, v850_sbss, v850_tbss,
+ v850_zbss, v850_rosdata, v850_rozdata): Fix section book keeping.
+ Remove redundant v850ea support.
+ * tc-v850.h (HANDLE_ALIGN): Define.
+ (v850_handle_align): Declare.
+ * doc/c-v850.c: Document -mrelax, .longcall and .longjump.
+
2002-08-28 Svein E. Seldal <Svein.Seldal@solidas.com>
* configure.in: Add tic4x-coff* and c4x-coff*-coff-coff targets.
diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c
index 2d159cd519..aa789b3dc2 100644
--- a/gas/config/tc-v850.c
+++ b/gas/config/tc-v850.c
@@ -78,6 +78,8 @@ const relax_typeS md_relax_table[] = {
{0x1fffff, -0x200000, 4, 0},
};
+static int v850_relax = 0;
+
/* Fixups. */
#define MAX_INSN_FIXUPS (5)
struct v850_fixup {
@@ -394,7 +396,13 @@ v850_comm (area)
}
else
{
+ segT old_sec;
+ int old_subsec;
+
allocate_common:
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+
S_SET_VALUE (symbolP, (valueT) size);
S_SET_ALIGN (symbolP, temp);
S_SET_EXTERNAL (symbolP);
@@ -411,6 +419,9 @@ v850_comm (area)
default:
abort ();
}
+
+ obj_elf_section_change_hook ();
+ subseg_set (old_sec, old_subsec);
}
}
else
@@ -468,10 +479,45 @@ set_machine (number)
{
case 0: processor_mask = PROCESSOR_V850; break;
case bfd_mach_v850e: processor_mask = PROCESSOR_V850E; break;
- case bfd_mach_v850ea: processor_mask = PROCESSOR_V850EA; break;
}
}
+static void v850_longcode PARAMS ((int));
+
+static void
+v850_longcode (type)
+ int type;
+{
+ expressionS ex;
+
+ if (! v850_relax)
+ {
+ if (type == 1)
+ as_warn (".longcall pseudo-op seen when not relaxing");
+ else
+ as_warn (".longjump pseudo-op seen when not relaxing");
+ }
+
+ expression (&ex);
+
+ if (ex.X_op != O_symbol || ex.X_add_number != 0)
+ {
+ as_bad ("bad .longcall format");
+ ignore_rest_of_line ();
+
+ return;
+ }
+
+ if (type == 1)
+ fix_new_exp (frag_now, frag_now_fix (), 4, & ex, 1,
+ BFD_RELOC_V850_LONGCALL);
+ else
+ fix_new_exp (frag_now, frag_now_fix (), 4, & ex, 1,
+ BFD_RELOC_V850_LONGJUMP);
+
+ demand_empty_rest_of_line ();
+}
+
/* The target specific pseudo-ops which we support. */
const pseudo_typeS md_pseudo_table[] = {
{ "sdata", v850_seg, SDATA_SECTION },
@@ -492,9 +538,10 @@ const pseudo_typeS md_pseudo_table[] = {
{ "call_table_data", v850_seg, CALL_TABLE_DATA_SECTION },
{ "call_table_text", v850_seg, CALL_TABLE_TEXT_SECTION },
{ "v850e", set_machine, bfd_mach_v850e },
- { "v850ea", set_machine, bfd_mach_v850ea },
{ "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 0 },
+ { "longcall", v850_longcode, 1 },
+ { "longjump", v850_longcode, 2 },
{ NULL, NULL, 0 }
};
@@ -1103,8 +1150,9 @@ md_show_usage (stream)
fprintf (stream, _(" -mwarn-unsigned-overflow Warn if unsigned immediate values overflow\n"));
fprintf (stream, _(" -mv850 The code is targeted at the v850\n"));
fprintf (stream, _(" -mv850e The code is targeted at the v850e\n"));
- fprintf (stream, _(" -mv850ea The code is targeted at the v850ea\n"));
fprintf (stream, _(" -mv850any The code is generic, despite any processor specific instructions\n"));
+ fprintf (stream, _(" -mrelax Enable relaxation\n"));
+
}
int
@@ -1138,19 +1186,16 @@ md_parse_option (c, arg)
machine = bfd_mach_v850e;
processor_mask = PROCESSOR_V850E;
}
- else if (strcmp (arg, "v850ea") == 0)
- {
- machine = bfd_mach_v850ea;
- processor_mask = PROCESSOR_V850EA;
- }
else if (strcmp (arg, "v850any") == 0)
{
/* Tell the world that this is for any v850 chip. */
machine = 0;
/* But support instructions for the extended versions. */
- processor_mask = PROCESSOR_V850EA;
+ processor_mask = PROCESSOR_V850E;
}
+ else if (strcmp (arg, "relax") == 0)
+ v850_relax = 1;
else
{
/* xgettext:c-format */
@@ -1275,17 +1320,9 @@ void
md_begin ()
{
char *prev_name = "";
- register const struct v850_opcode *op;
-
- if (strncmp (TARGET_CPU, "v850ea", 6) == 0)
- {
- if (machine == -1)
- machine = bfd_mach_v850ea;
+ const struct v850_opcode *op;
- if (processor_mask == -1)
- processor_mask = PROCESSOR_V850EA;
- }
- else if (strncmp (TARGET_CPU, "v850e", 5) == 0)
+ if (strncmp (TARGET_CPU, "v850e", 5) == 0)
{
if (machine == -1)
machine = bfd_mach_v850e;
@@ -1750,8 +1787,7 @@ md_assemble (str)
extra_data_after_insn = true;
extra_data_len = 4;
- extra_data = ex.X_add_number;
- ex.X_add_number = 0;
+ extra_data = 0;
break;
default:
@@ -2215,12 +2251,32 @@ tc_gen_reloc (seg, fixp)
if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
|| fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
reloc->addend = fixp->fx_offset;
+ else if ( fixp->fx_r_type == BFD_RELOC_V850_LONGCALL
+ || fixp->fx_r_type == BFD_RELOC_V850_LONGJUMP
+ || fixp->fx_r_type == BFD_RELOC_V850_ALIGN)
+ reloc->addend = fixp->fx_offset;
else
reloc->addend = fixp->fx_addnumber;
return reloc;
}
+void
+v850_handle_align (frag)
+ fragS * frag;
+{
+ if (v850_relax
+ && frag->fr_type == rs_align
+ && frag->fr_address + frag->fr_fix > 0
+ && frag->fr_offset > 1
+ && now_seg != bss_section
+ && now_seg != v850_seg_table[SBSS_SECTION].s
+ && now_seg != v850_seg_table[TBSS_SECTION].s
+ && now_seg != v850_seg_table[ZBSS_SECTION].s)
+ fix_new (frag, frag->fr_fix, 2, & abs_symbol, frag->fr_offset, 0,
+ BFD_RELOC_V850_ALIGN);
+}
+
/* Return current size of variable part of frag. */
int
@@ -2261,6 +2317,8 @@ md_apply_fix3 (fixP, valueP, seg)
char *where;
if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_V850_LONGCALL
+ || fixP->fx_r_type == BFD_RELOC_V850_LONGJUMP
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
{
fixP->fx_done = 0;
@@ -2268,10 +2326,11 @@ md_apply_fix3 (fixP, valueP, seg)
}
if (fixP->fx_addsy == (symbolS *) NULL)
+ fixP->fx_addnumber = value,
fixP->fx_done = 1;
else if (fixP->fx_pcrel)
- ;
+ fixP->fx_addnumber = fixP->fx_offset;
else
{
@@ -2287,6 +2346,7 @@ md_apply_fix3 (fixP, valueP, seg)
_("expression too complex"));
}
}
+ fixP->fx_addnumber = value;
}
if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
@@ -2345,8 +2405,6 @@ md_apply_fix3 (fixP, valueP, seg)
else if (fixP->fx_size == 4)
bfd_putl32 (value, (unsigned char *) where);
}
-
- fixP->fx_addnumber = value;
}
/* Parse a cons expression. We have to handle hi(), lo(), etc
@@ -2430,5 +2488,17 @@ v850_force_relocation (fixP)
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 1;
+ if ( fixP->fx_r_type == BFD_RELOC_V850_LONGCALL
+ || fixP->fx_r_type == BFD_RELOC_V850_LONGJUMP)
+ return 1;
+
+ if (v850_relax
+ && (fixP->fx_pcrel
+ || fixP->fx_r_type == BFD_RELOC_V850_ALIGN
+ || fixP->fx_r_type == BFD_RELOC_V850_22_PCREL
+ || fixP->fx_r_type == BFD_RELOC_V850_9_PCREL
+ || fixP->fx_r_type >= BFD_RELOC_UNUSED))
+ return 1;
+
return 0;
}
diff --git a/gas/config/tc-v850.h b/gas/config/tc-v850.h
index 8257428eab..f3827e7c9c 100644
--- a/gas/config/tc-v850.h
+++ b/gas/config/tc-v850.h
@@ -70,6 +70,11 @@ extern void cons_fix_new_v850 PARAMS ((fragS *, int, int, expressionS *));
#define TC_GENERIC_RELAX_TABLE md_relax_table
extern const struct relax_type md_relax_table[];
+/* When relaxing, we need to generate
+ relocations for alignment directives. */
+#define HANDLE_ALIGN(frag) v850_handle_align (frag)
+extern void v850_handle_align PARAMS ((fragS *));
+
/* This section must be in the small data area (pointed to by GP). */
#define SHF_V850_GPREL 0x10000000
/* This section must be in the tiny data area (pointed to by EP). */
diff --git a/gas/doc/c-v850.texi b/gas/doc/c-v850.texi
index 4b36461ee5..f67ad5c743 100644
--- a/gas/doc/c-v850.texi
+++ b/gas/doc/c-v850.texi
@@ -62,6 +62,14 @@ routines used by the code produced by GCC for all versions of the v850
architecture, together with support routines only used by the V850E
architecture.
+@cindex @code{-mrelax} command line option, V850
+@item -mrelax
+Enables relaxation. This allows the .longcall and .longjump pseudo
+ops to be used in the assembler source code. These ops label sections
+of code which are either a long function call or a long branch. The
+assembler will then flag these sections of code and the linker will
+attempt to relax them.
+
@end table
@@ -354,10 +362,23 @@ example:
will put the call the function whoes address is held in the call table
at the location labeled 'table_func1'.
+@cindex @code{longcall} pseudo-op, V850
+@item .longcall @code{name}
+Indicates that the following sequence of instructions is a long call
+to function @code{name}. The linker will attempt to shorten this call
+sequence if @code{name} is within a 22bit offset of the call. Only
+valid if the @code{-mrelax} command line switch has been enabled.
+
+@cindex @code{longjump} pseudo-op, V850
+@item .longjump @code{name}
+Indicates that the following sequence of instructions is a long jump
+to label @code{name}. The linker will attempt to shorten this code
+sequence if @code{name} is within a 22bit offset of the jump. Only
+valid if the @code{-mrelax} command line switch has been enabled.
+
@end table
For information on the V850 instruction set, see @cite{V850
Family 32-/16-Bit single-Chip Microcontroller Architecture Manual} from NEC.
Ltd.
-
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index a7dfa25965..0ffa6ab9d3 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,8 @@
+2002-08-28 Catherine Moore <clm@redhat.com>
+
+ * elf/v850.h (R_V850_LONGCALL, R_V850_ALIGN,
+ R_V850_LONGJUMP): New relocations.
+
2002-08-15 Alan Modra <amodra@bigpond.net.au>
* i370.h: Define relocs using reloc-macros.h.
diff --git a/include/elf/v850.h b/include/elf/v850.h
index 62b9541e8e..a15c9ee086 100644
--- a/include/elf/v850.h
+++ b/include/elf/v850.h
@@ -1,22 +1,22 @@
/* V850 ELF support for BFD.
- Copyright 1997, 1998, 2000 Free Software Foundation, Inc.
+ Copyright 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
Created by Michael Meissner, Cygnus Support <meissner@cygnus.com>
-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. */
/* This file holds definitions specific to the MIPS ELF ABI. Note
that most of this is not actually implemented by BFD. */
@@ -35,18 +35,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* v850e code. */
#define E_V850E_ARCH 0x10000000
-/* v850ea code. */
-#define E_V850EA_ARCH 0x20000000
+/* Flags for the st_other field. */
+#define V850_OTHER_SDA 0x01 /* Symbol had SDA relocations. */
+#define V850_OTHER_ZDA 0x02 /* Symbol had ZDA relocations. */
+#define V850_OTHER_TDA 0x04 /* Symbol had TDA relocations. */
+#define V850_OTHER_TDA_BYTE 0x08 /* Symbol had TDA byte relocations. */
+#define V850_OTHER_ERROR 0x80 /* Symbol had an error reported. */
-/* Flags for the st_other field */
-#define V850_OTHER_SDA 0x01 /* symbol had SDA relocations */
-#define V850_OTHER_ZDA 0x02 /* symbol had ZDA relocations */
-#define V850_OTHER_TDA 0x04 /* symbol had TDA relocations */
-#define V850_OTHER_TDA_BYTE 0x08 /* symbol had TDA byte relocations */
-#define V850_OTHER_ERROR 0x80 /* symbol had an error reported */
-
-/* V850 relocations */
+/* V850 relocations. */
#include "elf/reloc-macros.h"
START_RELOC_NUMBERS (v850_reloc_type)
@@ -75,6 +72,9 @@ START_RELOC_NUMBERS (v850_reloc_type)
RELOC_NUMBER( R_V850_CALLT_16_16_OFFSET, 22) /* For callt */
RELOC_NUMBER (R_V850_GNU_VTINHERIT, 23)
RELOC_NUMBER (R_V850_GNU_VTENTRY, 24)
+ RELOC_NUMBER (R_V850_LONGCALL, 25)
+ RELOC_NUMBER (R_V850_LONGJUMP, 26)
+ RELOC_NUMBER (R_V850_ALIGN, 27)
END_RELOC_NUMBERS (R_V850_max)
@@ -103,5 +103,4 @@ END_RELOC_NUMBERS (R_V850_max)
/* Section contains the .scommon data. */
#define SHT_V850_ZCOMMON 0x70000002
-
#endif /* _ELF_V850_H */