This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Thumb-2 interworked b.w


The ARM linker contains logic to generate interworking veneers for Thumb-2 b.w 
instructions.  However the code that populates these veneers 
(insert_thumb_branch) aborts when this happens.  The code in 
insert_thumb_branch and many of the supporting comments are at best confused, 
at worst completely wrong, so I've rewritten the whole thing.

Tested on arm-none-eabi.
Applied to CVS head.

Paul

2008-03-08  Paul Brook  <paul@codesourcery.com>

	bfd/
	* elf32-arm.c (insert_thumb_branch): Rewrite.
	(elf32_thumb_to_arm_stub): Use new insert_thumb_branch.

	ld/testsuite/
	* ld-arm/arm-elf.exp (armeabitests): Add thumb2-b-interwork.
	* ld-arm/thumb2-b-interwork.d: New test.
	* ld-arm/thumb2-b-interwork.s: New test.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v
retrieving revision 1.137
diff -u -p -r1.137 elf32-arm.c
--- bfd/elf32-arm.c	8 Mar 2008 01:20:38 -0000	1.137
+++ bfd/elf32-arm.c	8 Mar 2008 13:58:25 -0000
@@ -4070,58 +4070,29 @@ bfd_elf32_arm_set_target_relocs (struct 
   elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
 }
 
-/* The thumb form of a long branch is a bit finicky, because the offset
-   encoding is split over two fields, each in it's own instruction. They
-   can occur in any order. So given a thumb form of long branch, and an
-   offset, insert the offset into the thumb branch and return finished
-   instruction.
-
-   It takes two thumb instructions to encode the target address. Each has
-   11 bits to invest. The upper 11 bits are stored in one (identified by
-   H-0.. see below), the lower 11 bits are stored in the other (identified
-   by H-1).
-
-   Combine together and shifted left by 1 (it's a half word address) and
-   there you have it.
-
-   Op: 1111 = F,
-   H-0, upper address-0 = 000
-   Op: 1111 = F,
-   H-1, lower address-0 = 800
-
-   They can be ordered either way, but the arm tools I've seen always put
-   the lower one first. It probably doesn't matter. krk@cygnus.com
-
-   XXX:  Actually the order does matter.  The second instruction (H-1)
-   moves the computed address into the PC, so it must be the second one
-   in the sequence.  The problem, however is that whilst little endian code
-   stores the instructions in HI then LOW order, big endian code does the
-   reverse.  nickc@cygnus.com.  */
-
-#define LOW_HI_ORDER      0xF800F000
-#define HI_LOW_ORDER      0xF000F800
-
-static insn32
-insert_thumb_branch (insn32 br_insn, int rel_off)
-{
-  unsigned int low_bits;
-  unsigned int high_bits;
-
-  BFD_ASSERT ((rel_off & 1) != 1);
-
-  rel_off >>= 1;				/* Half word aligned address.  */
-  low_bits = rel_off & 0x000007FF;		/* The bottom 11 bits.  */
-  high_bits = (rel_off >> 11) & 0x000007FF;	/* The top 11 bits.  */
-
-  if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
-    br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
-  else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)
-    br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
-  else
-    /* FIXME: abort is probably not the right call. krk@cygnus.com  */
-    abort ();	/* Error - not a valid branch instruction form.  */
+/* Replace the target offset of a Thumb bl or b.w instruction.  */
 
-  return br_insn;
+static void
+insert_thumb_branch (bfd *abfd, long int offset, bfd_byte *insn)
+{
+  bfd_vma upper;
+  bfd_vma lower;
+  int reloc_sign;
+
+  BFD_ASSERT ((offset & 1) == 0);
+
+  upper = bfd_get_16 (abfd, insn);
+  lower = bfd_get_16 (abfd, insn + 2);
+  reloc_sign = (offset < 0) ? 1 : 0;
+  upper = (upper & ~(bfd_vma) 0x7ff)
+	  | ((offset >> 12) & 0x3ff)
+	  | (reloc_sign << 10);
+  lower = (lower & ~(bfd_vma) 0x2fff) 
+	  | (((!((offset >> 23) & 1)) ^ reloc_sign) << 13)
+	  | (((!((offset >> 22) & 1)) ^ reloc_sign) << 11)
+	  | ((offset >> 1) & 0x7ff);
+  bfd_put_16 (abfd, upper, insn);
+  bfd_put_16 (abfd, lower, insn + 2);
 }
 
 
@@ -4170,7 +4141,6 @@ elf32_thumb_to_arm_stub (struct bfd_link
 {
   asection * s = 0;
   bfd_vma my_offset;
-  unsigned long int tmp;
   long int ret_offset;
   struct elf_link_hash_entry * myh;
   struct elf32_arm_link_hash_table * globals;
@@ -4251,12 +4221,7 @@ elf32_thumb_to_arm_stub (struct bfd_link
     /* Biassing for PC-relative addressing.  */
     - 8;
 
-  tmp = bfd_get_32 (input_bfd, hit_data
-		    - input_section->vma);
-
-  bfd_put_32 (output_bfd,
-	      (bfd_vma) insert_thumb_branch (tmp, ret_offset),
-	      hit_data - input_section->vma);
+  insert_thumb_branch (input_bfd, ret_offset, hit_data - input_section->vma);
 
   return TRUE;
 }
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.33
diff -u -p -r1.33 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	8 Mar 2008 01:20:39 -0000	1.33
+++ ld/testsuite/ld-arm/arm-elf.exp	8 Mar 2008 13:58:41 -0000
@@ -209,6 +209,9 @@ set armeabitests {
      {"Thumb-2 BL" "-Ttext 0x1000 --section-start .foo=0x1001000" "" 
{thumb2-bl.s}
       {{objdump -dr thumb2-bl.d}}
       "thumb2-bl"}
+     {"Thumb-2 Interworked branch" "-T arm.ld" "" {thumb2-b-interwork.s}
+      {{objdump -dr thumb2-b-interwork.d}}
+      "thumb2-b-interwork"}
 }
 
 run_ld_link_tests $armeabitests
Index: ld/testsuite/ld-arm/thumb2-b-interwork.d
===================================================================
RCS file: ld/testsuite/ld-arm/thumb2-b-interwork.d
diff -N ld/testsuite/ld-arm/thumb2-b-interwork.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/thumb2-b-interwork.d	6 Mar 2008 20:30:34 -0000
@@ -0,0 +1,19 @@
+
+.*thumb2-b-interwork:     file format elf32-.*arm
+
+Disassembly of section .text:
+
+00008000 <_start>:
+    8000:	f000 b802 	b.w	8008 <__bar_from_thumb>
+
+00008004 <bar>:
+    8004:	e12fff1e 	bx	lr
+Disassembly of section .glue_7t:
+
+00008008 <__bar_from_thumb>:
+    8008:	4778      	bx	pc
+    800a:	46c0      	nop			\(mov r8, r8\)
+
+0000800c <__bar_change_to_arm>:
+    800c:	eafffffc 	b	8004 <bar>
+
Index: ld/testsuite/ld-arm/thumb2-b-interwork.s
===================================================================
RCS file: ld/testsuite/ld-arm/thumb2-b-interwork.s
diff -N ld/testsuite/ld-arm/thumb2-b-interwork.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/thumb2-b-interwork.s	6 Mar 2008 20:30:34 -0000
@@ -0,0 +1,20 @@
+@ Test to ensure that a Thumb-2 B.W can branch to an ARM funtion.
+
+	.arch armv7-a
+	.global _start
+	.syntax unified
+	.text
+	.thumb_func
+
+_start:
+	b.w bar
+
+@ Put this in a separate section to force the assembler to generate a reloc
+
+	.arm
+	.section .after, "xa"
+	.global bar
+	.type bar, %function
+bar:
+	bx lr
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]