Adds support to the RL78 port for linker relaxation affecting .debug sections.
authorNick Clifton <nickc@redhat.com>
Tue, 14 Apr 2015 15:23:33 +0000 (16:23 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 14 Apr 2015 15:23:33 +0000 (16:23 +0100)
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.

bfd/ChangeLog
bfd/elf32-rl78.c
binutils/ChangeLog
binutils/readelf.c
gas/ChangeLog
gas/config/tc-rl78.c
gas/config/tc-rl78.h
gas/testsuite/ChangeLog
gas/testsuite/gas/lns/lns.exp

index 056833e..49202af 100644 (file)
@@ -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
index 70b49aa..2822547 100644 (file)
   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)
 };
 \f
 /* 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;
index 31eb7a3..717533f 100644 (file)
@@ -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
index ca25136..1533806 100644 (file)
@@ -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;
index 636ef3c..c90f98c 100644 (file)
@@ -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
index 337b819..b5f0563 100644 (file)
@@ -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))
index e2b9699..b9ede61 100644 (file)
@@ -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
index fc2b934..6076b89 100644 (file)
@@ -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.
index b72c536..96aaffd 100644 (file)
@@ -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*-*-*] } {