-};
-\f
-/* Handle the R_M32R_10_PCREL reloc. */
-
-static bfd_reloc_status_type
-m32r_elf_10_pcrel_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message)
- bfd * abfd;
- arelent * reloc_entry;
- asymbol * symbol;
- PTR data;
- asection * input_section;
- bfd * output_bfd;
- char ** error_message ATTRIBUTE_UNUSED;
-{
- /* This part is from bfd_elf_generic_reloc. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (! reloc_entry->howto->partial_inplace
- || reloc_entry->addend == 0))
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (output_bfd != NULL)
- {
- /* FIXME: See bfd_perform_relocation. Is this right? */
- return bfd_reloc_continue;
- }
-
- return m32r_elf_do_10_pcrel_reloc (abfd, reloc_entry->howto,
- input_section,
- data, reloc_entry->address,
- symbol->section,
- (symbol->value
- + symbol->section->output_section->vma
- + symbol->section->output_offset),
- reloc_entry->addend);
-}
-
-/* Utility to actually perform an R_M32R_10_PCREL reloc. */
-
-static bfd_reloc_status_type
-m32r_elf_do_10_pcrel_reloc (abfd, howto, input_section, data, offset,
- symbol_section, symbol_value, addend)
- bfd *abfd;
- reloc_howto_type *howto;
- asection *input_section;
- bfd_byte *data;
- bfd_vma offset;
- asection *symbol_section ATTRIBUTE_UNUSED;
- bfd_vma symbol_value;
- bfd_vma addend;
-{
- bfd_signed_vma relocation;
- unsigned long x;
- bfd_reloc_status_type status;
-
- /* Sanity check the address (offset in section). */
- if (offset > bfd_get_section_limit (abfd, input_section))
- return bfd_reloc_outofrange;
-
- relocation = symbol_value + addend;
- /* Make it pc relative. */
- relocation -= (input_section->output_section->vma
- + input_section->output_offset);
- /* These jumps mask off the lower two bits of the current address
- before doing pcrel calculations. */
- relocation -= (offset & -(bfd_vma) 4);
-
- if (relocation < -0x200 || relocation > 0x1ff)
- status = bfd_reloc_overflow;
- else
- status = bfd_reloc_ok;
-
- x = bfd_get_16 (abfd, data + offset);
- relocation >>= howto->rightshift;
- relocation <<= howto->bitpos;
- x = (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask);
- bfd_put_16 (abfd, (bfd_vma) x, data + offset);
-
- return status;
-}
-
-/* Handle the R_M32R_HI16_[SU]LO relocs.
- HI16_SLO is for the add3 and load/store with displacement instructions.
- HI16_ULO is for the or3 instruction.
- For R_M32R_HI16_SLO, the lower 16 bits are sign extended when added to
- the high 16 bytes so if the lower 16 bits are negative (bit 15 == 1) then
- we must add one to the high 16 bytes (which will get subtracted off when
- the low 16 bits are added).
- These relocs have to be done in combination with an R_M32R_LO16 reloc
- because there is a carry from the LO16 to the HI16. Here we just save
- the information we need; we do the actual relocation when we see the LO16.
- This code is copied from the elf32-mips.c. We also support an arbitrary
- number of HI16 relocs to be associated with a single LO16 reloc. The
- assembler sorts the relocs to ensure each HI16 immediately precedes its
- LO16. However if there are multiple copies, the assembler may not find
- the real LO16 so it picks the first one it finds. */
-
-struct m32r_hi16
-{
- struct m32r_hi16 *next;
- bfd_byte *addr;
- bfd_vma addend;
-};
-
-/* FIXME: This should not be a static variable. */
-
-static struct m32r_hi16 *m32r_hi16_list;
-
-static bfd_reloc_status_type
-m32r_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- struct m32r_hi16 *n;
-
- /* This part is from bfd_elf_generic_reloc.
- If we're relocating, and this an external symbol, we don't want
- to change anything. */
- if (output_bfd != (bfd *) NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && reloc_entry->addend == 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- /* Sanity check the address (offset in section). */
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
- return bfd_reloc_outofrange;
-
- ret = bfd_reloc_ok;
- if (bfd_is_und_section (symbol->section)
- && output_bfd == (bfd *) NULL)
- ret = bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- /* Save the information, and let LO16 do the actual relocation. */
- n = (struct m32r_hi16 *) bfd_malloc ((bfd_size_type) sizeof *n);
- if (n == NULL)
- return bfd_reloc_outofrange;
- n->addr = (bfd_byte *) data + reloc_entry->address;
- n->addend = relocation;
- n->next = m32r_hi16_list;
- m32r_hi16_list = n;
-
- if (output_bfd != (bfd *) NULL)
- reloc_entry->address += input_section->output_offset;
-
- return ret;
-}
-
-/* Handle an M32R ELF HI16 reloc. */
-
-static void
-m32r_elf_relocate_hi16 (input_bfd, type, relhi, rello, contents, addend)
- bfd *input_bfd;
- int type;
- Elf_Internal_Rela *relhi;
- Elf_Internal_Rela *rello;
- bfd_byte *contents;
- bfd_vma addend;
-{
- unsigned long insn;
- bfd_vma addlo;
-
- insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
-
- addlo = bfd_get_32 (input_bfd, contents + rello->r_offset);
- if (type == R_M32R_HI16_SLO)
- addlo = ((addlo & 0xffff) ^ 0x8000) - 0x8000;
- else
- addlo &= 0xffff;
-
- addend += ((insn & 0xffff) << 16) + addlo;