This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Add support for G13 and G14 flag bits in RL78 ELF binaries.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1740ba0cec44bdfe9cba586892a5953a4c602228

commit 1740ba0cec44bdfe9cba586892a5953a4c602228
Author: Nick Clifton <nickc@redhat.com>
Date:   Thu Mar 19 15:37:43 2015 +0000

    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.

Diff:
---
 bfd/ChangeLog         |  9 +++++
 bfd/elf32-rl78.c      | 92 +++++++++++++++++++++++++++++++++++----------------
 binutils/ChangeLog    |  4 +++
 binutils/readelf.c    |  9 +++--
 gas/ChangeLog         |  8 +++++
 gas/config/tc-rl78.c  | 19 +++++++++++
 gas/doc/c-rl78.texi   |  9 +++++
 include/elf/ChangeLog |  6 ++++
 include/elf/rl78.h    |  6 +++-
 9 files changed, 130 insertions(+), 32 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e158591..f901f5a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,14 @@
 2015-03-19  Nick Clifton  <nickc@redhat.com>
 
+	* 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  <nickc@redhat.com>
+
 	PR 18078
 	* compress.c (bfd_compress_section_contents): Do not define this
 	function if it is not used.
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;
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 5c0efb1..a3249ad 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,7 @@
+2015-03-19  Nick Clifton  <nickc@redhat.com>
+
+	* readelf.c (get_machine_flags): Decode RL78's G13 and G14 flags.
+
 2015-03-18  Jon Turney  <jon.turney@dronecode.org.uk>
 	    Nick Clifton  <nickc@redhat.com>
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 20cfc47..adf2a91 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 7bf7794..fbf8489 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,11 @@
+2015-03-19  Nick Clifton  <nickc@redhat.com>
+
+	* 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  <jon.turney@dronecode.org.uk>
 	    Nick Clifton  <nickc@redhat.com>
 
diff --git a/gas/config/tc-rl78.c b/gas/config/tc-rl78.c
index abc05a0..337b819 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 fee16f1..5cb568f 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 056aaf5..41de600 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-19  Nick Clifton  <nickc@redhat.com>
+
+	* 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  <marcus.shawcroft@arm.com>
 
 	* aarch64.h (R_AARCH64_P32_TLSGD_ADR_PREL21): Add.
diff --git a/include/elf/rl78.h b/include/elf/rl78.h
index e7df0d7..b5236d9 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 */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]