From fc91707cc23bf4d1cd75cc754c28cc4ff6b8c5bd Mon Sep 17 00:00:00 2001 From: Nick Clifton <nickc@redhat.com> Date: Wed, 21 Nov 2007 12:06:26 +0000 Subject: [PATCH] * elf-m10300.c (mn10300_elf_relax_section): Allow for alignment relocs when computing whether instructions can be relaxed. * ld-mn10300/i135409-4.s: New test case. Check for relaxation to a 16-bit jump instruction. * ld-mn10300/i135409-4.t: Linker script for the new test. * ld-mn10300/i135409-4.d: Expected disassembly of new test. * ld-mn10300/mn10300.exp: Run the new test. --- bfd/ChangeLog | 5 +++++ bfd/elf-m10300.c | 33 ++++++++++++++++++++++++++++- ld/testsuite/ChangeLog | 8 +++++++ ld/testsuite/ld-mn10300/i135409-4.d | 7 ++++++ ld/testsuite/ld-mn10300/i135409-4.s | 8 +++++++ ld/testsuite/ld-mn10300/i135409-4.t | 23 ++++++++++++++++++++ ld/testsuite/ld-mn10300/mn10300.exp | 8 +++++++ 7 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 ld/testsuite/ld-mn10300/i135409-4.d create mode 100644 ld/testsuite/ld-mn10300/i135409-4.s create mode 100644 ld/testsuite/ld-mn10300/i135409-4.t diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c02027b94a0..8dc7003f3fe 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2007-11-21 Nick Clifton <nickc@redhat.com> + + * elf-m10300.c (mn10300_elf_relax_section): Allow for alignment + relocs when computing whether instructions can be relaxed. + 2007-11-16 Tristan Gingold <gingold@adacore.com> * elflink.c (elf_link_output_extsym): Weaken assertion: if diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index 77c8caee34a..2695217f4eb 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -2105,6 +2105,7 @@ mn10300_elf_relax_section (bfd *abfd, Elf_Internal_Sym *isymbuf = NULL; struct elf32_mn10300_link_hash_table *hash_table; asection *section = sec; + bfd_vma align_gap_adjustment; /* Assume nothing changes. */ *again = FALSE; @@ -2718,6 +2719,33 @@ mn10300_elf_relax_section (bfd *abfd, if (internal_relocs == NULL) goto error_return; + /* Scan for worst case alignment gap changes. Note that this logic + is not ideal; what we should do is run this scan for every + opcode/address range and adjust accordingly, but that's + expensive. Worst case is that for an alignment of N bytes, we + move by 2*N-N-1 bytes, assuming we have aligns of 1, 2, 4, 8, etc + all before it. Plus, this still doesn't cover cross-section + jumps with section alignment. */ + irelend = internal_relocs + sec->reloc_count; + align_gap_adjustment = 0; + for (irel = internal_relocs; irel < irelend; irel++) + { + if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN) + { + bfd_vma adj = 1 << irel->r_addend; + bfd_vma aend = irel->r_offset; + + aend = BFD_ALIGN (aend, 1 << irel->r_addend); + adj = 2*adj - adj - 1; + + /* Record the biggest adjustmnet. Skip any alignment at the + end of our section. */ + if (align_gap_adjustment < adj + && aend < sec->output_section->vma + sec->output_offset + sec->size) + align_gap_adjustment = adj; + } + } + /* Walk through them looking for relaxing opportunities. */ irelend = internal_relocs + sec->reloc_count; for (irel = internal_relocs; irel < irelend; irel++) @@ -2933,7 +2961,10 @@ mn10300_elf_relax_section (bfd *abfd, /* See if the value will fit in 16 bits, note the high value is 0x7fff + 2 as the target will be two bytes closer if we are able to relax. */ - if ((long) value < 0x8001 && (long) value > -0x8000) + /* Account for jumps across alignment boundaries using + align_gap_adjustment. */ + if (value < 0x8001 - align_gap_adjustment + && ((bfd_signed_vma) value > -0x8000 + (bfd_signed_vma) align_gap_adjustment)) { unsigned char code; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index da6d9b08296..7e8719ad93a 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2007-11-21 Nick Clifton <nickc@redhat.com> + + * ld-mn10300/i135409-4.s: New test case. Check for relaxation to + a 16-bit jump instruction. + * ld-mn10300/i135409-4.t: Linker script for the new test. + * ld-mn10300/i135409-4.d: Expected disassembly of new test. + * ld-mn10300/mn10300.exp: Run the new test. + 2007-11-20 Nick Clifton <nickc@redhat.com> * lib/ld-lib.exp (check_gc_sections_available): New proc, based diff --git a/ld/testsuite/ld-mn10300/i135409-4.d b/ld/testsuite/ld-mn10300/i135409-4.d new file mode 100644 index 00000000000..f14ea7d4b3e --- /dev/null +++ b/ld/testsuite/ld-mn10300/i135409-4.d @@ -0,0 +1,7 @@ + +tmpdir/i135409-4.x: file format elf32-.* + +Disassembly of section .text: + +0+0 <_start>: + 0:[ ]+cc 00 07[ ]+jmp[ ]+700 \<L001\> diff --git a/ld/testsuite/ld-mn10300/i135409-4.s b/ld/testsuite/ld-mn10300/i135409-4.s new file mode 100644 index 00000000000..90badde5b00 --- /dev/null +++ b/ld/testsuite/ld-mn10300/i135409-4.s @@ -0,0 +1,8 @@ + .text + .global _start +_start: + jmp L001 + + .section .text1 +L001: + nop diff --git a/ld/testsuite/ld-mn10300/i135409-4.t b/ld/testsuite/ld-mn10300/i135409-4.t new file mode 100644 index 00000000000..9d905cbd065 --- /dev/null +++ b/ld/testsuite/ld-mn10300/i135409-4.t @@ -0,0 +1,23 @@ +SECTIONS +{ + . = 0x0; + .text : + { + *(.text) + } + + . = 0x700; + .text1 : + { + *(.text1) + } + . = 0x8100; + .bss : + { + *(.bss) + } + .data : + { + *(.data) + } +} diff --git a/ld/testsuite/ld-mn10300/mn10300.exp b/ld/testsuite/ld-mn10300/mn10300.exp index a8128ed68be..f67881f75af 100644 --- a/ld/testsuite/ld-mn10300/mn10300.exp +++ b/ld/testsuite/ld-mn10300/mn10300.exp @@ -79,6 +79,14 @@ set mn10300_tests { { {objdump -d i135409-3.d} } "i135409-3.x" } + { + "adjusting a 16 bit branch" + "-Ti135409-4.t -relax" + "" + { "i135409-4.s" } + { {objdump -d i135409-4.d} } + "i135409-4.x" + } } run_ld_link_tests $mn10300_tests