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] Adds support to the RL78 port for linker relaxation affecting .debug sections.


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

commit 6ff71e768112317de1236a429e7c88c9d3e32116
Author: Nick Clifton <nickc@redhat.com>
Date:   Tue Apr 14 16:23:33 2015 +0100

    Adds support to the RL78 port for linker relaxation affecting .debug sections.
    
    gas	* config/tc-rl78.h (TC_LINKRELAX_FIXUP): Define.
    	(TC_FORCE_RELOCATION_SUB_SAME): Define.
    	(DWARF2_USE_FIXED_ADVANCE_PC): Define.
    
    	* gas/lns/lns.exp: Add RL78 to list of targets using
    	DW_LNS_fixed_advance_pc.
    
    bfd	* elf32-rl78.c (RL78_OP_REL): New macro.
    	(rl78_elf_howto_table): Use it for complex relocs.
    	(get_symbol_value): Handle the cases when the info or status
    	arguments are NULL.
    	(get_romstart): Cache the status returned by get_symbol_value.
    	(get_ramstart): Likewise.
    	(RL78_STACK_PUSH): Generate an error message if the stack
    	overflows.
    	(RL78_STACK_POP): Likewise for underflows.
    	(rl78_compute_complex_reloc): New function.  Contains the basic
    	processing code for all RL78 complex relocs.
    	(rl78_special_reloc): New function.  Provides special reloc
    	handling for complex relocs.
    	(rl78_elf_relocate_section): Use rl78_compute_complex_reloc.
    	(rl78_offset_for_reloc): Likewise.
    
    binutils* readelf.c (target_specific_reloc_handling): Add code to handle
    	RL78 complex relocs.

Diff:
---
 bfd/ChangeLog                 |  18 +
 bfd/elf32-rl78.c              | 835 ++++++++++++++++++++++--------------------
 binutils/ChangeLog            |   5 +
 binutils/readelf.c            |  36 ++
 gas/ChangeLog                 |   6 +
 gas/config/tc-rl78.c          |  29 +-
 gas/config/tc-rl78.h          |  14 +
 gas/testsuite/ChangeLog       |   5 +
 gas/testsuite/gas/lns/lns.exp |   7 +-
 9 files changed, 555 insertions(+), 400 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 056833e..49202af 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,21 @@
+2015-04-14  Nick Clifton  <nickc@redhat.com>
+
+	* elf32-rl78.c (RL78_OP_REL): New macro.
+	(rl78_elf_howto_table): Use it for complex relocs.
+	(get_symbol_value): Handle the cases when the info or status
+	arguments are NULL.
+	(get_romstart): Cache the status returned by get_symbol_value.
+	(get_ramstart): Likewise.
+	(RL78_STACK_PUSH): Generate an error message if the stack
+	overflows.
+	(RL78_STACK_POP): Likewise for underflows.
+	(rl78_compute_complex_reloc): New function.  Contains the basic
+	processing code for all RL78 complex relocs.
+	(rl78_special_reloc): New function.  Provides special reloc
+	handling for complex relocs.
+	(rl78_elf_relocate_section): Use rl78_compute_complex_reloc.
+	(rl78_offset_for_reloc): Likewise.
+
 2015-04-14  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/pr17709
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c
index 70b49aa..2822547 100644
--- a/bfd/elf32-rl78.c
+++ b/bfd/elf32-rl78.c
@@ -31,6 +31,14 @@
   HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
 	 bfd_elf_generic_reloc, "R_RL78_" #n, FALSE, 0, ~0, FALSE)
 
+static bfd_reloc_status_type rl78_special_reloc (bfd *, arelent *, asymbol *, void *,
+						 asection *, bfd *, char **);
+
+/* FIXME: We could omit the SHIFT parameter, it is always zero.  */
+#define RL78_OP_REL(n,sz,bit,shift,complain,pcrel)			\
+  HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
+	 rl78_special_reloc, "R_RL78_" #n, FALSE, 0, ~0, FALSE)
+
 /* Note that the relocations around 0x7f are internal to this file;
    feel free to move them as needed to avoid conflicts with published
    relocation numbers.  */
@@ -106,23 +114,23 @@ static reloc_howto_type rl78_elf_howto_table [] =
   EMPTY_HOWTO (0x3f),
   EMPTY_HOWTO (0x40),
 
-  RL78REL (ABS32,        2, 32, 0, dont,     FALSE),
-  RL78REL (ABS24S,       2, 24, 0, signed,   FALSE),
-  RL78REL (ABS16,        1, 16, 0, dont,     FALSE),
-  RL78REL (ABS16U,       1, 16, 0, unsigned, FALSE),
-  RL78REL (ABS16S,       1, 16, 0, signed,   FALSE),
-  RL78REL (ABS8,         0,  8, 0, dont,     FALSE),
-  RL78REL (ABS8U,        0,  8, 0, unsigned, FALSE),
-  RL78REL (ABS8S,        0,  8, 0, signed,   FALSE),
-  RL78REL (ABS24S_PCREL, 2, 24, 0, signed,   TRUE),
-  RL78REL (ABS16S_PCREL, 1, 16, 0, signed,   TRUE),
-  RL78REL (ABS8S_PCREL,  0,  8, 0, signed,   TRUE),
-  RL78REL (ABS16UL,      1, 16, 0, unsigned, FALSE),
-  RL78REL (ABS16UW,      1, 16, 0, unsigned, FALSE),
-  RL78REL (ABS8UL,       0,  8, 0, unsigned, FALSE),
-  RL78REL (ABS8UW,       0,  8, 0, unsigned, FALSE),
-  RL78REL (ABS32_REV,    2, 32, 0, dont,     FALSE),
-  RL78REL (ABS16_REV,    1, 16, 0, dont,     FALSE),
+  RL78_OP_REL (ABS32,        2, 32, 0, dont,     FALSE),
+  RL78_OP_REL (ABS24S,       2, 24, 0, signed,   FALSE),
+  RL78_OP_REL (ABS16,        1, 16, 0, dont,     FALSE),
+  RL78_OP_REL (ABS16U,       1, 16, 0, unsigned, FALSE),
+  RL78_OP_REL (ABS16S,       1, 16, 0, signed,   FALSE),
+  RL78_OP_REL (ABS8,         0,  8, 0, dont,     FALSE),
+  RL78_OP_REL (ABS8U,        0,  8, 0, unsigned, FALSE),
+  RL78_OP_REL (ABS8S,        0,  8, 0, signed,   FALSE),
+  RL78_OP_REL (ABS24S_PCREL, 2, 24, 0, signed,   TRUE),
+  RL78_OP_REL (ABS16S_PCREL, 1, 16, 0, signed,   TRUE),
+  RL78_OP_REL (ABS8S_PCREL,  0,  8, 0, signed,   TRUE),
+  RL78_OP_REL (ABS16UL,      1, 16, 0, unsigned, FALSE),
+  RL78_OP_REL (ABS16UW,      1, 16, 0, unsigned, FALSE),
+  RL78_OP_REL (ABS8UL,       0,  8, 0, unsigned, FALSE),
+  RL78_OP_REL (ABS8UW,       0,  8, 0, unsigned, FALSE),
+  RL78_OP_REL (ABS32_REV,    2, 32, 0, dont,     FALSE),
+  RL78_OP_REL (ABS16_REV,    1, 16, 0, dont,     FALSE),
 
 #define STACK_REL_P(x) ((x) <= R_RL78_ABS16_REV && (x) >= R_RL78_ABS32)
 
@@ -174,29 +182,29 @@ static reloc_howto_type rl78_elf_howto_table [] =
   EMPTY_HOWTO (0x7e),
   EMPTY_HOWTO (0x7f),
 
-  RL78REL (SYM,       2, 32, 0, dont, FALSE),
-  RL78REL (OPneg,     2, 32, 0, dont, FALSE),
-  RL78REL (OPadd,     2, 32, 0, dont, FALSE),
-  RL78REL (OPsub,     2, 32, 0, dont, FALSE),
-  RL78REL (OPmul,     2, 32, 0, dont, FALSE),
-  RL78REL (OPdiv,     2, 32, 0, dont, FALSE),
-  RL78REL (OPshla,    2, 32, 0, dont, FALSE),
-  RL78REL (OPshra,    2, 32, 0, dont, FALSE),
-  RL78REL (OPsctsize, 2, 32, 0, dont, FALSE),
+  RL78_OP_REL (SYM,       2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPneg,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPadd,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPsub,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPmul,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPdiv,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPshla,    2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPshra,    2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPsctsize, 2, 32, 0, dont, FALSE),
   EMPTY_HOWTO (0x89),
   EMPTY_HOWTO (0x8a),
   EMPTY_HOWTO (0x8b),
   EMPTY_HOWTO (0x8c),
-  RL78REL (OPscttop,  2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPscttop,  2, 32, 0, dont, FALSE),
   EMPTY_HOWTO (0x8e),
   EMPTY_HOWTO (0x8f),
-  RL78REL (OPand,     2, 32, 0, dont, FALSE),
-  RL78REL (OPor,      2, 32, 0, dont, FALSE),
-  RL78REL (OPxor,     2, 32, 0, dont, FALSE),
-  RL78REL (OPnot,     2, 32, 0, dont, FALSE),
-  RL78REL (OPmod,     2, 32, 0, dont, FALSE),
-  RL78REL (OPromtop,  2, 32, 0, dont, FALSE),
-  RL78REL (OPramtop,  2, 32, 0, dont, FALSE)
+  RL78_OP_REL (OPand,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPor,      2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPxor,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPnot,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPmod,     2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPromtop,  2, 32, 0, dont, FALSE),
+  RL78_OP_REL (OPramtop,  2, 32, 0, dont, FALSE)
 };
 
 /* Map BFD reloc types to RL78 ELF reloc types.  */
@@ -292,22 +300,29 @@ get_symbol_value (const char *            name,
 		  asection *              input_section,
 		  int			  offset)
 {
-  bfd_vma value = 0;
   struct bfd_link_hash_entry * h;
 
+  if (info == NULL)
+    return 0;
+
   h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
 
   if (h == NULL
       || (h->type != bfd_link_hash_defined
 	  && h->type != bfd_link_hash_defweak))
-    * status = info->callbacks->undefined_symbol
-      (info, name, input_bfd, input_section, offset, TRUE);
-  else
-    value = (h->u.def.value
-	     + h->u.def.section->output_section->vma
-	     + h->u.def.section->output_offset);
+    {
+      bfd_reloc_status_type res;
+
+      res = info->callbacks->undefined_symbol
+	(info, name, input_bfd, input_section, offset, TRUE);
+      if (status)
+	* status = res;
+      return 0;
+    }
 
-  return value;
+  return (h->u.def.value
+	  + h->u.def.section->output_section->vma
+	  + h->u.def.section->output_offset);
 }
 
 static bfd_vma
@@ -319,12 +334,15 @@ get_romstart (bfd_reloc_status_type * status,
 {
   static bfd_boolean cached = FALSE;
   static bfd_vma     cached_value = 0;
+  static bfd_reloc_status_type cached_status;
 
   if (!cached)
     {
-      cached_value = get_symbol_value ("_start", status, info, abfd, sec, offset);
+      cached_value = get_symbol_value ("_start", & cached_status, info, abfd, sec, offset);
       cached = TRUE;
     }
+  if (status)
+    * status = cached_status;
   return cached_value;
 }
 
@@ -337,12 +355,15 @@ get_ramstart (bfd_reloc_status_type * status,
 {
   static bfd_boolean cached = FALSE;
   static bfd_vma     cached_value = 0;
+  static bfd_reloc_status_type cached_status;
 
   if (!cached)
     {
-      cached_value = get_symbol_value ("__datastart", status, info, abfd, sec, offset);
+      cached_value = get_symbol_value ("__datastart", & cached_status, info, abfd, sec, offset);
       cached = TRUE;
     }
+  if (status)
+    * status = cached_status;
   return cached_value;
 }
 
@@ -356,7 +377,7 @@ static unsigned int rl78_stack_top;
       if (rl78_stack_top < NUM_STACK_ENTRIES)	\
         rl78_stack [rl78_stack_top ++] = (val);	\
       else					\
-        r = bfd_reloc_dangerous;		\
+	_bfd_error_handler (_("Internal Error: RL78 reloc stack overflow")); \
     }						\
   while (0)
 
@@ -364,12 +385,269 @@ static unsigned int rl78_stack_top;
   do						\
     {						\
       if (rl78_stack_top > 0)			\
-        (dest) = rl78_stack [-- rl78_stack_top];	\
+        (dest) = rl78_stack [-- rl78_stack_top];\
       else					\
-        (dest) = 0, r = bfd_reloc_dangerous;	\
+	{					\
+          _bfd_error_handler (_("Internal Error: RL78 reloc stack underflow")); \
+          (dest) = 0;				\
+        }					\
     }						\
   while (0)
 
+/* Special handling for RL78 complex relocs.  Returns the
+   value of the reloc, or 0 for relocs which do not generate
+   a result.  SYMVAL is the value of the symbol for relocs
+   which use a symbolic argument.  */
+
+static bfd_vma
+rl78_compute_complex_reloc (unsigned long  r_type,
+			    bfd_vma        symval,
+			    asection *     input_section)
+{
+  int32_t tmp1, tmp2;
+  bfd_vma relocation;
+
+  switch (r_type)
+    {
+    default:
+      return 0;
+
+    case R_RL78_ABS24S_PCREL:
+    case R_RL78_ABS16S_PCREL:
+    case R_RL78_ABS8S_PCREL:
+      RL78_STACK_POP (relocation);
+      relocation -= input_section->output_section->vma + input_section->output_offset;
+      return relocation;
+
+    case R_RL78_ABS32:
+    case R_RL78_ABS32_REV:
+    case R_RL78_ABS16:
+    case R_RL78_ABS16_REV:
+    case R_RL78_ABS16S:
+    case R_RL78_ABS16U:
+    case R_RL78_ABS8:
+    case R_RL78_ABS8U:
+    case R_RL78_ABS8S:
+      RL78_STACK_POP (relocation);
+      return relocation;
+
+    case R_RL78_ABS16UL:
+    case R_RL78_ABS8UL:
+      RL78_STACK_POP (relocation);
+      return relocation >> 2;
+
+    case R_RL78_ABS16UW:
+    case R_RL78_ABS8UW:
+      RL78_STACK_POP (relocation);
+      return relocation >> 1;
+
+      /* The rest of the relocs compute values and then push them onto the stack.  */
+    case R_RL78_OPramtop:
+    case R_RL78_OPromtop:
+    case R_RL78_SYM:
+      RL78_STACK_PUSH (symval);
+      return 0;
+      
+    case R_RL78_OPneg:
+      RL78_STACK_POP (tmp1);
+      tmp1 = - tmp1;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPadd:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 += tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPsub:
+      /* For the expression "A - B", the assembler pushes A,
+	 then B, then OPSUB.  So the first op we pop is B, not A.  */
+      RL78_STACK_POP (tmp2);	/* B */
+      RL78_STACK_POP (tmp1);	/* A */
+      tmp1 -= tmp2;		/* A - B */
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPmul:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 *= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPdiv:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 /= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPshla:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 <<= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPshra:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 >>= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPsctsize:
+      RL78_STACK_PUSH (input_section->size);
+      return 0;
+
+    case R_RL78_OPscttop:
+      RL78_STACK_PUSH (input_section->output_section->vma);
+      return 0;
+
+    case R_RL78_OPand:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 &= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPor:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 |= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPxor:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 ^= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPnot:
+      RL78_STACK_POP (tmp1);
+      tmp1 = ~ tmp1;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+
+    case R_RL78_OPmod:
+      RL78_STACK_POP (tmp2);
+      RL78_STACK_POP (tmp1);
+      tmp1 %= tmp2;
+      RL78_STACK_PUSH (tmp1);
+      return 0;
+    }
+}
+
+#undef RL78_STACK_PUSH
+#undef RL78_STACK_POP
+
+#define OP(i)      (contents[reloc->address + (i)])
+
+static bfd_reloc_status_type
+rl78_special_reloc (bfd *      input_bfd,
+		    arelent *  reloc,
+		    asymbol *  symbol,
+		    void *     data,
+		    asection * input_section,
+		    bfd *      output_bfd ATTRIBUTE_UNUSED,
+		    char **    error_message ATTRIBUTE_UNUSED)
+{
+  bfd_reloc_status_type  r = bfd_reloc_ok;
+  bfd_vma                relocation = 0;
+  unsigned long          r_type = reloc->howto->type;
+  bfd_byte *             contents = data;
+
+  /* If necessary, compute the symbolic value of the relocation.  */
+  switch (r_type)
+    {
+    case R_RL78_SYM:
+      relocation = (symbol->value
+		    + symbol->section->output_section->vma
+		    + symbol->section->output_offset
+		    + reloc->addend);
+	break;
+
+    case R_RL78_OPromtop:
+      relocation = get_romstart (&r, NULL, input_bfd, input_section,
+				 reloc->address);
+      break;
+
+    case R_RL78_OPramtop:
+      relocation = get_ramstart (&r, NULL, input_bfd, input_section,
+				 reloc->address);
+      break;
+    }
+
+  /* Get the value of the relocation.  */
+  relocation = rl78_compute_complex_reloc (r_type, relocation, input_section);
+
+  /* If the relocation alters the contents of the section then apply it now.
+     Note - since this function is called from
+     bfd_generic_get_relocated_section_contents via bfd_perform_relocation,
+     and not from the linker, we do not perform any range checking.  The
+     clients who are calling us are only interested in some relocated section
+     contents, and not any linkage problems that might occur later.  */
+  switch (r_type)
+    {
+    case R_RL78_ABS32:
+      OP (0) = relocation;
+      OP (1) = relocation >> 8;
+      OP (2) = relocation >> 16;
+      OP (3) = relocation >> 24;
+      break;
+
+    case R_RL78_ABS32_REV:
+      OP (3) = relocation;
+      OP (2) = relocation >> 8;
+      OP (1) = relocation >> 16;
+      OP (0) = relocation >> 24;
+      break;
+
+    case R_RL78_ABS24S_PCREL:
+    case R_RL78_ABS24S:
+      OP (0) = relocation;
+      OP (1) = relocation >> 8;
+      OP (2) = relocation >> 16;
+      break;
+
+    case R_RL78_ABS16_REV:
+      OP (1) = relocation;
+      OP (0) = relocation >> 8;
+      break;
+
+    case R_RL78_ABS16S_PCREL:
+    case R_RL78_ABS16:
+    case R_RL78_ABS16S:
+    case R_RL78_ABS16U:
+    case R_RL78_ABS16UL:
+    case R_RL78_ABS16UW:
+      OP (0) = relocation;
+      OP (1) = relocation >> 8;
+      break;
+
+    case R_RL78_ABS8S_PCREL:
+    case R_RL78_ABS8:
+    case R_RL78_ABS8U:
+    case R_RL78_ABS8UL:
+    case R_RL78_ABS8UW:
+    case R_RL78_ABS8S:
+      OP (0) = relocation;
+      break;
+
+    default:
+      break;
+    }
+
+  return r;
+}
+
+#undef  OP
+#define OP(i)      (contents[rel->r_offset + (i)])
+
 /* Relocate an RL78 ELF section.
    There is some attempt to make this function usable for many architectures,
    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
@@ -475,7 +753,7 @@ rl78_elf_relocate_section
 	  name = h->root.root.string;
 	}
 
-      if (sec != NULL && discarded_section (sec))
+      if (sec != NULL && discarded_section (sec)
 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
 					 rel, 1, relend, howto, 0, contents);
 
@@ -559,8 +837,6 @@ rl78_elf_relocate_section
       r = bfd_reloc_ok;
 
 #define RANGE(a,b) if (a > (long) relocation || (long) relocation > b) r = bfd_reloc_overflow
-#define ALIGN(m)   if (relocation & m) r = bfd_reloc_other;
-#define OP(i)      (contents[rel->r_offset + (i)])
 
       /* Opcode relocs are always big endian.  Data relocs are bi-endian.  */
       switch (r_type)
@@ -663,279 +939,141 @@ rl78_elf_relocate_section
 	  break;
 
 	  /* Complex reloc handling:  */
-
 	case R_RL78_ABS32:
-	  RL78_STACK_POP (relocation);
-	  OP (0) = relocation;
-	  OP (1) = relocation >> 8;
-	  OP (2) = relocation >> 16;
-	  OP (3) = relocation >> 24;
-	  break;
-
 	case R_RL78_ABS32_REV:
-	  RL78_STACK_POP (relocation);
-	  OP (3) = relocation;
-	  OP (2) = relocation >> 8;
-	  OP (1) = relocation >> 16;
-	  OP (0) = relocation >> 24;
-	  break;
-
 	case R_RL78_ABS24S_PCREL:
 	case R_RL78_ABS24S:
-	  RL78_STACK_POP (relocation);
-	  RANGE (-0x800000, 0x7fffff);
-	  OP (0) = relocation;
-	  OP (1) = relocation >> 8;
-	  OP (2) = relocation >> 16;
-	  break;
-
 	case R_RL78_ABS16:
-	  RL78_STACK_POP (relocation);
-	  RANGE (-32768, 65535);
-	  OP (0) = relocation;
-	  OP (1) = relocation >> 8;
-	  break;
-
 	case R_RL78_ABS16_REV:
-	  RL78_STACK_POP (relocation);
-	  RANGE (-32768, 65535);
-	  OP (1) = relocation;
-	  OP (0) = relocation >> 8;
-	  break;
-
 	case R_RL78_ABS16S_PCREL:
 	case R_RL78_ABS16S:
-	  RL78_STACK_POP (relocation);
-	  RANGE (-32768, 32767);
-	  OP (0) = relocation;
-	  OP (1) = relocation >> 8;
-	  break;
-
 	case R_RL78_ABS16U:
-	  RL78_STACK_POP (relocation);
-	  RANGE (0, 65536);
-	  OP (0) = relocation;
-	  OP (1) = relocation >> 8;
-	  break;
-
 	case R_RL78_ABS16UL:
-	  RL78_STACK_POP (relocation);
-	  relocation >>= 2;
-	  RANGE (0, 65536);
-	  OP (0) = relocation;
-	  OP (1) = relocation >> 8;
-	  break;
-
 	case R_RL78_ABS16UW:
-	  RL78_STACK_POP (relocation);
-	  relocation >>= 1;
-	  RANGE (0, 65536);
-	  OP (0) = relocation;
-	  OP (1) = relocation >> 8;
-	  break;
-
 	case R_RL78_ABS8:
-	  RL78_STACK_POP (relocation);
-	  RANGE (-128, 255);
-	  OP (0) = relocation;
-	  break;
-
 	case R_RL78_ABS8U:
-	  RL78_STACK_POP (relocation);
-	  RANGE (0, 255);
-	  OP (0) = relocation;
-	  break;
-
 	case R_RL78_ABS8UL:
-	  RL78_STACK_POP (relocation);
-	  relocation >>= 2;
-	  RANGE (0, 255);
-	  OP (0) = relocation;
-	  break;
-
 	case R_RL78_ABS8UW:
-	  RL78_STACK_POP (relocation);
-	  relocation >>= 1;
-	  RANGE (0, 255);
-	  OP (0) = relocation;
-	  break;
-
 	case R_RL78_ABS8S_PCREL:
 	case R_RL78_ABS8S:
-	  RL78_STACK_POP (relocation);
-	  RANGE (-128, 127);
-	  OP (0) = relocation;
-	  break;
-
-	case R_RL78_SYM:
-	  if (r_symndx < symtab_hdr->sh_info)
-	    RL78_STACK_PUSH (sec->output_section->vma
-			   + sec->output_offset
-			   + sym->st_value
-			   + rel->r_addend);
-	  else
-	    {
-	      if (h != NULL
-		  && (h->root.type == bfd_link_hash_defined
-		      || h->root.type == bfd_link_hash_defweak))
-		RL78_STACK_PUSH (h->root.u.def.value
-			       + sec->output_section->vma
-			       + sec->output_offset
-			       + rel->r_addend);
-	      else if (h->root.type == bfd_link_hash_undefweak)
-		RL78_STACK_PUSH (0);
-	      else
-		_bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol"));
-	    }
-	  break;
-
 	case R_RL78_OPneg:
-	  {
-	    int32_t tmp;
-
-	    RL78_STACK_POP (tmp);
-	    tmp = - tmp;
-	    RL78_STACK_PUSH (tmp);
-	  }
-	  break;
-
 	case R_RL78_OPadd:
-	  {
-	    int32_t tmp1, tmp2;
-
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 += tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
-
 	case R_RL78_OPsub:
-	  {
-	    int32_t tmp1, tmp2;
-
-	    /* For the expression "A - B", the assembler pushes A,
-	       then B, then OPSUB.  So the first op we pop is B, not
-	       A.  */
-	    RL78_STACK_POP (tmp2);	/* B */
-	    RL78_STACK_POP (tmp1);	/* A */
-	    tmp1 -= tmp2;		/* A - B */
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
-
 	case R_RL78_OPmul:
-	  {
-	    int32_t tmp1, tmp2;
-
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 *= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
-
 	case R_RL78_OPdiv:
-	  {
-	    int32_t tmp1, tmp2;
-
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 /= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
-
 	case R_RL78_OPshla:
-	  {
-	    int32_t tmp1, tmp2;
-
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 <<= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
-
 	case R_RL78_OPshra:
-	  {
-	    int32_t tmp1, tmp2;
-
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 >>= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
-
 	case R_RL78_OPsctsize:
-	  RL78_STACK_PUSH (input_section->size);
-	  break;
-
 	case R_RL78_OPscttop:
-	  RL78_STACK_PUSH (input_section->output_section->vma);
-	  break;
-
 	case R_RL78_OPand:
-	  {
-	    int32_t tmp1, tmp2;
+	case R_RL78_OPor:
+	case R_RL78_OPxor:
+	case R_RL78_OPnot:
+	case R_RL78_OPmod:
+	  relocation = rl78_compute_complex_reloc (r_type, 0, input_section);
 
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 &= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
+	  switch (r_type)
+	    {
+	    case R_RL78_ABS32:
+	      OP (0) = relocation;
+	      OP (1) = relocation >> 8;
+	      OP (2) = relocation >> 16;
+	      OP (3) = relocation >> 24;
+	      break;
 
-	case R_RL78_OPor:
-	  {
-	    int32_t tmp1, tmp2;
+	    case R_RL78_ABS32_REV:
+	      OP (3) = relocation;
+	      OP (2) = relocation >> 8;
+	      OP (1) = relocation >> 16;
+	      OP (0) = relocation >> 24;
+	      break;
 
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 |= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
+	    case R_RL78_ABS24S_PCREL:
+	    case R_RL78_ABS24S:
+	      RANGE (-0x800000, 0x7fffff);
+	      OP (0) = relocation;
+	      OP (1) = relocation >> 8;
+	      OP (2) = relocation >> 16;
+	      break;
 
-	case R_RL78_OPxor:
-	  {
-	    int32_t tmp1, tmp2;
+	    case R_RL78_ABS16:
+	      RANGE (-32768, 65535);
+	      OP (0) = relocation;
+	      OP (1) = relocation >> 8;
+	      break;
 
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 ^= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
-	  break;
+	    case R_RL78_ABS16_REV:
+	      RANGE (-32768, 65535);
+	      OP (1) = relocation;
+	      OP (0) = relocation >> 8;
+	      break;
 
-	case R_RL78_OPnot:
-	  {
-	    int32_t tmp;
+	    case R_RL78_ABS16S_PCREL:
+	    case R_RL78_ABS16S:
+	      RANGE (-32768, 32767);
+	      OP (0) = relocation;
+	      OP (1) = relocation >> 8;
+	      break;
 
-	    RL78_STACK_POP (tmp);
-	    tmp = ~ tmp;
-	    RL78_STACK_PUSH (tmp);
-	  }
-	  break;
+	    case R_RL78_ABS16U:
+	    case R_RL78_ABS16UL:
+	    case R_RL78_ABS16UW:
+	      RANGE (0, 65536);
+	      OP (0) = relocation;
+	      OP (1) = relocation >> 8;
+	      break;
 
-	case R_RL78_OPmod:
-	  {
-	    int32_t tmp1, tmp2;
+	    case R_RL78_ABS8:
+	      RANGE (-128, 255);
+	      OP (0) = relocation;
+	      break;
 
-	    RL78_STACK_POP (tmp2);
-	    RL78_STACK_POP (tmp1);
-	    tmp1 %= tmp2;
-	    RL78_STACK_PUSH (tmp1);
-	  }
+	    case R_RL78_ABS8U:
+	    case R_RL78_ABS8UL:
+	    case R_RL78_ABS8UW:
+	      RANGE (0, 255);
+	      OP (0) = relocation;
+	      break;
+
+	    case R_RL78_ABS8S_PCREL:
+	    case R_RL78_ABS8S:
+	      RANGE (-128, 127);
+	      OP (0) = relocation;
+	      break;
+
+	    default:
+	      break;
+	    }
+	  break;
+	  
+	case R_RL78_SYM:
+	  if (r_symndx < symtab_hdr->sh_info)
+	    relocation = sec->output_section->vma + sec->output_offset
+	      + sym->st_value + rel->r_addend;
+	  else if (h != NULL
+		   && (h->root.type == bfd_link_hash_defined
+		       || h->root.type == bfd_link_hash_defweak))
+	    relocation = h->root.u.def.value
+	      + sec->output_section->vma
+	      + sec->output_offset
+	      + rel->r_addend;
+	  else
+	    {
+	      relocation = 0;
+	      if (h->root.type != bfd_link_hash_undefweak)
+		_bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol"));
+	    }
+	  (void) rl78_compute_complex_reloc (r_type, relocation, input_section);
 	  break;
 
 	case R_RL78_OPromtop:
-	  RL78_STACK_PUSH (get_romstart (&r, info, input_bfd, input_section, rel->r_offset));
+	  relocation = get_romstart (&r, info, input_bfd, input_section, rel->r_offset);
+	  (void) rl78_compute_complex_reloc (r_type, relocation, input_section);
 	  break;
 
 	case R_RL78_OPramtop:
-	  RL78_STACK_PUSH (get_ramstart (&r, info, input_bfd, input_section, rel->r_offset));
+	  relocation = get_ramstart (&r, info, input_bfd, input_section, rel->r_offset);
+	  (void) rl78_compute_complex_reloc (r_type, relocation, input_section);
 	  break;
 
 	default:
@@ -1688,22 +1826,21 @@ reloc_bubblesort (Elf_Internal_Rela * r, int count)
 
 #define OFFSET_FOR_RELOC(rel, lrel, scale) \
   rl78_offset_for_reloc (abfd, rel + 1, symtab_hdr, shndx_buf, intsyms, \
-		       lrel, abfd, sec, link_info, scale)
+			 lrel, abfd, sec, link_info, scale)
 
 static bfd_vma
 rl78_offset_for_reloc (bfd *                    abfd,
-		     Elf_Internal_Rela *      rel,
-		     Elf_Internal_Shdr *      symtab_hdr,
-		     Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED,
-		     Elf_Internal_Sym *       intsyms,
-		     Elf_Internal_Rela **     lrel,
-		     bfd *                    input_bfd,
-		     asection *               input_section,
-		     struct bfd_link_info *   info,
-		     int *                    scale)
+		       Elf_Internal_Rela *      rel,
+		       Elf_Internal_Shdr *      symtab_hdr,
+		       Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED,
+		       Elf_Internal_Sym *       intsyms,
+		       Elf_Internal_Rela **     lrel,
+		       bfd *                    input_bfd,
+		       asection *               input_section,
+		       struct bfd_link_info *   info,
+		       int *                    scale)
 {
   bfd_vma symval;
-  bfd_reloc_status_type r;
 
   *scale = 1;
 
@@ -1712,7 +1849,7 @@ rl78_offset_for_reloc (bfd *                    abfd,
      gets a pointer to the last relocation used.  */
   while (1)
     {
-      int32_t tmp1, tmp2;
+      unsigned long r_type;
 
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF32_R_SYM (rel->r_info) < symtab_hdr->sh_info)
@@ -1786,135 +1923,57 @@ rl78_offset_for_reloc (bfd *                    abfd,
 	  symval += rel->r_addend;
 	}
 
-      switch (ELF32_R_TYPE (rel->r_info))
+      r_type = ELF32_R_TYPE (rel->r_info);
+      switch (r_type)
 	{
 	case R_RL78_SYM:
-	  RL78_STACK_PUSH (symval);
+	  (void) rl78_compute_complex_reloc (r_type, symval, input_section);
 	  break;
 
-	case R_RL78_OPneg:
-	  RL78_STACK_POP (tmp1);
-	  tmp1 = - tmp1;
-	  RL78_STACK_PUSH (tmp1);
+	case R_RL78_OPromtop:
+	  symval = get_romstart (NULL, info, input_bfd, input_section, rel->r_offset);
+	  (void) rl78_compute_complex_reloc (r_type, symval, input_section);
 	  break;
 
-	case R_RL78_OPadd:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 += tmp2;
-	  RL78_STACK_PUSH (tmp1);
+	case R_RL78_OPramtop:
+	  symval = get_ramstart (NULL, info, input_bfd, input_section, rel->r_offset);
+	  (void) rl78_compute_complex_reloc (r_type, symval, input_section);
 	  break;
 
+	case R_RL78_OPneg:
+	case R_RL78_OPadd:
 	case R_RL78_OPsub:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp2 -= tmp1;
-	  RL78_STACK_PUSH (tmp2);
-	  break;
-
 	case R_RL78_OPmul:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 *= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPdiv:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 /= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPshla:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 <<= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPshra:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 >>= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPsctsize:
-	  RL78_STACK_PUSH (input_section->size);
-	  break;
-
 	case R_RL78_OPscttop:
-	  RL78_STACK_PUSH (input_section->output_section->vma);
-	  break;
-
 	case R_RL78_OPand:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 &= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPor:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 |= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPxor:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 ^= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPnot:
-	  RL78_STACK_POP (tmp1);
-	  tmp1 = ~ tmp1;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
 	case R_RL78_OPmod:
-	  RL78_STACK_POP (tmp1);
-	  RL78_STACK_POP (tmp2);
-	  tmp1 %= tmp2;
-	  RL78_STACK_PUSH (tmp1);
-	  break;
-
-	case R_RL78_OPromtop:
-	  RL78_STACK_PUSH (get_romstart (&r, info, input_bfd, input_section, rel->r_offset));
-	  break;
-
-	case R_RL78_OPramtop:
-	  RL78_STACK_PUSH (get_ramstart (&r, info, input_bfd, input_section, rel->r_offset));
+	  (void) rl78_compute_complex_reloc (r_type, 0, input_section);
 	  break;
 
 	case R_RL78_DIR16UL:
 	case R_RL78_DIR8UL:
 	case R_RL78_ABS16UL:
 	case R_RL78_ABS8UL:
-	  if (rl78_stack_top)
-	    RL78_STACK_POP (symval);
-	  if (lrel)
-	    *lrel = rel;
 	  *scale = 4;
-	  return symval;
+	  goto reloc_computes_value;
 
 	case R_RL78_DIR16UW:
 	case R_RL78_DIR8UW:
 	case R_RL78_ABS16UW:
 	case R_RL78_ABS8UW:
-	  if (rl78_stack_top)
-	    RL78_STACK_POP (symval);
-	  if (lrel)
-	    *lrel = rel;
 	  *scale = 2;
-	  return symval;
-
+	  goto reloc_computes_value;
+	  
 	default:
-	  if (rl78_stack_top)
-	    RL78_STACK_POP (symval);
+	reloc_computes_value:
+	  symval = rl78_compute_complex_reloc (r_type, 0, input_section);
 	  if (lrel)
 	    *lrel = rel;
 	  return symval;
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 31eb7a3..717533f 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,8 @@
+2015-04-14  Nick Clifton  <nickc@redhat.com>
+
+	* readelf.c (target_specific_reloc_handling): Add code to handle
+	RL78 complex relocs.
+
 2015-04-13  Doug Evans  <dje@google.com>
 
 	PR binutils/18218
diff --git a/binutils/readelf.c b/binutils/readelf.c
index ca25136..1533806 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -11161,6 +11161,42 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
 	  }
 	break;
       }
+
+    case EM_RL78:
+      {
+	static bfd_vma saved_sym1 = 0;
+	static bfd_vma saved_sym2 = 0;
+	static bfd_vma value;
+
+	switch (reloc_type)
+	  {
+	  case 0x80: /* R_RL78_SYM.  */
+	    saved_sym1 = saved_sym2;
+	    saved_sym2 = symtab[get_reloc_symindex (reloc->r_info)].st_value;
+	    saved_sym2 += reloc->r_addend;
+	    return TRUE;
+
+	  case 0x83: /* R_RL78_OPsub.  */
+	    value = saved_sym1 - saved_sym2;
+	    saved_sym2 = saved_sym1 = 0;
+	    return TRUE;
+	    break;
+
+	  case 0x41: /* R_RL78_ABS32.  */
+	    byte_put (start + reloc->r_offset, value, 4);
+	    value = 0;
+	    return TRUE;
+
+	  case 0x43: /* R_RL78_ABS16.  */
+	    byte_put (start + reloc->r_offset, value, 2);
+	    value = 0;
+	    return TRUE;
+
+	  default:
+	    break;
+	  }
+	break;
+      }
     }
 
   return FALSE;
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 636ef3c..c90f98c 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,9 @@
+2015-04-14  Nick Clifton  <nickc@redhat.com>
+
+	* config/tc-rl78.h (TC_LINKRELAX_FIXUP): Define.
+	(TC_FORCE_RELOCATION_SUB_SAME): Define.
+	(DWARF2_USE_FIXED_ADVANCE_PC): Define.
+
 2015-04-10  Nick Clifton  <nickc@redhat.com>
 
 	PR binutils/18198
diff --git a/gas/config/tc-rl78.c b/gas/config/tc-rl78.c
index 337b819..b5f0563 100644
--- a/gas/config/tc-rl78.c
+++ b/gas/config/tc-rl78.c
@@ -340,15 +340,16 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
 }
 
 void
-md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
+md_show_usage (FILE * stream)
 {
   fprintf (stream, _(" RL78 specific command line options:\n"));
+  fprintf (stream, _("  --mrelax          Enable link time relaxation\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"));
+  fprintf (stream, _("  --m64bit-doubles  Source code uses 64-bit doubles\n"));
 }
 
 static void
@@ -662,13 +663,23 @@ rl78_cons_fix_new (fragS *	frag,
     case BFD_RELOC_RL78_LO16:
     case BFD_RELOC_RL78_HI16:
       if (size != 2)
-	as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
-      type = exp->X_md;
+	{
+	  /* Fixups to assembler generated expressions do not use %hi or %lo.  */
+	  if (frag->fr_file)
+	    as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
+	}
+      else
+	type = exp->X_md;
       break;
     case BFD_RELOC_RL78_HI8:
       if (size != 1)
-	as_bad (_("%%hi8 only applies to .byte"));
-      type = exp->X_md;
+	{
+	  /* Fixups to assembler generated expressions do not use %hi or %lo.  */
+	  if (frag->fr_file)
+	    as_bad (_("%%hi8 only applies to .byte"));
+	}
+      else
+	type = exp->X_md;
       break;
     default:
       break;
@@ -823,7 +834,7 @@ rl78_frag_fix_value (fragS *    fragP,
 /* Estimate how big the opcode is after this relax pass.  The return
    value is the difference between fr_fix and the actual size.  We
    compute the total size in rl78_relax_frag and store it in fr_subtype,
-   sowe only need to subtract fx_fix and return it.  */
+   so we only need to subtract fx_fix and return it.  */
 
 int
 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
@@ -960,8 +971,8 @@ rl78_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
   fragP->fr_subtype = newsize;
   tprintf (" -> new %d old %d delta %d\n", newsize, oldsize, newsize-oldsize);
   return newsize - oldsize;
- }
- 
+}
+
 /* This lets us test for the opcode type and the desired size in a
    switch statement.  */
 #define OPCODE(type,size) ((type) * 16 + (size))
diff --git a/gas/config/tc-rl78.h b/gas/config/tc-rl78.h
index e2b9699..b9ede61 100644
--- a/gas/config/tc-rl78.h
+++ b/gas/config/tc-rl78.h
@@ -85,3 +85,17 @@ extern void rl78_elf_final_processing (void);
 
 #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES)	\
   ((EXP)->X_md = 0, expression (EXP), TC_PARSE_CONS_RETURN_NONE)
+
+#define TC_LINKRELAX_FIXUP(seg) ((seg->flags & SEC_CODE) || (seg->flags & SEC_DEBUGGING))
+
+/* Do not adjust relocations involving symbols in code sections,
+   because it breaks linker relaxations.  This could be fixed in the
+   linker, but this fix is simpler, and it pretty much only affects
+   object size a little bit.  */
+#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEC)	\
+  (   ((SEC)->flags & SEC_CODE) != 0		\
+   || ((SEC)->flags & SEC_DEBUGGING) != 0	\
+   || ! SEG_NORMAL (SEC)			\
+   || TC_FORCE_RELOCATION (FIX))
+
+#define DWARF2_USE_FIXED_ADVANCE_PC 1
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index fc2b934..6076b89 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-04-14  Nick Clifton  <nickc@redhat.com>
+
+	* gas/lns/lns.exp: Add RL78 to list of targets using
+	DW_LNS_fixed_advance_pc.
+
 2015-04-08  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* gas/i386/dw2-compressed-1.d: New file.
diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp
index b72c536..96aaffd 100644
--- a/gas/testsuite/gas/lns/lns.exp
+++ b/gas/testsuite/gas/lns/lns.exp
@@ -32,13 +32,14 @@ if {
      && ![istarget s390*-*-*]
 } {
     # Use alternate file for targets using DW_LNS_fixed_advance_pc opcodes.
-    if {    [istarget xtensa*-*-*]
-	 || [istarget am3*-*-*]
+    if {    [istarget am3*-*-*]
 	 || [istarget cr16-*-*]
 	 || [istarget crx-*-*]
+	 || [istarget mn10*-*-*]
 	 || [istarget msp430-*-*]
 	 || [istarget nds32*-*-*]
-	 || [istarget mn10*-*-*] } {
+	 || [istarget rl78-*-*]
+	 || [istarget xtensa*-*-*] } {
       run_dump_test "lns-common-1-alt"
       run_dump_test "lns-big-delta"
     } elseif { [istarget ia64*-*-*] } {


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