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