aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-msp430.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-01-08 16:23:16 +0000
committerNick Clifton <nickc@redhat.com>2015-01-08 16:23:16 +0000
commit23d4663e222cbb2b9776150677683516bb7135b7 (patch)
tree252ae9c68ed8ed8a67fb907c39b18768ba441eda /bfd/elf32-msp430.c
parent063bb0250defafcc55544474a2961ecbc153882e (diff)
downloadgdb-23d4663e222cbb2b9776150677683516bb7135b7.zip
gdb-23d4663e222cbb2b9776150677683516bb7135b7.tar.gz
gdb-23d4663e222cbb2b9776150677683516bb7135b7.tar.bz2
Adds code to the MSP430 linker to transform a 4-byte BR instruction into
a 2-byte JMP instruction, when this can be done safely. * elf32-msp430.c (msp430_elf_relax_section): Add relaxation of 16-bit absolute BR instructions to 10-bit pc-relative JMP instructions.
Diffstat (limited to 'bfd/elf32-msp430.c')
-rw-r--r--bfd/elf32-msp430.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c
index d3a7cdb..2157eb0 100644
--- a/bfd/elf32-msp430.c
+++ b/bfd/elf32-msp430.c
@@ -1768,7 +1768,6 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
bfd_byte * contents = NULL;
Elf_Internal_Sym * isymbuf = NULL;
-
/* Assume nothing changes. */
*again = FALSE;
@@ -1966,10 +1965,6 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
*again = TRUE;
}
- if (! uses_msp430x_relocs (abfd))
- /* Now perform the relocations that shrink the code size.
- We only do this for non msp430x as gas only generates the RL
- reloc for the msp430. */
for (irel = internal_relocs; irel < irelend; irel++)
{
bfd_vma symval;
@@ -2048,7 +2043,8 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
/* Try to turn a 16bit pc-relative branch into a 10bit pc-relative
branch. */
/* Paranoia? paranoia... */
- if (ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
+ if (! uses_msp430x_relocs (abfd)
+ && ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
{
bfd_vma value = symval;
@@ -2158,6 +2154,62 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
*again = TRUE;
}
}
+
+ /* 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 -= 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;
+ }
+ }
}
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)