+ 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_LO16:
+ relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ /* Do not complain if value has top bit set, as this has been anticipated. */
+ bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_16:
+ relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ /* drop through */
+
+ case R_V850_SDA_16_16_OFFSET:
+ case R_V850_ZDA_16_16_OFFSET:
+ case R_V850_TDA_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;
+
+ case R_V850_SDA_15_16_OFFSET:
+ case R_V850_ZDA_15_16_OFFSET:
+ if ((long)relocation > 0x7ffe || (long)relocation < -0x8000)
+ return bfd_reloc_overflow;
+
+ if (relocation & 1)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn &= 1;
+ insn |= (relocation >> 1) & ~1;
+
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_TDA_6_8_OFFSET:
+ if ((long) relocation > 0xfc || (long) relocation < 0)
+ return bfd_reloc_overflow;
+
+ if (relocation & 3)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn &= 0xff81;
+ insn |= (relocation >> 1);
+
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_TDA_7_8_OFFSET:
+ if ((long) relocation > 0xfe || (long) relocation < 0)
+ return bfd_reloc_overflow;
+
+ if (relocation & 1)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn &= 0xff80;
+ insn |= (relocation >> 1);
+
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_TDA_7_7_OFFSET:
+ if ((long) relocation > 0x7f || (long) relocation < 0)
+ return bfd_reloc_overflow;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn &= 0xff80;
+ insn |= relocation;
+
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+/* start-sanitize-v850e */
+ case R_V850_TDA_4_5_OFFSET:
+ if ((long) relocation > 0x1e || (long) relocation < 0)
+ return bfd_reloc_overflow;
+
+ if (relocation & 1)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn &= 0xfff0;
+ insn |= (relocation >> 1);
+
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_TDA_4_4_OFFSET:
+ if ((long) relocation > 0xf || (long) relocation < 0)
+ return bfd_reloc_overflow;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn &= 0xfff0;
+ insn |= relocation;
+
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_ZDA_16_16_SPLIT_OFFSET:
+ case R_V850_SDA_16_16_SPLIT_OFFSET:
+ if ((long) relocation > 0xffff || (long) relocation < 0)
+ return bfd_reloc_overflow;
+
+ insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
+
+ insn &= 0x0001ffdf;
+ insn |= (relocation & 1) << 5;
+ insn |= (relocation & ~1) << 16;
+
+ bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_CALLT_6_7_OFFSET:
+ if ((long) relocation > 0x7e || (long) relocation < 0)
+ return bfd_reloc_overflow;
+
+ if (relocation & 1)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn &= 0xff80;
+ insn |= (relocation >> 1);
+
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+ case R_V850_CALLT_16_16_OFFSET:
+ bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+
+/* end-sanitize-v850e */
+ }
+
+ return bfd_reloc_continue;
+}
+
+\f
+/*ARGSUSED*/
+static boolean
+v850_elf_is_local_label_name (abfd, name)
+ bfd * abfd;
+ const char * name;
+{
+ return ((name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
+ || (name[0] == '_' && name[1] == '.' && name[2] == 'L'
+ && name[3] == '_'));
+}
+
+\f
+/* Perform a relocation as part of a final link. */
+static bfd_reloc_status_type
+v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
+ input_section, contents, offset, value,
+ addend, info, sym_sec, is_local)
+ reloc_howto_type * howto;
+ bfd * input_bfd;
+ bfd * output_bfd;
+ asection * input_section;
+ bfd_byte * contents;
+ bfd_vma offset;
+ bfd_vma value;
+ bfd_vma addend;
+ struct bfd_link_info * info;
+ asection * sym_sec;
+ int is_local;
+{
+ unsigned long insn;
+ unsigned long r_type = howto->type;
+ bfd_byte * hit_data = contents + offset;
+
+ switch (r_type)
+ {
+ case R_V850_9_PCREL:
+ value -= (input_section->output_section->vma
+ + input_section->output_offset);
+ value -= offset;
+
+ if ((long)value > 0xff || (long)value < -0x100)
+ return bfd_reloc_overflow;
+
+ if ((value % 2) != 0)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_16 (input_bfd, hit_data);
+ insn &= 0x078f;
+ insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
+ bfd_put_16 (input_bfd, insn, hit_data);
+ return bfd_reloc_ok;
+
+ case R_V850_22_PCREL:
+ value -= (input_section->output_section->vma
+ + input_section->output_offset);
+ value -= offset;
+
+ if ((long)value > 0x1ffff || (long)value < -0x200000)
+ return bfd_reloc_overflow;
+
+ if ((value % 2) != 0)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_32 (input_bfd, hit_data);
+ insn &= 0x1ffc0;
+ insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
+ bfd_put_32 (input_bfd, insn, hit_data);
+ return bfd_reloc_ok;
+
+ case R_V850_HI16_S:
+ value += (short)bfd_get_16 (input_bfd, hit_data);
+ value = (value >> 16) + ((value & 0x8000) != 0);
+