diff options
author | Nick Clifton <nickc@redhat.com> | 2015-03-19 15:37:43 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-03-19 15:37:43 +0000 |
commit | 1740ba0cec44bdfe9cba586892a5953a4c602228 (patch) | |
tree | 26294748df3121fa55f1be80dce4027b1aff3f18 /bfd/elf32-rl78.c | |
parent | 8bf3b159e55b42bb084f9da1af400a285025618f (diff) | |
download | fsf-binutils-gdb-1740ba0cec44bdfe9cba586892a5953a4c602228.zip fsf-binutils-gdb-1740ba0cec44bdfe9cba586892a5953a4c602228.tar.gz fsf-binutils-gdb-1740ba0cec44bdfe9cba586892a5953a4c602228.tar.bz2 |
Add support for G13 and G14 flag bits in RL78 ELF binaries.
inc * rl78.h (E_FLAG_RL78_G10): Redefine.
(E_FLAG_RL78_CPU_MASK, E_FLAG_RL78_ANY_CPU, E_FLAG_RL78_G13
E_FLAG_RL78_G14): New flags.
bin * readelf.c (get_machine_flags): Decode RL78's G13 and G14 flags.
gas * config/tc-rl78.c (enum options): Add G13 and G14.
(md_longopts): Add -mg13 and -mg14.
(md_parse_option): Handle -mg13 and -mg14.
(md_show_usage): List -mg13 and -mg14.
* doc/c-rl78.texi: Add description of -mg13 and -mg14 options.
bfd * elf32-rl78.c (rl78_cpu_name): New function. Prints the name of
the RL78 core based upon the flags.
(rl78_elf_merge_private_bfd_data): Handle merging of G13 and G14
flags.
(rl78_elf_print_private_bfd_data): Use rl78_cpu_name.
(elf32_rl78_machine): Always return bfd_mach_rl78.
Diffstat (limited to 'bfd/elf32-rl78.c')
-rw-r--r-- | bfd/elf32-rl78.c | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c index acd82b9..70b49aa 100644 --- a/bfd/elf32-rl78.c +++ b/bfd/elf32-rl78.c @@ -1018,6 +1018,18 @@ bfd_elf32_rl78_set_target_flags (bfd_boolean user_no_warn_mismatch) no_warn_mismatch = user_no_warn_mismatch; } +static const char * +rl78_cpu_name (flagword flags) +{ + switch (flags & E_FLAG_RL78_CPU_MASK) + { + default: return ""; + case E_FLAG_RL78_G10: return "G10"; + case E_FLAG_RL78_G13: return "G13"; + case E_FLAG_RL78_G14: return "G14"; + } +} + /* Merge backend specific data from an object file to the output object file when linking. */ @@ -1041,17 +1053,44 @@ rl78_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd) { flagword changed_flags = old_flags ^ new_flags; - if (changed_flags & E_FLAG_RL78_G10) + if (changed_flags & E_FLAG_RL78_CPU_MASK) { - (*_bfd_error_handler) - (_("RL78/G10 ABI conflict: cannot link G10 and non-G10 objects together")); + flagword out_cpu = old_flags & E_FLAG_RL78_CPU_MASK; + flagword in_cpu = new_flags & E_FLAG_RL78_CPU_MASK; - if (old_flags & E_FLAG_RL78_G10) - (*_bfd_error_handler) (_("- %s is G10, %s is not"), - bfd_get_filename (obfd), bfd_get_filename (ibfd)); + if (in_cpu == E_FLAG_RL78_ANY_CPU || in_cpu == out_cpu) + /* It does not matter what new_cpu may have. */; + else if (out_cpu == E_FLAG_RL78_ANY_CPU) + { + if (in_cpu == E_FLAG_RL78_G10) + { + /* G10 files can only be linked with other G10 files. + If the output is set to "any" this means that it is + a G14 file that does not use hardware multiply/divide, + but that is still incompatible with the G10 ABI. */ + error = TRUE; + + (*_bfd_error_handler) + (_("RL78 ABI conflict: G10 file %s cannot be linked with %s file %s"), + bfd_get_filename (ibfd), + rl78_cpu_name (out_cpu), bfd_get_filename (obfd)); + } + else + { + old_flags &= ~ E_FLAG_RL78_CPU_MASK; + old_flags |= in_cpu; + elf_elfheader (obfd)->e_flags = old_flags; + } + } else - (*_bfd_error_handler) (_("- %s is G10, %s is not"), - bfd_get_filename (ibfd), bfd_get_filename (obfd)); + { + error = TRUE; + + (*_bfd_error_handler) + (_("RL78 ABI conflict: cannot link %s file %s with %s file %s"), + rl78_cpu_name (in_cpu), bfd_get_filename (ibfd), + rl78_cpu_name (out_cpu), bfd_get_filename (obfd)); + } } if (changed_flags & E_FLAG_RL78_64BIT_DOUBLES) @@ -1065,6 +1104,7 @@ rl78_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd) else (*_bfd_error_handler) (_("- %s is 64-bit, %s is not"), bfd_get_filename (ibfd), bfd_get_filename (obfd)); + error = TRUE; } } @@ -1085,8 +1125,8 @@ rl78_elf_print_private_bfd_data (bfd * abfd, void * ptr) flags = elf_elfheader (abfd)->e_flags; fprintf (file, _("private flags = 0x%lx:"), (long) flags); - if (flags & E_FLAG_RL78_G10) - fprintf (file, _(" [G10]")); + if (flags & E_FLAG_RL78_CPU_MASK) + fprintf (file, " [%s]", rl78_cpu_name (flags)); if (flags & E_FLAG_RL78_64BIT_DOUBLES) fprintf (file, _(" [64-bit doubles]")); @@ -1098,12 +1138,9 @@ rl78_elf_print_private_bfd_data (bfd * abfd, void * ptr) /* Return the MACH for an e_flags value. */ static int -elf32_rl78_machine (bfd * abfd) +elf32_rl78_machine (bfd * abfd ATTRIBUTE_UNUSED) { - if ((elf_elfheader (abfd)->e_flags & EF_RL78_CPU_MASK) == EF_RL78_CPU_RL78) - return bfd_mach_rl78; - - return 0; + return bfd_mach_rl78; } static bfd_boolean @@ -1240,7 +1277,7 @@ rl78_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED, this check if we're relaxing. Unfortunately, check_relocs is called before relaxation. */ - if (info->relax_trip > 0) + if (info->relax_trip > 0) return TRUE; if ((dynobj = elf_hash_table (info)->dynobj) != NULL @@ -1473,7 +1510,7 @@ rl78_elf_relax_plt_section (bfd *dynobj, static bfd_boolean elf32_rl78_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count, - Elf_Internal_Rela *alignment_rel, int force_snip) + Elf_Internal_Rela *alignment_rel, int force_snip) { Elf_Internal_Shdr * symtab_hdr; unsigned int sec_shndx; @@ -2129,8 +2166,8 @@ rl78_elf_relax_section nbytes /= alignment; nbytes *= alignment; - elf32_rl78_relax_delete_bytes (abfd, sec, erel->r_offset-nbytes, nbytes, next_alignment, - erel->r_offset == sec->size); + elf32_rl78_relax_delete_bytes (abfd, sec, erel->r_offset - nbytes, nbytes, + next_alignment, erel->r_offset == sec->size); *again = TRUE; continue; @@ -2163,16 +2200,17 @@ rl78_elf_relax_section pc = sec->output_section->vma + sec->output_offset + srel->r_offset; -#define GET_RELOC \ - BFD_ASSERT (nrelocs > 0); \ - symval = OFFSET_FOR_RELOC (srel, &srel, &scale); \ - pcrel = symval - pc + srel->r_addend; \ +#define GET_RELOC \ + BFD_ASSERT (nrelocs > 0); \ + symval = OFFSET_FOR_RELOC (srel, &srel, &scale); \ + pcrel = symval - pc + srel->r_addend; \ nrelocs --; #define SNIPNR(offset, nbytes) \ elf32_rl78_relax_delete_bytes (abfd, sec, (insn - contents) + offset, nbytes, next_alignment, 0); -#define SNIP(offset, nbytes, newtype) \ - SNIPNR (offset, nbytes); \ + +#define SNIP(offset, nbytes, newtype) \ + SNIPNR (offset, nbytes); \ srel->r_info = ELF32_R_INFO (ELF32_R_SYM (srel->r_info), newtype) /* The order of these bit tests must match the order that the @@ -2335,7 +2373,6 @@ rl78_elf_relax_section } break; } - } if ((irel->r_addend & RL78_RELAXA_MASK) == RL78_RELAXA_ADDR16 @@ -2402,13 +2439,10 @@ rl78_elf_relax_section insn[poff] = relax_addr16[idx].insn_for_saddr; SNIP (poff+2, 1, R_RL78_RH_SADDR); } - } } } - /*----------------------------------------------------------------------*/ - } return TRUE; |