From ab86aea8d7b8fffc4f9bcb7d9af94be859394d13 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sat, 8 Mar 2008 14:58:14 +0000 Subject: [PATCH] 2008-03-08 Paul Brook 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. --- bfd/ChangeLog | 5 ++ bfd/elf32-arm.c | 81 +++++++++----------------------- ld/testsuite/ChangeLog | 6 +++ ld/testsuite/ld-arm/arm-elf.exp | 3 ++ ld/testsuite/ld-arm/thumb2-b-interwork.d | 19 ++++++++ ld/testsuite/ld-arm/thumb2-b-interwork.s | 20 ++++++++ 6 files changed, 76 insertions(+), 58 deletions(-) create mode 100644 ld/testsuite/ld-arm/thumb2-b-interwork.d create mode 100644 ld/testsuite/ld-arm/thumb2-b-interwork.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 73c6a77c3b..9027887700 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2008-03-08 Paul Brook + + * elf32-arm.c (insert_thumb_branch): Rewrite. + (elf32_thumb_to_arm_stub): Use new insert_thumb_branch. + 2008-03-07 Paul Brook * elf32-arm.c (elf32_arm_howto_table_1): Fix bitmasks for MOVW and diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 687d9cd33a..6764e67b17 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -4070,58 +4070,29 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, 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_info * info, { 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_info * info, /* 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; } diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index a30eba9433..329d6fb930 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-03-08 Paul Brook + + * 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. + 2008-03-07 Paul Brook * ld-arm/arm-elf.exp (armelftests): Add movw-merge and arm-app-movw. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 7c6ee2134f..81b9f75182 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -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 diff --git a/ld/testsuite/ld-arm/thumb2-b-interwork.d b/ld/testsuite/ld-arm/thumb2-b-interwork.d new file mode 100644 index 0000000000..00bc4d4245 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-b-interwork.d @@ -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 : + 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 + diff --git a/ld/testsuite/ld-arm/thumb2-b-interwork.s b/ld/testsuite/ld-arm/thumb2-b-interwork.s new file mode 100644 index 0000000000..4452a8f437 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-b-interwork.s @@ -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 + -- 2.11.0