diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e158591097..f901f5a325 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2015-03-19 Nick Clifton + + * 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. + 2015-03-19 Nick Clifton PR 18078 diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c index acd82b9b6c..70b49aa00a 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; diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 5c0efb115f..a3249ad47d 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,7 @@ +2015-03-19 Nick Clifton + + * readelf.c (get_machine_flags): Decode RL78's G13 and G14 flags. + 2015-03-18 Jon Turney Nick Clifton diff --git a/binutils/readelf.c b/binutils/readelf.c index 20cfc473d9..adf2a91999 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -3256,8 +3256,13 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) break; case EM_RL78: - if (e_flags & E_FLAG_RL78_G10) - strcat (buf, ", G10"); + switch (e_flags & E_FLAG_RL78_CPU_MASK) + { + case E_FLAG_RL78_ANY_CPU: break; + case E_FLAG_RL78_G10: strcat (buf, ", G10"); break; + case E_FLAG_RL78_G13: strcat (buf, ", G13"); break; + case E_FLAG_RL78_G14: strcat (buf, ", G14"); break; + } if (e_flags & E_FLAG_RL78_64BIT_DOUBLES) strcat (buf, ", 64-bit doubles"); break; diff --git a/gas/ChangeLog b/gas/ChangeLog index 7bf7794f5d..fbf84896b4 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2015-03-19 Nick Clifton + + * 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. + 2015-03-18 Jon Turney Nick Clifton diff --git a/gas/config/tc-rl78.c b/gas/config/tc-rl78.c index abc05a01b1..337b819b57 100644 --- a/gas/config/tc-rl78.c +++ b/gas/config/tc-rl78.c @@ -281,6 +281,8 @@ enum options { OPTION_RELAX = OPTION_MD_BASE, OPTION_G10, + OPTION_G13, + OPTION_G14, OPTION_32BIT_DOUBLES, OPTION_64BIT_DOUBLES, }; @@ -293,6 +295,9 @@ struct option md_longopts[] = { {"relax", no_argument, NULL, OPTION_RELAX}, {"mg10", no_argument, NULL, OPTION_G10}, + {"mg13", no_argument, NULL, OPTION_G13}, + {"mg14", no_argument, NULL, OPTION_G14}, + {"mrl78", no_argument, NULL, OPTION_G14}, {"m32bit-doubles", no_argument, NULL, OPTION_32BIT_DOUBLES}, {"m64bit-doubles", no_argument, NULL, OPTION_64BIT_DOUBLES}, {NULL, no_argument, NULL, 0} @@ -309,9 +314,20 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED) return 1; case OPTION_G10: + elf_flags &= ~ E_FLAG_RL78_CPU_MASK; elf_flags |= E_FLAG_RL78_G10; return 1; + case OPTION_G13: + elf_flags &= ~ E_FLAG_RL78_CPU_MASK; + elf_flags |= E_FLAG_RL78_G13; + return 1; + + case OPTION_G14: + elf_flags &= ~ E_FLAG_RL78_CPU_MASK; + elf_flags |= E_FLAG_RL78_G14; + return 1; + case OPTION_32BIT_DOUBLES: elf_flags &= ~ E_FLAG_RL78_64BIT_DOUBLES; return 1; @@ -328,6 +344,9 @@ md_show_usage (FILE * stream ATTRIBUTE_UNUSED) { fprintf (stream, _(" RL78 specific command line options:\n")); fprintf (stream, _(" --mg10 Enable support for G10 variant\n")); + fprintf (stream, _(" --mg13 Selects the G13 core.\n")); + fprintf (stream, _(" --mg14 Selects the G14 core [default]\n")); + fprintf (stream, _(" --mrl78 Alias for --mg14\n")); fprintf (stream, _(" --m32bit-doubles [default]\n")); fprintf (stream, _(" --m64bit-doubles\n")); } diff --git a/gas/doc/c-rl78.texi b/gas/doc/c-rl78.texi index fee16f105b..5cb568f3ec 100644 --- a/gas/doc/c-rl78.texi +++ b/gas/doc/c-rl78.texi @@ -32,6 +32,15 @@ Enable support for link-time relaxation. Mark the generated binary as targeting the G10 variant of the RL78 architecture. +@item mg13 +Mark the generated binary as targeting the G13 variant of the RL78 +architecture. + +@item mg14 +@itemx mrl78 +Mark the generated binary as targeting the G14 variant of the RL78 +architecture. This is the default. + @item m32bit-doubles Mark the generated binary as one that uses 32-bits to hold the @code{double} floating point type. This is the default. diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 056aaf5236..41de600e96 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,9 @@ +2015-03-19 Nick Clifton + + * 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. + 2015-02-19 Marcus Shawcroft * aarch64.h (R_AARCH64_P32_TLSGD_ADR_PREL21): Add. diff --git a/include/elf/rl78.h b/include/elf/rl78.h index e7df0d72f9..b5236d9338 100644 --- a/include/elf/rl78.h +++ b/include/elf/rl78.h @@ -106,7 +106,11 @@ END_RELOC_NUMBERS (R_RL78_max) /* Values for the e_flags field in the ELF header. */ #define E_FLAG_RL78_64BIT_DOUBLES (1 << 0) #define E_FLAG_RL78_DSP (1 << 1) /* Defined in the RL78 CPU Object file specification, but not explained. */ -#define E_FLAG_RL78_G10 (1 << 2) /* CPU is missing register banks 1-3, so uses different ABI. */ +#define E_FLAG_RL78_CPU_MASK 0x0c +#define E_FLAG_RL78_ANY_CPU 0x00 /* CPU not specified. Assume no CPU specific code usage. */ +#define E_FLAG_RL78_G10 0x04 /* CPU is missing register banks 1-3, so uses different ABI. */ +#define E_FLAG_RL78_G13 0x08 /* CPU uses a peripheral for multiply/divide. */ +#define E_FLAG_RL78_G14 0x0c /* CPU has multiply/divide instructions. */ /* These define the addend field of R_RL78_RH_RELAX relocations. */ #define RL78_RELAXA_MASK 0x000000f0 /* Mask for relax types */