mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
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.
This commit is contained in:
parent
39623e120c
commit
12a0a0fd88
@ -1,3 +1,8 @@
|
||||
2008-03-08 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* elf32-arm.c (insert_thumb_branch): Rewrite.
|
||||
(elf32_thumb_to_arm_stub): Use new insert_thumb_branch.
|
||||
|
||||
2008-03-07 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* elf32-arm.c (elf32_arm_howto_table_1): Fix bitmasks for MOVW and
|
||||
|
@ -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.
|
||||
/* Replace the target offset of a Thumb bl or b.w 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)
|
||||
static void
|
||||
insert_thumb_branch (bfd *abfd, long int offset, bfd_byte *insn)
|
||||
{
|
||||
unsigned int low_bits;
|
||||
unsigned int high_bits;
|
||||
bfd_vma upper;
|
||||
bfd_vma lower;
|
||||
int reloc_sign;
|
||||
|
||||
BFD_ASSERT ((rel_off & 1) != 1);
|
||||
BFD_ASSERT ((offset & 1) == 0);
|
||||
|
||||
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. */
|
||||
|
||||
return br_insn;
|
||||
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;
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
2008-03-08 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* 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 <paul@codesourcery.com>
|
||||
|
||||
* ld-arm/arm-elf.exp (armelftests): Add movw-merge and arm-app-movw.
|
||||
|
@ -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
|
||||
|
19
ld/testsuite/ld-arm/thumb2-b-interwork.d
Normal file
19
ld/testsuite/ld-arm/thumb2-b-interwork.d
Normal file
@ -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>
|
||||
|
20
ld/testsuite/ld-arm/thumb2-b-interwork.s
Normal file
20
ld/testsuite/ld-arm/thumb2-b-interwork.s
Normal file
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user