+
+ /* Try to turn a 16-bit absolute branch into a 10-bit pc-relative
+ branch. */
+ if (uses_msp430x_relocs (abfd)
+ && ELF32_R_TYPE (irel->r_info) == R_MSP430X_ABS16)
+ {
+ bfd_vma value = symval;
+
+ value -= (sec->output_section->vma + sec->output_offset);
+ value -= irel->r_offset;
+ value += irel->r_addend;
+
+ /* See if the value will fit in 10 bits, note the high value is
+ 1016 as the target will be two bytes closer if we are
+ able to relax. */
+ if ((long) value < 1016 && (long) value > -1016)
+ {
+ int code2;
+
+ /* Get the opcode. */
+ code2 = bfd_get_16 (abfd, contents + irel->r_offset - 2);
+ if (code2 != 0x4030)
+ continue;
+ /* FIXME: check r4 and r3 ? */
+ /* FIXME: Handle 0x4010 as well ? */
+
+ /* Note that we've changed the relocs, section contents, etc. */
+ elf_section_data (sec)->relocs = internal_relocs;
+ elf_section_data (sec)->this_hdr.contents = contents;
+ symtab_hdr->contents = (unsigned char *) isymbuf;
+
+ /* Fix the relocation's type. */
+ if (uses_msp430x_relocs (abfd))
+ {
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ R_MSP430X_10_PCREL);
+ }
+ else
+ {
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ R_MSP430_10_PCREL);
+ }
+
+ /* Fix the opcode right way. */
+ bfd_put_16 (abfd, 0x3c00, contents + irel->r_offset - 2);
+ irel->r_offset -= 2;
+
+ /* Delete bytes. */
+ if (!msp430_elf_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 2, 2))
+ goto error_return;
+
+ /* That will change things, so, we should relax again.
+ Note that this is not required, and it may be slow. */
+ *again = TRUE;
+ }
+ }