summaryrefslogtreecommitdiff
path: root/bfd/elf32-v850.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2012-11-09 17:36:11 +0000
committerNick Clifton <nickc@redhat.com>2012-11-09 17:36:11 +0000
commit79f5ae397a764b301812c93498ac2a8b666deae8 (patch)
tree5e25a342915b8201fe787e6093c4380e483de1af /bfd/elf32-v850.c
parent2f531e6be1e97d868ef473752be670bac26e966f (diff)
downloadbinutils-redhat-79f5ae397a764b301812c93498ac2a8b666deae8.tar.gz
2012-11-09 Nick Clifton <nickc@redhat.com>
* Makefile.am (ALL_MACHINES): Add cpu-v850-rh850.lo. (ALL_MACHINES_CFILES): Add cpu-v850-rh850.c. * archures.c (bfd_arch_info): Add bfd_v850_rh850_arch. * config.bfd: Likewise. * configure.in: Add bfd_elf32_v850_rh850_vec. * cpu-v850.c: Update printed description. * cpu-v850_rh850.c: New file. * elf32-v850.c (v850_elf_check_relocs): Add support for RH850 ABI relocs. (v850_elf_perform_relocation): Likewise. (v850_elf_final_link_relocate): Likewise. (v850_elf_relocate_section): Likewise. (v850_elf_relax_section): Likewise. (v800_elf_howto_table): New. (v850_elf_object_p): Add support for RH850 ABI values. (v850_elf_final_write_processing): Likewise. (v850_elf_merge_private_bfd_data): Likewise. (v850_elf_print_private_bfd_data): Likewise. (v800_elf_reloc_map): New. (v800_elf_reloc_type_lookup): New. (v800_elf_reloc_name_lookup): New. (v800_elf_info_to_howto): New. (bfd_elf32_v850_rh850_vec): New. (bfd_arch_v850_rh850): New. * targets.c (_bfd_targets): Add bfd_elf32_v850_rh850_vec. * Makefile.in: Regenerate. * bfd-in2.h: Regenerate. * configure: Regenerate. * readelf.c (get_machine_flags): Add support for E_FLAG_RX_ABI. (guess_is_rela): Add EM_V800. (dump_relocations): Likewise. (get_machine_name): Update EM_V800. (get_machine_flags): Add support for RH850 ABI flags. (is_32bit_abs_reloc): Add support for RH850 ABI reloc. * config/tc-v850.c (v850_target_arch): New. (v850_target_format): New. (set_machine): Use v850_target_arch. (md_begin): Likewise. (md_show_usage): Document new switches. (md_parse_option): Add -mgcc-abi, -mrh850-abi, -m8byte-align and -m4byte-align. * config/tc-v850.c (TARGET_ARCH) Use v850_target_arch. (TARGET_FORMAT): Use v850_target_format. * doc/c-v850.texi: Document new options. * v850.h: Add RH850 ABI values. * Makefile.am: (ALL_EMULATION_SOURCES): Add ev850_rh850.c. * Makefile.in: Regenerate. * configure.tgt (v850*-*-*): Make v850_rh850 the default emulation. Add vanilla v850 as an extra emulation. * emulparams/v850_rh850.sh: New file. * scripttempl/v850_rh850.sc: New file. * configure.in: Add bfd_v850_rh850_arch. * configure: Regenerate. * disassemble.c (disassembler): Likewise.
Diffstat (limited to 'bfd/elf32-v850.c')
-rw-r--r--bfd/elf32-v850.c512
1 files changed, 420 insertions, 92 deletions
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 6cf275f279..80e3acbaf2 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -55,7 +55,7 @@ v850_elf_check_relocs (bfd *abfd,
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
- enum v850_reloc_type r_type;
+ unsigned int r_type;
int other = 0;
const char *common = NULL;
@@ -87,32 +87,10 @@ v850_elf_check_relocs (bfd *abfd,
h = (struct elf_link_hash_entry *) h->root.u.i.link;
}
- r_type = (enum v850_reloc_type) ELF32_R_TYPE (rel->r_info);
+ r_type = ELF32_R_TYPE (rel->r_info);
switch (r_type)
{
default:
- case R_V850_NONE:
- case R_V850_9_PCREL:
- case R_V850_16_PCREL:
- case R_V850_17_PCREL:
- case R_V850_22_PCREL:
- case R_V850_32_PCREL:
- case R_V850_32_ABS:
- case R_V850_HI16:
- case R_V850_HI16_S:
- case R_V850_LO16:
- case R_V850_LO16_S1:
- case R_V850_LO16_SPLIT_OFFSET:
- case R_V850_23:
- case R_V850_ABS32:
- case R_V850_REL32:
- case R_V850_16:
- case R_V850_16_S1:
- case R_V850_16_SPLIT_OFFSET:
- case R_V850_8:
- case R_V850_CALLT_6_7_OFFSET:
- case R_V850_CALLT_15_16_OFFSET:
- case R_V850_CALLT_16_16_OFFSET:
break;
/* This relocation describes the C++ object vtable hierarchy.
@@ -134,6 +112,9 @@ v850_elf_check_relocs (bfd *abfd,
case R_V850_SDA_16_16_SPLIT_OFFSET:
case R_V850_SDA_16_16_OFFSET:
case R_V850_SDA_15_16_OFFSET:
+ case R_V810_GPWLO_1:
+ case R_V850_HWLO:
+ case R_V850_HWLO_1:
other = V850_OTHER_SDA;
common = ".scommon";
goto small_data_common;
@@ -510,13 +491,19 @@ v850_elf_perform_relocation (bfd *abfd,
switch (r_type)
{
default:
+#ifdef DEBUG
+ fprintf (stderr, "reloc number %d not recognised\n", r_type);
+#endif
return bfd_reloc_notsupported;
case R_V850_REL32:
case R_V850_ABS32:
+ case R_V810_WORD:
+ case R_V850_PC32:
bfd_put_32 (abfd, addend, address);
return bfd_reloc_ok;
+ case R_V850_WLO23:
case R_V850_23:
insn = bfd_get_32 (abfd, address);
insn &= ~((0x7f << 4) | (0x7fff80 << (16-7)));
@@ -524,6 +511,7 @@ v850_elf_perform_relocation (bfd *abfd,
bfd_put_32 (abfd, (bfd_vma) insn, address);
return bfd_reloc_ok;
+ case R_V850_PCR22:
case R_V850_22_PCREL:
if (saddend > 0x1fffff || saddend < -0x200000)
return bfd_reloc_overflow;
@@ -537,6 +525,7 @@ v850_elf_perform_relocation (bfd *abfd,
bfd_put_32 (abfd, (bfd_vma) insn, address);
return bfd_reloc_ok;
+ case R_V850_PC17:
case R_V850_17_PCREL:
if (saddend > 0xffff || saddend < -0x10000)
return bfd_reloc_overflow;
@@ -549,6 +538,7 @@ v850_elf_perform_relocation (bfd *abfd,
insn |= ((addend & 0xfffe) << 16) | ((addend & 0x10000) >> (16-4));
break;
+ case R_V850_PC16U:
case R_V850_16_PCREL:
if ((saddend < -0xffff) || (saddend > 0))
return bfd_reloc_overflow;
@@ -561,6 +551,7 @@ v850_elf_perform_relocation (bfd *abfd,
insn |= (-addend & 0xfffe);
break;
+ case R_V850_PC9:
case R_V850_9_PCREL:
if (saddend > 0xff || saddend < -0x100)
return bfd_reloc_overflow;
@@ -573,12 +564,14 @@ v850_elf_perform_relocation (bfd *abfd,
insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3);
break;
+ case R_V810_WHI:
case R_V850_HI16:
addend += (bfd_get_16 (abfd, address) << 16);
addend = (addend >> 16);
insn = addend;
break;
+ case R_V810_WHI1:
case R_V850_HI16_S:
/* Remember where this relocation took place. */
remember_hi16s_reloc (abfd, addend, address);
@@ -593,12 +586,14 @@ v850_elf_perform_relocation (bfd *abfd,
insn = addend;
break;
+ case R_V810_WLO:
case R_V850_LO16:
insn = bfd_get_16 (abfd, address);
if (! v850_elf_perform_lo16_relocation (abfd, &insn, addend))
return bfd_reloc_overflow;
break;
+ case R_V810_BYTE:
case R_V850_8:
addend += (char) bfd_get_8 (abfd, address);
@@ -652,6 +647,7 @@ v850_elf_perform_relocation (bfd *abfd,
break;
case R_V850_16:
+ case R_V810_HWORD:
case R_V850_SDA_16_16_OFFSET:
case R_V850_ZDA_16_16_OFFSET:
case R_V850_TDA_16_16_OFFSET:
@@ -668,6 +664,7 @@ v850_elf_perform_relocation (bfd *abfd,
case R_V850_16_S1:
case R_V850_SDA_15_16_OFFSET:
case R_V850_ZDA_15_16_OFFSET:
+ case R_V810_GPWLO_1:
insn = bfd_get_16 (abfd, address);
addend += (insn & 0xfffe);
@@ -756,6 +753,9 @@ v850_elf_perform_relocation (bfd *abfd,
insn |= addend;
break;
+ case R_V810_WLO_1:
+ case R_V850_HWLO:
+ case R_V850_HWLO_1:
case R_V850_LO16_S1:
insn = bfd_get_16 (abfd, address);
result = insn & 0xfffe;
@@ -768,6 +768,7 @@ v850_elf_perform_relocation (bfd *abfd,
bfd_put_16 (abfd, insn, address);
return bfd_reloc_ok;
+ case R_V850_BLO:
case R_V850_LO16_SPLIT_OFFSET:
insn = bfd_get_32 (abfd, address);
result = ((insn & 0xfffe0000) >> 16) | ((insn & 0x20) >> 5);
@@ -886,7 +887,7 @@ v850_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
}
/* Note: It is REQUIRED that the 'type' value of each entry
in this array match the index of the entry in the array.
- SeeAlso: RELOC_NUBMER in include/elf/v850.h */
+ SeeAlso: RELOC_NUBMER in include/elf/v850.h. */
static reloc_howto_type v850_elf_howto_table[] =
{
/* This reloc does nothing. */
@@ -1742,6 +1743,109 @@ static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
{ BFD_RELOC_V850_CODE, R_V850_CODE },
{ BFD_RELOC_V850_DATA, R_V850_DATA },
};
+
+#define V800_RELOC(name,sz,bit,shift,complain,pcrel,resolver) \
+ HOWTO (name, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
+ bfd_elf_ ## resolver ## _reloc, #name, FALSE, 0, ~0, FALSE)
+
+#define V800_EMPTY(name) EMPTY_HOWTO (name - R_V810_NONE)
+
+#define bfd_elf_v850_reloc v850_elf_reloc
+
+/* Note: It is REQUIRED that the 'type' value (R_V810_...) of each entry
+ in this array match the index of the entry in the array minus 0x30.
+ See: bfd_elf_v850_relocate_section(), v800_elf_reloc_type_lookup()
+ and v800_elf_info_to_howto(). */
+
+static reloc_howto_type v800_elf_howto_table[] =
+{
+ V800_RELOC (R_V810_NONE, 0, 0, 0, dont, FALSE, generic), /* Type = 0x30 */
+ V800_RELOC (R_V810_BYTE, 0, 8, 0, dont, FALSE, generic),
+ V800_RELOC (R_V810_HWORD, 1, 16, 0, dont, FALSE, generic),
+ V800_RELOC (R_V810_WORD, 2, 32, 0, dont, FALSE, generic),
+ V800_RELOC (R_V810_WLO, 1, 16, 0, dont, FALSE, generic),
+ V800_RELOC (R_V810_WHI, 1, 16, 0, dont, FALSE, generic),
+ V800_RELOC (R_V810_WHI1, 1, 16, 0, dont, FALSE, generic),
+ V800_RELOC (R_V810_GPBYTE, 0, 8, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_GPHWORD, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_GPWORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_GPWLO, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_GPWHI, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_GPWHI1, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_HWLO, 1, 16, 0, dont, FALSE, generic),
+ V800_EMPTY (R_V810_reserved1),
+ V800_RELOC (R_V850_EP7BIT, 0, 7, 0, unsigned, FALSE, v850),
+ V800_RELOC (R_V850_EPHBYTE, 0, 8, 1, unsigned, FALSE, v850),
+ V800_RELOC (R_V850_EPWBYTE, 0, 8, 2, unsigned, FALSE, v850),
+ V800_RELOC (R_V850_REGHWLO, 1, 16, 0, dont, FALSE, v850),
+ V800_EMPTY (R_V810_reserved2),
+ V800_RELOC (R_V850_GPHWLO, 1, 16, 0, dont, FALSE, v850),
+ V800_EMPTY (R_V810_reserved3),
+ V800_RELOC (R_V850_PCR22, 2, 22, 0, signed, TRUE, generic),
+ V800_RELOC (R_V850_BLO, 2, 24, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_EP4BIT, 0, 4, 0, unsigned, FALSE, v850),
+ V800_RELOC (R_V850_EP5BIT, 0, 5, 0, unsigned, FALSE, v850),
+ V800_RELOC (R_V850_REGBLO, 2, 24, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_GPBLO, 2, 24, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_WLO_1, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_GPWLO_1, 1, 16, 0, signed, FALSE, v850),
+ V800_RELOC (R_V850_BLO_1, 2, 16, 0, signed, FALSE, v850),
+ V800_RELOC (R_V850_HWLO_1, 1, 16, 0, signed, FALSE, v850),
+ V800_EMPTY (R_V810_reserved4),
+ V800_RELOC (R_V850_GPBLO_1, 2, 16, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_GPHWLO_1, 1, 16, 1, signed, FALSE, v850),
+ V800_EMPTY (R_V810_reserved5),
+ V800_RELOC (R_V850_EPBLO, 2, 16, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_EPHWLO, 1, 16, 1, signed, FALSE, v850),
+ V800_EMPTY (R_V810_reserved6),
+ V800_RELOC (R_V850_EPWLO_N, 1, 16, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_PC32, 2, 32, 1, signed, TRUE, v850),
+ V800_RELOC (R_V850_W23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_GPW23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_EPW23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_B23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_GPB23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_EPB23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_PC16U, 1, 16, 1, unsigned, TRUE, generic),
+ V800_RELOC (R_V850_PC17, 2, 17, 1, signed, TRUE, generic),
+ V800_RELOC (R_V850_DW8, 2, 8, 2, signed, FALSE, v850),
+ V800_RELOC (R_V850_GPDW8, 2, 8, 2, signed, FALSE, v850),
+ V800_RELOC (R_V850_EPDW8, 2, 8, 2, signed, FALSE, v850),
+ V800_RELOC (R_V850_PC9, 1, 9, 3, signed, TRUE, v850),
+ V800_RELOC (R_V810_REGBYTE, 0, 8, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_REGHWORD, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_REGWORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_REGWLO, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_REGWHI, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_REGWHI1, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_REGW23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_REGB23BIT, 2, 23, 1, signed, FALSE, v850),
+ V800_RELOC (R_V850_REGDW8, 2, 8, 2, signed, FALSE, v850),
+ V800_RELOC (R_V810_EPBYTE, 0, 8, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_EPHWORD, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_EPWORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_WLO23, 2, 32, 1, dont, FALSE, v850),
+ V800_RELOC (R_V850_WORD_E, 2, 32, 1, dont, FALSE, v850),
+ V800_RELOC (R_V850_REGWORD_E, 2, 32, 1, dont, FALSE, v850),
+ V800_RELOC (R_V850_WORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_GPWORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_REGWORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_EPWORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_TPBYTE, 0, 8, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_TPHWORD, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_TPWORD, 2, 32, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_TPWLO, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_TPWHI, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_TPWHI1, 1, 16, 0, dont, FALSE, v850),
+ V800_RELOC (R_V850_TPHWLO, 1, 16, 1, dont, FALSE, v850),
+ V800_RELOC (R_V850_TPBLO, 2, 24, 0, dont, FALSE, v850),
+ V800_RELOC (R_V810_TPWLO_1, 1, 16, 0, signed, FALSE, v850),
+ V800_RELOC (R_V850_TPBLO_1, 2, 16, 0, signed, FALSE, v850),
+ V800_RELOC (R_V850_TPHWLO_1, 1, 16, 0, signed, FALSE, v850),
+ V800_RELOC (R_V850_TP23BIT, 2, 23, 0, signed, FALSE, v850),
+ V800_RELOC (R_V850_TPW23BIT, 2, 23, 0, signed, FALSE, v850),
+ V800_RELOC (R_V850_TPDW8, 2, 8, 0, signed, FALSE, v850)
+};
/* Map a bfd relocation into the appropriate howto structure. */
@@ -1841,12 +1945,14 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
/* Adjust the value according to the relocation. */
switch (r_type)
{
+ case R_V850_PC9:
case R_V850_9_PCREL:
value -= (input_section->output_section->vma
+ input_section->output_offset);
value -= offset;
break;
+ case R_V850_PC16U:
case R_V850_16_PCREL:
value -= (input_section->output_section->vma
+ input_section->output_offset
@@ -1858,6 +1964,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
break;
+ case R_V850_PC17:
case R_V850_17_PCREL:
value -= (input_section->output_section->vma
+ input_section->output_offset
@@ -1870,6 +1977,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
value = SEXT17 (value);
break;
+ case R_V850_PCR22:
case R_V850_22_PCREL:
value -= (input_section->output_section->vma
+ input_section->output_offset
@@ -1883,6 +1991,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
value = SEXT22 (value);
break;
+ case R_V850_PC32:
case R_V850_32_PCREL:
value -= (input_section->output_section->vma
+ input_section->output_offset
@@ -1899,6 +2008,15 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
case R_V850_16:
case R_V850_ABS32:
case R_V850_8:
+ case R_V810_BYTE:
+ case R_V810_HWORD:
+ case R_V810_WORD:
+ case R_V810_WLO:
+ case R_V810_WHI:
+ case R_V810_WHI1:
+ case R_V810_WLO_1:
+ case R_V850_WLO23:
+ case R_V850_BLO:
break;
case R_V850_ZDA_15_16_OFFSET:
@@ -1913,6 +2031,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
case R_V850_SDA_15_16_OFFSET:
case R_V850_SDA_16_16_OFFSET:
case R_V850_SDA_16_16_SPLIT_OFFSET:
+ case R_V810_GPWLO_1:
{
unsigned long gp;
struct bfd_link_hash_entry * h;
@@ -2002,6 +2121,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
break;
case R_V850_NONE:
+ case R_V810_NONE:
case R_V850_GNU_VTINHERIT:
case R_V850_GNU_VTENTRY:
case R_V850_LONGCALL:
@@ -2010,6 +2130,9 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
return bfd_reloc_ok;
default:
+#ifdef DEBUG
+ fprintf (stderr, "reloc number %d not recognised\n", r_type);
+#endif
return bfd_reloc_notsupported;
}
@@ -2046,7 +2169,7 @@ v850_elf_relocate_section (bfd *output_bfd,
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
{
- int r_type;
+ unsigned int r_type;
reloc_howto_type *howto;
unsigned long r_symndx;
Elf_Internal_Sym *sym;
@@ -2062,7 +2185,13 @@ v850_elf_relocate_section (bfd *output_bfd,
|| r_type == R_V850_GNU_VTINHERIT)
continue;
- howto = v850_elf_howto_table + r_type;
+ if (bfd_get_arch (input_bfd) == bfd_arch_v850_rh850)
+ howto = v800_elf_howto_table + (r_type - R_V810_NONE);
+ else
+ howto = v850_elf_howto_table + r_type;
+
+ BFD_ASSERT (r_type == howto->type);
+
h = NULL;
sym = NULL;
sec = NULL;
@@ -2199,31 +2328,40 @@ v850_elf_gc_mark_hook (asection *sec,
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
-/* Set the right machine number. */
+/* Set the right machine number and architecture. */
static bfd_boolean
v850_elf_object_p (bfd *abfd)
{
- switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
+ enum bfd_architecture arch;
+ unsigned long mach;
+
+ switch (elf_elfheader (abfd)->e_machine)
{
- default:
- 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);
+ case EM_V800:
+ arch = bfd_arch_v850_rh850;
+ mach = bfd_mach_v850e2v3;
break;
- case E_V850E2_ARCH:
- bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e2);
- break;
- case E_V850E2V3_ARCH:
- bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e2v3);
+
+ case EM_CYGNUS_V850:
+ case EM_V850:
+ arch = bfd_arch_v850;
+ switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
+ {
+ default:
+ case E_V850_ARCH: mach = bfd_mach_v850; break;
+ case E_V850E_ARCH: mach = bfd_mach_v850e; break;
+ case E_V850E1_ARCH: mach = bfd_mach_v850e1; break;
+ case E_V850E2_ARCH: mach = bfd_mach_v850e2; break;
+ case E_V850E2V3_ARCH: mach = bfd_mach_v850e2v3; break;
+ }
break;
+
+ default:
+ return FALSE;
}
- return TRUE;
+
+ return bfd_default_set_arch_mach (abfd, arch, mach);
}
/* Store the machine number in the flags field. */
@@ -2234,18 +2372,29 @@ v850_elf_final_write_processing (bfd *abfd,
{
unsigned long val;
- switch (bfd_get_mach (abfd))
+ switch (bfd_get_arch (abfd))
{
+ case bfd_arch_v850_rh850:
+ val = EF_RH850_ABI;
+ elf_elfheader (abfd)->e_flags |= val;
+ break;
+
+ case bfd_arch_v850:
+ switch (bfd_get_mach (abfd))
+ {
+ default:
+ 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;
+ case bfd_mach_v850e2: val = E_V850E2_ARCH; break;
+ case bfd_mach_v850e2v3: val = E_V850E2V3_ARCH; break;
+ }
+ elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
+ elf_elfheader (abfd)->e_flags |= val;
+ break;
default:
- 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;
- case bfd_mach_v850e2: val = E_V850E2_ARCH; break;
- case bfd_mach_v850e2v3: val = E_V850E2V3_ARCH; break;
+ break;
}
-
- elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
- elf_elfheader (abfd)->e_flags |= val;
}
/* Function to keep V850 specific file flags. */
@@ -2302,17 +2451,36 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
if (in_flags == out_flags)
return TRUE;
+ if (bfd_get_arch (obfd) == bfd_arch_v850_rh850)
+ {
+ if ((in_flags & EF_V800_850E3) != (out_flags & EF_V800_850E3))
+ {
+ _bfd_error_handler (_("%B: Architecture mismatch with previous modules"),
+ ibfd);
+ elf_elfheader (obfd)->e_flags |= EF_V800_850E3;
+ }
+
+ if ((in_flags & EF_RH850_DATA_ALIGN8) != (out_flags & EF_RH850_DATA_ALIGN8))
+ {
+ _bfd_error_handler (_("%B: Alignment mismatch with previous modules"),
+ ibfd);
+ elf_elfheader (obfd)->e_flags |= EF_RH850_DATA_ALIGN8;
+ }
+
+ return TRUE;
+ }
+
if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH)
&& (in_flags & EF_V850_ARCH) != E_V850_ARCH)
{
-
- /* Allow v850e1 binaries to be linked with v850e binaries.
- Set the output binary to v850e. */
- if ((in_flags & EF_V850_ARCH) == E_V850E1_ARCH
+ /* Allow earlier architecture binaries to be linked with later binaries.
+ Set the output binary to the later architecture, except for v850e1,
+ which we set 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_V850_ARCH
+ if ( (in_flags & EF_V850_ARCH) == E_V850_ARCH
&& (out_flags & EF_V850_ARCH) == E_V850E_ARCH)
{
elf_elfheader (obfd)->e_flags =
@@ -2320,7 +2488,7 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
return TRUE;
}
- if (((in_flags & EF_V850_ARCH) == E_V850_ARCH
+ if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH
|| (in_flags & EF_V850_ARCH) == E_V850E_ARCH)
&& (out_flags & EF_V850_ARCH) == E_V850E2_ARCH)
{
@@ -2329,7 +2497,7 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
return TRUE;
}
- if (((in_flags & EF_V850_ARCH) == E_V850_ARCH
+ if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH
|| (in_flags & EF_V850_ARCH) == E_V850E_ARCH
|| (in_flags & EF_V850_ARCH) == E_V850E2_ARCH)
&& (out_flags & EF_V850_ARCH) == E_V850E2V3_ARCH)
@@ -2360,14 +2528,29 @@ v850_elf_print_private_bfd_data (bfd *abfd, void * ptr)
/* xgettext:c-format. */
fprintf (file, _("private flags = %lx: "), elf_elfheader (abfd)->e_flags);
- switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850)
{
- default:
- case E_V850_ARCH: fprintf (file, _("v850 architecture")); break;
- case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break;
- case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break;
- case E_V850E2_ARCH: fprintf (file, _("v850e2 architecture")); break;
- case E_V850E2V3_ARCH: fprintf (file, _("v850e2v3 architecture")); break;
+ if ((elf_elfheader (abfd)->e_flags & EF_RH850_ABI) != EF_RH850_ABI)
+ fprintf (file, _("unknown v850 architecture"));
+ else if (elf_elfheader (abfd)->e_flags & EF_V800_850E3)
+ fprintf (file, _("v850 E3 architecture"));
+ else
+ fprintf (file, _("v850 architecture"));
+
+ if (elf_elfheader (abfd)->e_flags & EF_RH850_DATA_ALIGN8)
+ fprintf (file, _(", 8-byte data alignment"));
+ }
+ else
+ {
+ switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
+ {
+ default:
+ case E_V850_ARCH: fprintf (file, _("v850 architecture")); break;
+ case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break;
+ case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break;
+ case E_V850E2_ARCH: fprintf (file, _("v850e2 architecture")); break;
+ case E_V850E2V3_ARCH: fprintf (file, _("v850e2v3 architecture")); break;
+ }
}
fputc ('\n', file);
@@ -2965,6 +3148,7 @@ v850_elf_relax_section (bfd *abfd,
Elf_Internal_Rela *lo_irelfn;
Elf_Internal_Rela *irelcall;
bfd_signed_vma foff;
+ unsigned int r_type;
if (! (irel->r_offset >= addr && irel->r_offset < toaddr
&& (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL
@@ -3060,23 +3244,33 @@ v850_elf_relax_section (bfd *abfd,
/* 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;
+ {
+ r_type = ELF32_R_TYPE (hi_irelfn->r_info);
+
+ if (hi_irelfn->r_offset == laddr + 2
+ && (r_type == (int) R_V850_HI16_S || r_type == (int) R_V810_WHI1))
+ 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;
+ {
+ r_type = ELF32_R_TYPE (lo_irelfn->r_info);
+
+ if (lo_irelfn->r_offset == laddr + 6
+ && (r_type == (int) R_V850_LO16 || r_type == (int) R_V810_WLO))
+ 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;
+ {
+ r_type = ELF32_R_TYPE (irelcall->r_info);
+
+ if (irelcall->r_offset == laddr + 8
+ && (r_type == (int) R_V850_22_PCREL || r_type == (int) R_V850_PCR22))
+ break;
+ }
if ( hi_irelfn == irelend
|| lo_irelfn == irelend
@@ -3202,7 +3396,10 @@ v850_elf_relax_section (bfd *abfd,
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);
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850)
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_PCR22);
+ else
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_22_PCREL);
addend = 0;
@@ -3278,14 +3475,22 @@ v850_elf_relax_section (bfd *abfd,
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;
+ {
+ r_type = ELF32_R_TYPE (hi_irelfn->r_info);
+
+ if (hi_irelfn->r_offset == laddr + 2
+ && ((r_type == (int) R_V850_HI16_S) || r_type == (int) R_V810_WHI1))
+ 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;
+ {
+ r_type = ELF32_R_TYPE (lo_irelfn->r_info);
+
+ if (lo_irelfn->r_offset == laddr + 6
+ && (r_type == (int) R_V850_LO16 || r_type == (int) R_V810_WLO))
+ break;
+ }
if ( hi_irelfn == irelend
|| lo_irelfn == irelend)
@@ -3392,8 +3597,11 @@ v850_elf_relax_section (bfd *abfd,
{
/* Replace the long jump with a jr. */
- irel->r_info =
- ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_22_PCREL);
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850)
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_PCR22);
+ else
+ irel->r_info =
+ ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_22_PCREL);
irel->r_addend = addend;
addend = 0;
@@ -3425,8 +3633,11 @@ v850_elf_relax_section (bfd *abfd,
{
/* Replace the long jump with a br. */
- irel->r_info =
- ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_9_PCREL);
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850)
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_PC9);
+ else
+ irel->r_info =
+ ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_9_PCREL);
irel->r_addend = addend;
addend = 0;
@@ -3539,7 +3750,6 @@ static const struct bfd_elf_special_section v850_elf_special_sections[] =
#define ELF_ARCH bfd_arch_v850
#define ELF_MACHINE_CODE EM_V850
#define ELF_MACHINE_ALT1 EM_CYGNUS_V850
-#define ELF_MACHINE_ALT2 EM_V800 /* This is the value used by the GreenHills toolchain. */
#define ELF_MAXPAGESIZE 0x1000
#define elf_info_to_howto v850_elf_info_to_howto_rela
@@ -3563,7 +3773,7 @@ static const struct bfd_elf_special_section v850_elf_special_sections[] =
#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_reloc_name_lookup v850_elf_reloc_name_lookup
+#define bfd_elf32_bfd_reloc_name_lookup v850_elf_reloc_name_lookup
#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
@@ -3571,4 +3781,122 @@ static const struct bfd_elf_special_section v850_elf_special_sections[] =
#define elf_symbol_leading_char '_'
+#undef elf32_bed
+#define elf32_bed elf32_v850_bed
+
+#include "elf32-target.h"
+
+/* Map BFD reloc types to V800 ELF reloc types. */
+
+static const struct v850_elf_reloc_map v800_elf_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_V810_NONE },
+ { BFD_RELOC_8, R_V810_BYTE },
+ { BFD_RELOC_16, R_V810_HWORD },
+ { BFD_RELOC_32, R_V810_WORD },
+ { BFD_RELOC_LO16, R_V810_WLO },
+ { BFD_RELOC_HI16, R_V810_WHI },
+ { BFD_RELOC_HI16_S, R_V810_WHI1 },
+ { BFD_RELOC_V850_32_PCREL, R_V850_PC32 },
+ { BFD_RELOC_V850_22_PCREL, R_V850_PCR22 },
+ { BFD_RELOC_V850_17_PCREL, R_V850_PC17 },
+ { BFD_RELOC_V850_16_PCREL, R_V850_PC16U },
+ { BFD_RELOC_V850_9_PCREL, R_V850_PC9 },
+ { BFD_RELOC_V850_LO16_S1, R_V810_WLO_1 }, /* Or R_V850_HWLO or R_V850_HWLO_1. */
+ { BFD_RELOC_V850_23, R_V850_WLO23 },
+ { BFD_RELOC_V850_LO16_SPLIT_OFFSET, R_V850_BLO },
+ { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V810_HWORD },
+ { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V810_HWORD },
+ { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V810_HWORD },
+ { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V810_GPWLO_1 }
+};
+
+/* Map a bfd relocation into the appropriate howto structure. */
+
+static reloc_howto_type *
+v800_elf_reloc_type_lookup (bfd * abfd, bfd_reloc_code_real_type code)
+{
+ unsigned int i;
+
+ BFD_ASSERT (bfd_get_arch (abfd) == bfd_arch_v850_rh850);
+
+ for (i = ARRAY_SIZE (v800_elf_reloc_map); i --;)
+ if (v800_elf_reloc_map[i].bfd_reloc_val == code)
+ {
+ unsigned int elf_reloc_val = v800_elf_reloc_map[i].elf_reloc_val;
+ unsigned int idx = elf_reloc_val - R_V810_NONE;
+
+ BFD_ASSERT (v800_elf_howto_table[idx].type == elf_reloc_val);
+
+ return v800_elf_howto_table + idx;
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "failed to find v800 equiv of bfd reloc code %d\n", code);
+#endif
+ return NULL;
+}
+
+static reloc_howto_type *
+v800_elf_reloc_name_lookup (bfd * abfd, const char * r_name)
+{
+ unsigned int i;
+
+ BFD_ASSERT (bfd_get_arch (abfd) == bfd_arch_v850_rh850);
+
+ for (i = ARRAY_SIZE (v800_elf_howto_table); i--;)
+ if (v800_elf_howto_table[i].name != NULL
+ && strcasecmp (v800_elf_howto_table[i].name, r_name) == 0)
+ return v800_elf_howto_table + i;
+
+ return NULL;
+}
+
+
+/* Set the howto pointer in CACHE_PTR for a V800 ELF reloc. */
+
+static void
+v800_elf_info_to_howto (bfd * abfd,
+ arelent * cache_ptr,
+ Elf_Internal_Rela * dst)
+{
+ unsigned int r_type = ELF32_R_TYPE (dst->r_info);
+
+ BFD_ASSERT (bfd_get_arch (abfd) == bfd_arch_v850_rh850);
+
+ BFD_ASSERT (r_type < (unsigned int) R_V800_max);
+
+ if (r_type == R_V800_NONE)
+ r_type = R_V810_NONE;
+
+ BFD_ASSERT (r_type >= (unsigned int) R_V810_NONE);
+ r_type -= R_V810_NONE;
+ BFD_ASSERT (r_type < ARRAY_SIZE (v800_elf_howto_table));
+
+ cache_ptr->howto = v800_elf_howto_table + r_type;
+}
+
+
+#undef TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM bfd_elf32_v850_rh850_vec
+#undef TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME "elf32-v850-rh850"
+#undef ELF_ARCH
+#define ELF_ARCH bfd_arch_v850_rh850
+#undef ELF_MACHINE_CODE
+#define ELF_MACHINE_CODE EM_V800
+#undef ELF_MACHINE_ALT1
+
+#undef elf32_bed
+#define elf32_bed elf32_v850_rh850_bed
+
+#undef elf_info_to_howto
+#define elf_info_to_howto v800_elf_info_to_howto
+#undef elf_info_to_howto_rel
+#define elf_info_to_howto_rel NULL
+#undef bfd_elf32_bfd_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_type_lookup v800_elf_reloc_type_lookup
+#undef bfd_elf32_bfd_reloc_name_lookup
+#define bfd_elf32_bfd_reloc_name_lookup v800_elf_reloc_name_lookup
+
#include "elf32-target.h"