summaryrefslogtreecommitdiff
path: root/bfd/elf32-rl78.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-04-14 16:23:33 +0100
committerNick Clifton <nickc@redhat.com>2015-04-14 16:23:33 +0100
commit6ff71e768112317de1236a429e7c88c9d3e32116 (patch)
tree3d24e09232efe594ec6a32482a95b2f161250e4e /bfd/elf32-rl78.c
parent9e811bc379ef78f0e2beadda9ed3ce6679ded7ea (diff)
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.
Diffstat (limited to 'bfd/elf32-rl78.c')
-rw-r--r--bfd/elf32-rl78.c835
1 files changed, 447 insertions, 388 deletions
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c
index 70b49aa00a..2822547629 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;