target: consider addressable unit size when reading/writing memory
[deliverable/binutils-gdb.git] / bfd / elf32-rl78.c
index 70b49aa00a8ff1398c57b037492c7571beafac66..ff3af7b33629cbda675cb08c5c26b3f6a399f97c 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],
@@ -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;
This page took 0.034678 seconds and 4 git commands to generate.