- {
- long relocation, insn;
-
- /* Is the address of the relocation really within the section? */
- if (reloc->address > isection->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Work out which section the relocation is targetted at and the
- initial relocation command value. */
-
- /* Get symbol value. (Common symbols are special.) */
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- /* Convert input-section-relative symbol value to absolute + addend. */
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc->addend;
-
- if (reloc->howto->pc_relative == true)
- {
- /* Here the variable relocation holds the final address of the
- symbol we are relocating against, plus any addend. */
- relocation -= isection->output_section->vma + isection->output_offset;
-
- /* Deal with pcrel_offset */
- relocation -= reloc->address;
- }
-
- /* I've got no clue... */
- reloc->addend = 0;
-
- switch (reloc->howto->type)
- {
- default:
- /* fprintf (stderr, "reloc type %d not SUPPORTED\n", reloc->howto->type ); */
- return bfd_reloc_notsupported;
-
- case R_V850_22_PCREL:
- if (relocation > 0x1ffff || relocation < -0x200000)
- return bfd_reloc_overflow;
-
- if ((relocation % 2) != 0)
- return bfd_reloc_dangerous;
-
- insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
- insn &= ~0xfffe003f;
- insn |= (((relocation & 0xfffe) << 16)
- | ((relocation & 0x3f0000) >> 16));
- bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
- return bfd_reloc_ok;
-
- case R_V850_9_PCREL:
- if (relocation > 0xff || relocation < -0x100)
- return bfd_reloc_overflow;
-
- if ((relocation % 2) != 0)
- return bfd_reloc_dangerous;
-
- insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
- insn &= ~ 0xf870;
- insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
- bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
- return bfd_reloc_ok;
-
- case R_V850_HI16_S:
- relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
- relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
- bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
- return bfd_reloc_ok;
-
- case R_V850_HI16:
- relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
- relocation = (relocation >> 16);
- bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
- return bfd_reloc_ok;
-
- case R_V850_16:
- case R_V850_LO16:
- relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
-
- case R_V850_SDA_16_16_OFFSET:
- case R_V850_ZDA_16_16_OFFSET:
- if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
- return bfd_reloc_overflow;
- bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
- return bfd_reloc_ok;