ARM long branch stubs: be8

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

ARM long branch stubs: be8

Christophe Lyon
Hi all,

Following our recent discussion, I propose the attached patch to fix
big-endian / be8 stubs encoding issues.

I am not particularly proud of the way it's now done, but it does the job.
In short, the Thumb instructions in the stubs now use 1 entry per
instruction (instead of 2 instr per entry), but this implies that the
encoding functions know the exact layout of each stub, so it makes
maintenance a bit more painful (I added some comments to warn about that).

I have added one more test (farcall-thumb-arm-be8).

Once this is OK, I'll come back to my original patches to improve
PIC/PLT support.

Christophe.

2009-02-20  Christophe Lyon  <[hidden email]>

        bfd/
        * elf32-arm.c (elf32_arm_stub_long_branch_thumb_only): Split Thumb
        instructions encoding.
        (elf32_arm_stub_long_branch_v4t_thumb_arm): Likewise.
        (elf32_arm_stub_short_branch_v4t_thumb_arm): Likewise.
        (arm_build_one_stub): Encode Arm and Thumb instructions separately
        to take endianness into account.
        (arm_size_one_stub): Hardcode size of stubs.

        testsuite/
        * ld-arm/arm-elf.exp: Add new farcall-thumb-arm-be8 test.
        * ld-arm/farcall-thumb-arm-be8.d: New expected result.
        * ld-arm/farcall-arm-arm-be8.d: Replace wildcards by instructions.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.172
diff -u -p -r1.172 elf32-arm.c
--- bfd/elf32-arm.c 18 Feb 2009 16:56:37 -0000 1.172
+++ bfd/elf32-arm.c 23 Feb 2009 09:50:07 -0000
@@ -2010,6 +2010,9 @@ static const bfd_vma elf32_arm_symbian_p
 #define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
 #define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
 
+/* CAUTION: when updating the stubs code, don't forget to also update
+   arm_build_one_stub and arm_size_one_stub below.  */
+
 /* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
    to reach the stub if necessary.  */
 static const bfd_vma elf32_arm_stub_long_branch_any_any[] =
@@ -2032,12 +2035,12 @@ static const bfd_vma elf32_arm_stub_long
    to ARM.  */
 static const bfd_vma elf32_arm_stub_long_branch_thumb_only[] =
   {
-    0x4e02b540,         /* push {r6, lr} */
-                        /* ldr  r6, [pc, #8] */
-    0x473046fe,         /* mov  lr, pc */
-                        /* bx   r6 */
-    0xbf00bd40,         /* pop  {r6, pc} */
-                        /* nop */
+    0xb540,             /* push {r6, lr} */
+    0x4e02,             /* ldr  r6, [pc, #8] */
+    0x46fe,             /* mov  lr, pc */
+    0x4730,             /* bx   r6 */
+    0xbd40,             /* pop  {r6, pc} */
+    0xbf00,             /* nop */
     0x00000000,         /* dcd  R_ARM_ABS32(X) */
   };
 
@@ -2045,10 +2048,10 @@ static const bfd_vma elf32_arm_stub_long
    available.  */
 static const bfd_vma elf32_arm_stub_long_branch_v4t_thumb_arm[] =
   {
-    0x4e03b540,         /* push {r6, lr} */
-                        /* ldr  r6, [pc, #12] */
-    0x473046fe,         /* mov  lr, pc */
-                        /* bx   r6 */
+    0xb540,             /* push {r6, lr} */
+    0x4e03,             /* ldr  r6, [pc, #12] */
+    0x46fe,             /* mov  lr, pc */
+    0x4730,             /* bx   r6 */
     0xe8bd4040,         /* pop  {r6, pc} */
     0xe12fff1e,         /* bx   lr */
     0x00000000,         /* dcd  R_ARM_ABS32(X) */
@@ -2058,8 +2061,8 @@ static const bfd_vma elf32_arm_stub_long
    one, when the destination is close enough.  */
 static const bfd_vma elf32_arm_stub_short_branch_v4t_thumb_arm[] =
   {
-    0x46c04778,         /* bx   pc */
-                        /* nop   */
+    0x4778,             /* bx   pc */
+    0x46c0,             /* nop   */
     0xea000000,         /* b    (X) */
   };
 
@@ -3089,8 +3092,7 @@ arm_build_one_stub (struct bfd_hash_entr
   bfd_vma stub_addr;
   bfd_byte *loc;
   bfd_vma sym_value;
-  int template_size;
-  int size;
+  int size = 0;
   const bfd_vma *template;
   int i;
   struct elf32_arm_link_hash_table * globals;
@@ -3119,49 +3121,85 @@ arm_build_one_stub (struct bfd_hash_entr
        + stub_entry->target_section->output_offset
        + stub_entry->target_section->output_section->vma);
 
+  /* CAUTION: the calls to put_arm_insn, put_thumb_insn and bfd_put_32
+     below must be kept in sync with the actual stubs contents.  */
   switch (stub_entry->stub_type)
     {
     case arm_stub_long_branch_any_any:
       template = elf32_arm_stub_long_branch_any_any;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
+      for (i = 0; i < 1; i++)
+ {
+  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+  size += 4;
+ }
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       break;
+
     case arm_stub_long_branch_v4t_arm_thumb:
       template =  elf32_arm_stub_long_branch_v4t_arm_thumb;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
+      for (i = 0; i < 2; i++)
+ {
+  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+  size += 4;
+ }
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       break;
+
     case arm_stub_long_branch_thumb_only:
       template =  elf32_arm_stub_long_branch_thumb_only;
-      template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
+      for (i = 0; i < 6; i++)
+ {
+  put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+  size += 2;
+ }
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       break;
+
     case arm_stub_long_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+      for (i = 0; i < 4; i++)
+ {
+  put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+  size += 2;
+ }
+      for (i = 4; i < 6; i++)
+ {
+  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+  size += 4;
+ }
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       break;
+
     case arm_stub_short_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_short_branch_v4t_thumb_arm;
-      template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+      for (i = 0; i < 2; i++)
+ {
+  put_thumb_insn (globals, stub_bfd, template[i], loc + size);
+  size += 2;
+ }
+      size += 4;
       break;
+
     case arm_stub_long_branch_any_any_pic:
       template = elf32_arm_stub_long_branch_any_any_pic;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
+      for (i = 0; i < 2; i++)
+ {
+  put_arm_insn (globals, stub_bfd, template[i], loc + size);
+  size += 4;
+ }
+      bfd_put_32 (stub_bfd, template[i], loc + size);
+      size += 4;
       break;
+
     default:
       BFD_FAIL ();
       return FALSE;
     }
 
-  size = 0;
-  for (i = 0; i < (template_size / 4); i++)
-    {
-      /* A 0 pattern is a placeholder, every other pattern is an
- instruction.  */
-      if (template[i] != 0)
- put_arm_insn (globals, stub_bfd, template[i], loc + size);
-      else
- bfd_put_32 (stub_bfd, template[i], loc + size);
-
-      size += 4;
-    }
   stub_sec->size += size;
 
   /* Destination is Thumb. Force bit 0 to 1 to reflect this.  */
@@ -3229,38 +3267,38 @@ arm_size_one_stub (struct bfd_hash_entry
   struct elf32_arm_link_hash_table *htab;
   const bfd_vma *template;
   int template_size;
-  int size;
-  int i;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
   htab = (struct elf32_arm_link_hash_table *) in_arg;
 
+  /* CAUTION: the stub sizes below must be kept in sync with the
+     actual stubs contents.  */
   switch (stub_entry->stub_type)
     {
     case arm_stub_long_branch_any_any:
       template =  elf32_arm_stub_long_branch_any_any;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
+      template_size = 8;
       break;
     case arm_stub_long_branch_v4t_arm_thumb:
       template =  elf32_arm_stub_long_branch_v4t_arm_thumb;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
+      template_size = 12;
       break;
     case arm_stub_long_branch_thumb_only:
       template =  elf32_arm_stub_long_branch_thumb_only;
-      template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
+      template_size = 16;
       break;
     case arm_stub_long_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+      template_size = 20;
       break;
     case arm_stub_short_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_short_branch_v4t_thumb_arm;
-      template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+      template_size = 8;
       break;
     case arm_stub_long_branch_any_any_pic:
       template = elf32_arm_stub_long_branch_any_any_pic;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
+      template_size = 12;
       break;
     default:
       BFD_FAIL ();
@@ -3268,11 +3306,8 @@ arm_size_one_stub (struct bfd_hash_entry
       break;
     }
 
-  size = 0;
-  for (i = 0; i < (template_size / 4); i++)
-      size += 4;
-  size = (size + 7) & ~7;
-  stub_entry->stub_sec->size += size;
+  template_size = (template_size + 7) & ~7;
+  stub_entry->stub_sec->size += template_size;
   return TRUE;
 }
 
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.44
diff -u -p -r1.44 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 5 Feb 2009 21:54:43 -0000 1.44
+++ ld/testsuite/ld-arm/arm-elf.exp 23 Feb 2009 09:50:13 -0000
@@ -284,6 +284,9 @@ set armeabitests {
     {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
      "farcall-thumb-arm"}
+    {"Thumb-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB --be8" "-W -EB" {farcall-thumb-arm.s}
+     {{objdump -d farcall-thumb-arm-be8.d}}
+     "farcall-thumb-arm"}
     {"Thumb-ARM (short) call" "-Ttext 0x1000 --section-start .foo=0x0002014" "-W" {farcall-thumb-arm-short.s}
      {{objdump -d farcall-thumb-arm-short.d}}
      "farcall-thumb-arm-short"}
Index: ld/testsuite/ld-arm/farcall-arm-arm-be8.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-arm-arm-be8.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-arm-arm-be8.d
--- ld/testsuite/ld-arm/farcall-arm-arm-be8.d 25 Jun 2008 14:28:48 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-arm-arm-be8.d 23 Feb 2009 09:50:13 -0000
@@ -3,12 +3,12 @@
 Disassembly of section .text:
 
 00001000 <__bar_veneer>:
-    1000: 04f01fe5 .*
+    1000: 04f01fe5 ldr pc, \[pc, #-4\] ; 1004 <__bar_veneer\+0x4>
     1004: 02001020 .word 0x02001020
 
 00001008 <_start>:
-    1008: fcffffeb .*
+    1008: fcffffeb bl 1000 <__bar_veneer>
 Disassembly of section .foo:
 
 02001020 <bar>:
- 2001020: 1eff2fe1 .*
+ 2001020: 1eff2fe1 bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
diff -N ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-thumb-arm-be8.d 23 Feb 2009 09:50:13 -0000
@@ -0,0 +1,20 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+    1000: 40b5       push {r6, lr}
+    1002: 034e       ldr r6, \[pc, #12\] \(1010 <__bar_from_thumb\+0x10>\)
+    1004: fe46       mov lr, pc
+    1006: 3047       bx r6
+    1008: 4040bde8 pop {r6, lr}
+    100c: 1eff2fe1 bx lr
+    1010: 02001014 .word 0x02001014
+    1014: 00000000 .word 0x00000000
+
+00001018 <_start>:
+    1018: fff7 f2ff bl 1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 1eff2fe1 bx lr
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Richard Earnshaw
On Mon, 2009-02-23 at 12:40 +0100, Christophe LYON wrote:

> Hi all,
>
> Following our recent discussion, I propose the attached patch to fix
> big-endian / be8 stubs encoding issues.
>
> I am not particularly proud of the way it's now done, but it does the job.
> In short, the Thumb instructions in the stubs now use 1 entry per
> instruction (instead of 2 instr per entry), but this implies that the
> encoding functions know the exact layout of each stub, so it makes
> maintenance a bit more painful (I added some comments to warn about that).
>
> I have added one more test (farcall-thumb-arm-be8).
>
> Once this is OK, I'll come back to my original patches to improve
> PIC/PLT support.
>

I think the cleanest way of doing this is to encode each entry as a
tupple -- the bit pattern and a type marker, then we have macros
THUMB16_INSN() THUMB32_INSN(), ARM_INSN() and DATA_WORD() which are used
to initialize the arrays.  You then get an instruction block that looks
like:

#define THUMB16_INSN(X) {X, 1}
#define THUMB32_INSN(X) {X, 2}
#define ARM_INSN(X)     {X, 3}
#define DATA_WORD(X)    {X, 4}

struct insn_sequence
{
  bfd_vma  data;
  uint8_t  type;
};

 static const insn_sequence elf32_arm_stub_long_branch_thumb_only[] =
   {
        THUMB16_INSN(0xb540),  /* push { r6, lr} */
        THUMB16_INSN(0x4e02),  /* ldr r6, [pc, #8] */
        DATA_WORD(0)
   };

Then there is some common code that takes such a block and copies it out
to memory, setting any appropriate mapping symbols as appropriate.

The encoding is slightly expensive (you only need 2 bits to represent
the 4 types of data that can exist in the array, which wastes at least
30 bits for every instruction in the list, but there aren't that many
stubs and the risk of errors over having separate arrays for the
instructions and the map is significantly higher.

R.

Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Paul Brook
On Monday 23 February 2009, Richard Earnshaw wrote:

> On Mon, 2009-02-23 at 12:40 +0100, Christophe LYON wrote:
> > Hi all,
> >
> > Following our recent discussion, I propose the attached patch to fix
> > big-endian / be8 stubs encoding issues.
> >
> > I am not particularly proud of the way it's now done, but it does the
> > job. In short, the Thumb instructions in the stubs now use 1 entry per
> > instruction (instead of 2 instr per entry), but this implies that the
> > encoding functions know the exact layout of each stub, so it makes
> > maintenance a bit more painful (I added some comments to warn about
> > that).
> >
> > I have added one more test (farcall-thumb-arm-be8).
> >
> > Once this is OK, I'll come back to my original patches to improve
> > PIC/PLT support.
>
> I think the cleanest way of doing this is to encode each entry as a
> tupple -- the bit pattern and a type marker, then we have macros
> THUMB16_INSN() THUMB32_INSN(), ARM_INSN() and DATA_WORD() which are used
> to initialize the arrays.  You then get an instruction block that looks
> like:
>
> #define THUMB16_INSN(X) {X, 1}
> #define THUMB32_INSN(X) {X, 2}
> #define ARM_INSN(X)     {X, 3}
> #define DATA_WORD(X)    {X, 4}

I agree.

You could be even cleverer by having ADDR_ABS/ADDR_PIC relocation-like
entries, and remove all the stub specific knowledge from the code.

> The encoding is slightly expensive (you only need 2 bits to represent
> the 4 types of data that can exist in the array, which wastes at least
> 30 bits for every instruction in the list, but there aren't that many
> stubs and the risk of errors over having separate arrays for the
> instructions and the map is significantly higher.

This is host data, so I don't think we care about a few bits.
I suspect you'll find the extra space used by the array is less than the code
required to populate the stubs individually.

Paul
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Christophe Lyon
Hi!
>
> You could be even cleverer by having ADDR_ABS/ADDR_PIC relocation-like
> entries, and remove all the stub specific knowledge from the code.
>

I was about to submit a new version when I saw your suggestion.
So I took a bit more time, and here is my new proposal.

Christophe.

2009-02-20  Christophe Lyon  <[hidden email]>

        bfd/
        * elf32-arm.c (stub_insn_type): New type.
        (stub_reloc_type): Likewise.
        (insn_sequence): Likewise.
        (elf32_arm_stub_long_branch_any_any): Encode using insn_sequence.
        (elf32_arm_stub_long_branch_v4t_arm_thumb): Likewise.
        (elf32_arm_stub_long_branch_thumb_only): Likewise.
        (elf32_arm_stub_long_branch_v4t_thumb_arm): Likewise.
        (elf32_arm_stub_short_branch_v4t_thumb_arm): Likewise.
        (elf32_arm_stub_long_branch_any_any_pic): Likewise.
        (elf32_arm_stub_hash_entry): Add new helper fields.
        (stub_hash_newfunc): Initialize these new fields.
        (arm_build_one_stub): Encode Arm and Thumb instructions separately
        to take endianness into account.
        (arm_size_one_stub): Compute size of stubs using insn_sequence.
        (arm_map_one_stub): Code is now more generic, thanks to
        insn_sequence.

        testsuite/
        * ld-arm/arm-elf.exp: Add new farcall-thumb-arm-be8 test.
        * ld-arm/farcall-thumb-arm-be8.d: New expected result.
        * ld-arm/farcall-arm-arm-be8.d: Replace wildcards by instructions.

Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.173
diff -u -p -r1.173 elf32-arm.c
--- bfd/elf32-arm.c 23 Feb 2009 10:03:46 -0000 1.173
+++ bfd/elf32-arm.c 23 Feb 2009 17:52:43 -0000
@@ -2010,63 +2010,92 @@ static const bfd_vma elf32_arm_symbian_p
 #define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
 #define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
 
+enum stub_insn_type
+  {
+    THUMB16_TYPE = 1,
+    THUMB32_TYPE,
+    ARM_TYPE,
+    DATA_TYPE
+  };
+
+enum stub_reloc_type
+  {
+    STUB_RELOC_NONE = 0,
+    STUB_RELOC_ABS,
+    STUB_RELOC_PIC,
+  };
+
+#define THUMB16_INSN(X)    {(X), THUMB16_TYPE, R_ARM_NONE, 0}
+#define THUMB32_INSN(X)    {(X), THUMB32_TYPE, R_ARM_NONE, 0}
+#define ARM_INSN(X)        {(X), ARM_TYPE, R_ARM_NONE, 0}
+#define ARM_REL_INSN(X, Z) {(X), ARM_TYPE, R_ARM_JUMP24, (Z)}
+#define DATA_WORD(X,Y,Z)   {(X), DATA_TYPE, (Y), (Z)}
+
+typedef struct
+{
+  bfd_vma data;
+  enum stub_insn_type type;
+  enum stub_reloc_type reloc_type;
+  int reloc_addend;
+}  insn_sequence;
+
 /* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
    to reach the stub if necessary.  */
-static const bfd_vma elf32_arm_stub_long_branch_any_any[] =
+static const insn_sequence elf32_arm_stub_long_branch_any_any[] =
   {
-    0xe51ff004,         /* ldr   pc, [pc, #-4] */
-    0x00000000,         /* dcd   R_ARM_ABS32(X) */
+    ARM_INSN(0xe51ff004),            /* ldr   pc, [pc, #-4] */
+    DATA_WORD(0, R_ARM_ABS32, 0),    /* dcd   R_ARM_ABS32(X) */
   };
 
 /* V4T Arm -> Thumb long branch stub. Used on V4T where blx is not
    available.  */
-static const bfd_vma elf32_arm_stub_long_branch_v4t_arm_thumb[] =
+static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb[] =
   {
-    0xe59fc000,         /* ldr   ip, [pc, #0] */
-    0xe12fff1c,         /* bx    ip */
-    0x00000000,         /* dcd   R_ARM_ABS32(X) */
+    ARM_INSN(0xe59fc000),            /* ldr   ip, [pc, #0] */
+    ARM_INSN(0xe12fff1c),            /* bx    ip */
+    DATA_WORD(0, R_ARM_ABS32, 0),    /* dcd   R_ARM_ABS32(X) */
   };
 
 /* Thumb -> Thumb long branch stub. Used on architectures which
    support only this mode, or on V4T where it is expensive to switch
    to ARM.  */
-static const bfd_vma elf32_arm_stub_long_branch_thumb_only[] =
+static const insn_sequence elf32_arm_stub_long_branch_thumb_only[] =
   {
-    0x4802b401,         /* push {r0} */
-                        /* ldr  r0, [pc, #8] */
-    0xbc014684,         /* mov  ip, r0 */
-                        /* pop  {r0} */
-    0xbf004760,         /* bx   ip */
-                        /* nop */
-    0x00000000,         /* dcd  R_ARM_ABS32(X) */
+    THUMB16_INSN(0xb401),             /* push {r0} */
+    THUMB16_INSN(0x4802),             /* ldr  r0, [pc, #8] */
+    THUMB16_INSN(0x4684),             /* mov  ip, r0 */
+    THUMB16_INSN(0xbc01),             /* pop  {r0} */
+    THUMB16_INSN(0x4760),             /* bx   ip */
+    THUMB16_INSN(0xbf00),             /* nop */
+    DATA_WORD(0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
   };
 
 /* V4T Thumb -> ARM long branch stub. Used on V4T where blx is not
    available.  */
-static const bfd_vma elf32_arm_stub_long_branch_v4t_thumb_arm[] =
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] =
   {
-    0x46c04778,         /* bx   pc */
-                        /* nop   */
-    0xe51ff004,         /* ldr   pc, [pc, #-4] */
-    0x00000000,         /* dcd   R_ARM_ABS32(X) */
+    THUMB16_INSN(0x4778),             /* bx   pc */
+    THUMB16_INSN(0x46c0),             /* nop   */
+    ARM_INSN(0xe51ff004),             /* ldr   pc, [pc, #-4] */
+    DATA_WORD(0, R_ARM_ABS32, 0),     /* dcd   R_ARM_ABS32(X) */
   };
 
 /* V4T Thumb -> ARM short branch stub. Shorter variant of the above
    one, when the destination is close enough.  */
-static const bfd_vma elf32_arm_stub_short_branch_v4t_thumb_arm[] =
+static const insn_sequence elf32_arm_stub_short_branch_v4t_thumb_arm[] =
   {
-    0x46c04778,         /* bx   pc */
-                        /* nop   */
-    0xea000000,         /* b    (X) */
+    THUMB16_INSN(0x4778),             /* bx   pc */
+    THUMB16_INSN(0x46c0),             /* nop   */
+    ARM_REL_INSN(0xea000000, -8),     /* b    (X-8) */
   };
 
 /* ARM/Thumb -> ARM/Thumb long branch stub, PIC. On V5T and above, use
    blx to reach the stub if necessary.  */
-static const bfd_vma elf32_arm_stub_long_branch_any_any_pic[] =
+static const insn_sequence elf32_arm_stub_long_branch_any_any_pic[] =
   {
-    0xe59fc000,         /* ldr   r12, [pc] */
-    0xe08ff00c,         /* add   pc, pc, ip */
-    0x00000000,         /* dcd   R_ARM_REL32(X-4) */
+    ARM_INSN(0xe59fc000),             /* ldr   r12, [pc] */
+    ARM_INSN(0xe08ff00c),             /* add   pc, pc, ip */
+    DATA_WORD(0, R_ARM_REL32, -4),    /* dcd   R_ARM_REL32(X-4) */
   };
 
 /* Section name for stubs is the associated section name plus this
@@ -2100,7 +2129,14 @@ struct elf32_arm_stub_hash_entry
   bfd_vma target_value;
   asection *target_section;
 
+  /* The stub type.  */
   enum elf32_arm_stub_type stub_type;
+  /* Its encoding size in bytes.  */
+  int stub_size;
+  /* Its template.  */
+  const insn_sequence *stub_template;
+  /* The size of the template (number of entries).  */
+  int stub_template_size;
 
   /* The symbol table entry, if any, that this was derived from.  */
   struct elf32_arm_link_hash_entry *h;
@@ -2469,6 +2505,9 @@ stub_hash_newfunc (struct bfd_hash_entry
       eh->target_value = 0;
       eh->target_section = NULL;
       eh->stub_type = arm_stub_none;
+      eh->stub_size = 0;
+      eh->stub_template = NULL;
+      eh->stub_template_size = 0;
       eh->h = NULL;
       eh->id_sec = NULL;
     }
@@ -3108,9 +3147,11 @@ arm_build_one_stub (struct bfd_hash_entr
   bfd_vma sym_value;
   int template_size;
   int size;
-  const bfd_vma *template;
+  const insn_sequence *template;
   int i;
   struct elf32_arm_link_hash_table * globals;
+  int stub_reloc_idx = -1;
+  int stub_reloc_offset;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
@@ -3136,101 +3177,61 @@ arm_build_one_stub (struct bfd_hash_entr
        + stub_entry->target_section->output_offset
        + stub_entry->target_section->output_section->vma);
 
-  switch (stub_entry->stub_type)
-    {
-    case arm_stub_long_branch_any_any:
-      template = elf32_arm_stub_long_branch_any_any;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
-      break;
-    case arm_stub_long_branch_v4t_arm_thumb:
-      template =  elf32_arm_stub_long_branch_v4t_arm_thumb;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
-      break;
-    case arm_stub_long_branch_thumb_only:
-      template =  elf32_arm_stub_long_branch_thumb_only;
-      template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
-      break;
-    case arm_stub_long_branch_v4t_thumb_arm:
-      template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
-      break;
-    case arm_stub_short_branch_v4t_thumb_arm:
-      template =  elf32_arm_stub_short_branch_v4t_thumb_arm;
-      template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
-      break;
-    case arm_stub_long_branch_any_any_pic:
-      template = elf32_arm_stub_long_branch_any_any_pic;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
-      break;
-    default:
-      BFD_FAIL ();
-      return FALSE;
-    }
+  template = stub_entry->stub_template;
+  template_size = stub_entry->stub_template_size;
 
   size = 0;
-  for (i = 0; i < (template_size / 4); i++)
+  for (i = 0; i < template_size; i++)
     {
-      /* A 0 pattern is a placeholder, every other pattern is an
- instruction.  */
-      if (template[i] != 0)
- put_arm_insn (globals, stub_bfd, template[i], loc + size);
-      else
- bfd_put_32 (stub_bfd, template[i], loc + size);
+      switch(template[i].type)
+ {
+ case THUMB16_TYPE:
+  put_thumb_insn (globals, stub_bfd, template[i].data, loc + size);
+  size += 2;
+  break;
 
-      size += 4;
+ case ARM_TYPE:
+  put_arm_insn (globals, stub_bfd, template[i].data, loc + size);
+  /* Handle cases where the target is encoded within the
+     instruction.  */
+  if (template[i].reloc_type == R_ARM_JUMP24)
+    {
+      stub_reloc_idx = i;
+      stub_reloc_offset = size;
+    }
+  size += 4;
+  break;
+
+ case DATA_TYPE:
+  bfd_put_32 (stub_bfd, template[i].data, loc + size);
+  stub_reloc_idx = i;
+  stub_reloc_offset = size;
+  size += 4;
+  break;
+
+ default:
+  BFD_FAIL ();
+  return FALSE;
+ }
     }
+
   stub_sec->size += size;
 
+  /* Stub size has already been computed in arm_size_one_stub. Check
+     consistency.  */
+  BFD_ASSERT (size == stub_entry->stub_size);
+
   /* Destination is Thumb. Force bit 0 to 1 to reflect this.  */
   if (stub_entry->st_type == STT_ARM_TFUNC)
     sym_value |= 1;
 
-  switch (stub_entry->stub_type)
-    {
-    case arm_stub_long_branch_any_any:
-      _bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
- stub_bfd, stub_sec, stub_sec->contents,
- stub_entry->stub_offset + 4, sym_value, 0);
-      break;
-    case arm_stub_long_branch_v4t_arm_thumb:
-      _bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
- stub_bfd, stub_sec, stub_sec->contents,
- stub_entry->stub_offset + 8, sym_value, 0);
-      break;
-    case arm_stub_long_branch_thumb_only:
-      _bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
- stub_bfd, stub_sec, stub_sec->contents,
- stub_entry->stub_offset + 12, sym_value, 0);
-      break;
-    case arm_stub_long_branch_v4t_thumb_arm:
-      _bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
- stub_bfd, stub_sec, stub_sec->contents,
- stub_entry->stub_offset + 8, sym_value, 0);
-      break;
-    case arm_stub_short_branch_v4t_thumb_arm:
-      {
- long int rel_offset;
- static const insn32 t2a3_b_insn = 0xea000000;
-
- rel_offset = sym_value - (stub_addr + 8 + 4);
+  /* Assume there is one and only one entry to relocate in each stub.  */
+  BFD_ASSERT (stub_reloc_idx != -1);
 
- put_arm_insn (globals, stub_bfd,
-      (bfd_vma) t2a3_b_insn | ((rel_offset >> 2) & 0x00FFFFFF),
-      loc + 4);
-      }
-      break;
-
-    case arm_stub_long_branch_any_any_pic:
-      /* We want the value relative to the address 8 bytes from the
- start of the stub.  */
-      _bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_REL32),
- stub_bfd, stub_sec, stub_sec->contents,
- stub_entry->stub_offset + 8, sym_value, -4);
-      break;
-    default:
-      BFD_FAIL();
-      break;
-    }
+  _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].reloc_type),
+    stub_bfd, stub_sec, stub_sec->contents,
+    stub_entry->stub_offset + stub_reloc_offset,
+    sym_value, template[stub_reloc_idx].reloc_addend);
 
   return TRUE;
 }
@@ -3244,7 +3245,7 @@ arm_size_one_stub (struct bfd_hash_entry
 {
   struct elf32_arm_stub_hash_entry *stub_entry;
   struct elf32_arm_link_hash_table *htab;
-  const bfd_vma *template;
+  const insn_sequence *template;
   int template_size;
   int size;
   int i;
@@ -3257,27 +3258,28 @@ arm_size_one_stub (struct bfd_hash_entry
     {
     case arm_stub_long_branch_any_any:
       template =  elf32_arm_stub_long_branch_any_any;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
+      template_size = sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (insn_sequence);
+
       break;
     case arm_stub_long_branch_v4t_arm_thumb:
       template =  elf32_arm_stub_long_branch_v4t_arm_thumb;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
+      template_size = sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (insn_sequence);
       break;
     case arm_stub_long_branch_thumb_only:
       template =  elf32_arm_stub_long_branch_thumb_only;
-      template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
+      template_size = sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (insn_sequence);
       break;
     case arm_stub_long_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_long_branch_v4t_thumb_arm;
-      template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+      template_size = sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (insn_sequence);
       break;
     case arm_stub_short_branch_v4t_thumb_arm:
       template =  elf32_arm_stub_short_branch_v4t_thumb_arm;
-      template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
+      template_size = sizeof (elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (insn_sequence);
       break;
     case arm_stub_long_branch_any_any_pic:
       template = elf32_arm_stub_long_branch_any_any_pic;
-      template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
+      template_size = sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (insn_sequence);
       break;
     default:
       BFD_FAIL ();
@@ -3286,10 +3288,35 @@ arm_size_one_stub (struct bfd_hash_entry
     }
 
   size = 0;
-  for (i = 0; i < (template_size / 4); i++)
-      size += 4;
+  for (i = 0; i < template_size; i++)
+    {
+      switch(template[i].type)
+ {
+ case THUMB16_TYPE:
+  size += 2;
+  break;
+
+ case ARM_TYPE:
+  size += 4;
+  break;
+
+ case DATA_TYPE:
+  size += 4;
+  break;
+
+ default:
+  BFD_FAIL ();
+  return FALSE;
+ }
+    }
+
+  stub_entry->stub_size = size;
+  stub_entry->stub_template = template;
+  stub_entry->stub_template_size = template_size;
+
   size = (size + 7) & ~7;
   stub_entry->stub_sec->size += size;
+
   return TRUE;
 }
 
@@ -11665,6 +11692,11 @@ arm_map_one_stub (struct bfd_hash_entry
   bfd_vma addr;
   char *stub_name;
   output_arch_syminfo *osi;
+  const insn_sequence *template;
+  enum stub_insn_type prev_type;
+  int size;
+  int i;
+  enum map_symbol_type sym_type;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
@@ -11683,62 +11715,70 @@ arm_map_one_stub (struct bfd_hash_entry
   addr = (bfd_vma) stub_entry->stub_offset;
   stub_name = stub_entry->output_name;
 
-  switch (stub_entry->stub_type)
+  template = stub_entry->stub_template;
+  switch(template[0].type)
     {
-    case arm_stub_long_branch_any_any:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 8))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 4))
- return FALSE;
-      break;
-    case arm_stub_long_branch_v4t_arm_thumb:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 8))
- return FALSE;
-      break;
-    case arm_stub_long_branch_thumb_only:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 16))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 12))
- return FALSE;
-      break;
-    case arm_stub_long_branch_v4t_thumb_arm:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 20))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 8))
+    case ARM_TYPE:
+      if (!elf32_arm_output_stub_sym (osi, stub_name, addr, stub_entry->stub_size))
  return FALSE;
       break;
-    case arm_stub_short_branch_v4t_thumb_arm:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 8))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
- return FALSE;
-      break;
-    case arm_stub_long_branch_any_any_pic:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
- return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 8))
+    case THUMB16_TYPE:
+      if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1,
+      stub_entry->stub_size))
  return FALSE;
       break;
     default:
       BFD_FAIL ();
     }
 
+  prev_type = DATA_TYPE;
+  size = 0;
+  for (i = 0; i < stub_entry->stub_template_size; i++)
+    {
+      switch(template[i].type)
+ {
+ case ARM_TYPE:
+  sym_type = ARM_MAP_ARM;
+  break;
+
+ case THUMB16_TYPE:
+  sym_type = ARM_MAP_THUMB;
+  break;
+
+ case DATA_TYPE:
+  sym_type = ARM_MAP_DATA;
+  break;
+
+ default:
+  BFD_FAIL ();
+ }
+
+      if (template[i].type != prev_type)
+ {
+  prev_type = template[i].type;
+  if (!elf32_arm_output_map_sym (osi, sym_type, addr + size))
+    return FALSE;
+ }
+
+      switch(template[i].type)
+ {
+ case ARM_TYPE:
+  size += 4;
+  break;
+
+ case THUMB16_TYPE:
+  size += 2;
+  break;
+
+ case DATA_TYPE:
+  size += 4;
+  break;
+
+ default:
+  BFD_FAIL ();
+ }
+    }
+
   return TRUE;
 }
 
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.45
diff -u -p -r1.45 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 23 Feb 2009 10:03:46 -0000 1.45
+++ ld/testsuite/ld-arm/arm-elf.exp 23 Feb 2009 17:52:46 -0000
@@ -297,6 +297,9 @@ set armeabitests {
     {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
      "farcall-thumb-arm"}
+    {"Thumb-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB --be8" "-W -EB" {farcall-thumb-arm.s}
+     {{objdump -d farcall-thumb-arm-be8.d}}
+     "farcall-thumb-arm"}
     {"Thumb-ARM (short) call" "-Ttext 0x1000 --section-start .foo=0x0002014" "-W" {farcall-thumb-arm-short.s}
      {{objdump -d farcall-thumb-arm-short.d}}
      "farcall-thumb-arm-short"}
Index: ld/testsuite/ld-arm/farcall-arm-arm-be8.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/farcall-arm-arm-be8.d,v
retrieving revision 1.2
diff -u -p -r1.2 farcall-arm-arm-be8.d
--- ld/testsuite/ld-arm/farcall-arm-arm-be8.d 25 Jun 2008 14:28:48 -0000 1.2
+++ ld/testsuite/ld-arm/farcall-arm-arm-be8.d 23 Feb 2009 17:52:46 -0000
@@ -3,12 +3,12 @@
 Disassembly of section .text:
 
 00001000 <__bar_veneer>:
-    1000: 04f01fe5 .*
+    1000: 04f01fe5 ldr pc, \[pc, #-4\] ; 1004 <__bar_veneer\+0x4>
     1004: 02001020 .word 0x02001020
 
 00001008 <_start>:
-    1008: fcffffeb .*
+    1008: fcffffeb bl 1000 <__bar_veneer>
 Disassembly of section .foo:
 
 02001020 <bar>:
- 2001020: 1eff2fe1 .*
+ 2001020: 1eff2fe1 bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
diff -N ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/farcall-thumb-arm-be8.d 23 Feb 2009 17:52:46 -0000
@@ -0,0 +1,17 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+    1000: 7847       bx pc
+    1002: c046       nop.*
+    1004: 04f01fe5 ldr pc, \[pc, #-4\] ; 1008 <__bar_from_thumb\+0x8>
+    1008: 02001014 .word 0x02001014
+    100c: 00000000 .word 0x00000000
+
+00001010 <_start>:
+    1010: fff7 f6ff bl 1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: 1eff2fe1 bx lr
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Daniel Jacobowitz-2
On Mon, Feb 23, 2009 at 06:55:51PM +0100, Christophe LYON wrote:
> Hi!
>>
>> You could be even cleverer by having ADDR_ABS/ADDR_PIC relocation-like  
>> entries, and remove all the stub specific knowledge from the code.
>>
>
> I was about to submit a new version when I saw your suggestion.
> So I took a bit more time, and here is my new proposal.

This is OK, thank you!  I've looked through it, I did not see any
problems, and it's much nicer to work with.

>      case arm_stub_long_branch_any_any:
>        template =  elf32_arm_stub_long_branch_any_any;
> -      template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
> +      template_size = sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (insn_sequence);
> +

FYI this is "ARRAY_SIZE (elf32_arm_stub_long_branch_any_any)".

--
Daniel Jacobowitz
CodeSourcery
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Daniel Jacobowitz-2
On Mon, Feb 23, 2009 at 01:27:14PM -0500, Daniel Jacobowitz wrote:

> On Mon, Feb 23, 2009 at 06:55:51PM +0100, Christophe LYON wrote:
> > Hi!
> >>
> >> You could be even cleverer by having ADDR_ABS/ADDR_PIC relocation-like  
> >> entries, and remove all the stub specific knowledge from the code.
> >>
> >
> > I was about to submit a new version when I saw your suggestion.
> > So I took a bit more time, and here is my new proposal.
>
> This is OK, thank you!  I've looked through it, I did not see any
> problems, and it's much nicer to work with.

Since I'm working on the stubs right now, I hope you don't mind that I
checked this in for you.  The new tests pass both before and after;
I added this additional patch with a big-endian test that fails after.

BE8 and little endian code have equivalent layout, even in Thumb; it's
big-endian that is the odd duck out.

--
Daniel Jacobowitz
CodeSourcery

2009-02-23  Daniel Jacobowitz  <[hidden email]>

        ld/testsuite/
        * ld-arm/arm-elf.exp (armeabitests): Run new tests.  Correct BE8 output
        filename.
        * ld-arm/farcall-arm-arm-be.d, ld-arm/farcall-thumb-arm-be.d: New.

Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
--- ld/testsuite/ld-arm/arm-elf.exp.orig 2009-02-23 13:44:02.000000000 -0800
+++ ld/testsuite/ld-arm/arm-elf.exp 2009-02-23 13:40:02.000000000 -0800
@@ -267,6 +267,9 @@ set armeabitests {
     {"ARM-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001020 -EB --be8" "-EB" {farcall-arm-arm.s}
      {{objdump -d farcall-arm-arm-be8.d}}
      "farcall-arm-arm-be8"}
+    {"ARM-ARM farcall (BE)" "-Ttext 0x1000 --section-start .foo=0x2001020 -EB" "-EB" {farcall-arm-arm.s}
+     {{objdump -d farcall-arm-arm-be.d}}
+     "farcall-arm-arm-be"}
 
     {"ARM-Thumb farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "" {farcall-arm-thumb.s}
      {{objdump -d farcall-arm-thumb.d}}
@@ -299,7 +302,10 @@ set armeabitests {
      "farcall-thumb-arm"}
     {"Thumb-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB --be8" "-W -EB" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm-be8.d}}
-     "farcall-thumb-arm"}
+     "farcall-thumb-arm-be8"}
+    {"Thumb-ARM farcall (BE)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB" "-W -EB" {farcall-thumb-arm.s}
+     {{objdump -d farcall-thumb-arm-be.d}}
+     "farcall-thumb-arm-be"}
     {"Thumb-ARM (short) call" "-Ttext 0x1000 --section-start .foo=0x0002014" "-W" {farcall-thumb-arm-short.s}
      {{objdump -d farcall-thumb-arm-short.d}}
      "farcall-thumb-arm-short"}
Index: ld/testsuite/ld-arm/farcall-arm-arm-be.d
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-arm/farcall-arm-arm-be.d 2009-02-23 13:41:57.000000000 -0800
@@ -0,0 +1,14 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_veneer>:
+    1000: e51ff004 ldr pc, \[pc, #-4\] ; 1004 <__bar_veneer\+0x4>
+    1004: 02001020 .word 0x02001020
+
+00001008 <_start>:
+    1008: ebfffffc bl 1000 <__bar_veneer>
+Disassembly of section .foo:
+
+02001020 <bar>:
+ 2001020: e12fff1e bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-arm-be.d
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-arm/farcall-thumb-arm-be.d 2009-02-23 13:42:39.000000000 -0800
@@ -0,0 +1,17 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+    1000: 4778       bx pc
+    1002: 46c0       nop.*
+    1004: e51ff004 ldr pc, \[pc, #-4\] ; 1008 <__bar_from_thumb\+0x8>
+    1008: 02001014 .word 0x02001014
+    100c: 00000000 .word 0x00000000
+
+00001010 <_start>:
+    1010: f7ff fff6 bl 1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+02001014 <bar>:
+ 2001014: e12fff1e bx lr
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Christophe Lyon

>
> Since I'm working on the stubs right now, I hope you don't mind that I
> checked this in for you.
No problem. Sorry for the timezone difference :-)

 > The new tests pass both before and after;
> I added this additional patch with a big-endian test that fails after.
I don't understand: I have just tried and the 2 new tests pass here
(arm-none-eabi).

> BE8 and little endian code have equivalent layout, even in Thumb; it's
> big-endian that is the odd duck out.
Sorry I had overlooked at this (we don't use this mode at all, here).

What confused me is that objdump -d dumps opcodes in a different order
in the BE8 case. Maybe it could be enhanced to make use of the BE8 EABI
flag?

Christophe.



Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Daniel Jacobowitz-2
On Tue, Feb 24, 2009 at 02:37:30PM +0100, Christophe LYON wrote:
> > The new tests pass both before and after;
>> I added this additional patch with a big-endian test that fails after.
> I don't understand: I have just tried and the 2 new tests pass here  
> (arm-none-eabi).

Really?  I definitely got failures on farcall-thumb-arm-be.d before
applying your patch.

> What confused me is that objdump -d dumps opcodes in a different order in
> the BE8 case. Maybe it could be enhanced to make use of the BE8 EABI  
> flag?

That would make sense to me, and the *-be8.d files could go away then.
Paul, Richard, what do you think?

--
Daniel Jacobowitz
CodeSourcery
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Christophe Lyon
On 24.02.2009 15:20, Daniel Jacobowitz wrote:
> On Tue, Feb 24, 2009 at 02:37:30PM +0100, Christophe LYON wrote:
>>> The new tests pass both before and after;
>>> I added this additional patch with a big-endian test that fails after.
>> I don't understand: I have just tried and the 2 new tests pass here  
>> (arm-none-eabi).
>
> Really?  I definitely got failures on farcall-thumb-arm-be.d before
> applying your patch.

You wrote that the new big-endian test fails after. Did you mean "before"?

Christophe.


Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Daniel Jacobowitz-2
On Tue, Feb 24, 2009 at 03:22:18PM +0100, Christophe LYON wrote:
> You wrote that the new big-endian test fails after. Did you mean "before"?

Whoops!  Yes, I did.  Sorry about that.

--
Daniel Jacobowitz
CodeSourcery
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Paul Brook
In reply to this post by Daniel Jacobowitz-2
> > What confused me is that objdump -d dumps opcodes in a different order in
> > the BE8 case. Maybe it could be enhanced to make use of the BE8 EABI
> > flag?
>
> That would make sense to me, and the *-be8.d files could go away then.
> Paul, Richard, what do you think?

I agree. IMHO the current be8 objdump behavior is a bug.

Paul
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Christophe Lyon
On 24.02.2009 15:48, Paul Brook wrote:

>>> What confused me is that objdump -d dumps opcodes in a different order in
>>> the BE8 case. Maybe it could be enhanced to make use of the BE8 EABI
>>> flag?
>> That would make sense to me, and the *-be8.d files could go away then.
>> Paul, Richard, what do you think?
>
> I agree. IMHO the current be8 objdump behavior is a bug.
>
> Paul
>
Hi,

I propose the attached patch.
I did not remove the arm-be8.d test because there is no non-be8 variant.

Christophe.



2009-03-13  Christophe Lyon  <[hidden email]>

        opcodes/
        * arm-dis.c (print_insn): Print BE8 opcodes in little endianness.

        ld/testsuite/
        * ld-arm/arm-elf.exp: BE8 tests expect the same output as the
        default ones.
        * ld-arm/arm-be8.d: Print opcodes in little endian.
        * ld-arm/farcall-thumb-arm-be8.d: Removed useless expected result.
        * ld-arm/farcall-arm-arm-be8.d: Likewise.


Index: ld/testsuite/ld-arm/arm-be8.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-be8.d,v
retrieving revision 1.2
diff -u -p -r1.2 arm-be8.d
--- ld/testsuite/ld-arm/arm-be8.d 7 Jul 2008 19:00:21 -0000 1.2
+++ ld/testsuite/ld-arm/arm-be8.d 13 Mar 2009 13:55:38 -0000
@@ -4,13 +4,13 @@
 Disassembly of section .text:
 
 00008000 <arm>:
-    8000: 0000a0e3 mov r0, #0 ; 0x0
-    8004: 1eff2fe1 bx lr
+    8000: e3a00000 mov r0, #0 ; 0x0
+    8004: e12fff1e bx lr
 
 00008008 <thumb>:
-    8008: c046       nop \(mov r8, r8\)
-    800a: 7047       bx lr
-    800c: fff7 fcff bl 8008 <thumb>
+    8008: 46c0       nop \(mov r8, r8\)
+    800a: 4770       bx lr
+    800c: f7ff fffc bl 8008 <thumb>
 
 00008010 <data>:
     8010: 12345678 .word 0x12345678
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.51
diff -u -p -r1.51 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 6 Mar 2009 08:57:58 -0000 1.51
+++ ld/testsuite/ld-arm/arm-elf.exp 13 Mar 2009 13:55:38 -0000
@@ -265,7 +265,7 @@ set armeabitests {
      {{objdump -d farcall-arm-arm-pic-veneer.d}}
      "farcall-arm-arm-pic-veneer"}
     {"ARM-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001020 -EB --be8" "-EB" {farcall-arm-arm.s}
-     {{objdump -d farcall-arm-arm-be8.d}}
+     {{objdump -d farcall-arm-arm.d}}
      "farcall-arm-arm-be8"}
     {"ARM-ARM farcall (BE)" "-Ttext 0x1000 --section-start .foo=0x2001020 -EB" "-EB" {farcall-arm-arm.s}
      {{objdump -d farcall-arm-arm.d}}
@@ -307,7 +307,7 @@ set armeabitests {
      {{objdump -d farcall-thumb-arm.d}}
      "farcall-thumb-arm"}
     {"Thumb-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB --be8" "-W -EB" {farcall-thumb-arm.s}
-     {{objdump -d farcall-thumb-arm-be8.d}}
+     {{objdump -d farcall-thumb-arm.d}}
      "farcall-thumb-arm-be8"}
     {"Thumb-ARM farcall (BE)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB" "-W -EB" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
Index: ld/testsuite/ld-arm/farcall-arm-arm-be8.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-arm-arm-be8.d
diff -N ld/testsuite/ld-arm/farcall-arm-arm-be8.d
--- ld/testsuite/ld-arm/farcall-arm-arm-be8.d 24 Feb 2009 22:43:10 -0000 1.4
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,15 +0,0 @@
-.*:     file format .*
-
-Disassembly of section .text:
-
-00001000 <_start>:
-    1000: 000000eb bl 1008 <__bar_veneer>
-    1004: 00000000 andeq r0, r0, r0
-
-00001008 <__bar_veneer>:
-    1008: 04f01fe5 ldr pc, \[pc, #-4\] ; 100c <__bar_veneer\+0x4>
-    100c: 02001020 .word 0x02001020
-Disassembly of section .foo:
-
-02001020 <bar>:
- 2001020: 1eff2fe1 bx lr
Index: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
===================================================================
RCS file: ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
diff -N ld/testsuite/ld-arm/farcall-thumb-arm-be8.d
--- ld/testsuite/ld-arm/farcall-thumb-arm-be8.d 24 Feb 2009 22:43:10 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,19 +0,0 @@
-.*:     file format .*
-
-Disassembly of section .text:
-
-00001000 <_start>:
-    1000: 00f0 02f8 bl 1008 <__bar_from_thumb>
-    1004: 0000       lsls r0, r0, #0
- \.\.\.
-
-00001008 <__bar_from_thumb>:
-    1008: 7847       bx pc
-    100a: c046       nop.*
-    100c: 04f01fe5 ldr pc, \[pc, #-4\] ; 1010 <__bar_from_thumb\+0x8>
-    1010: 02001014 .word 0x02001014
-    1014: 00000000 .word 0x00000000
-Disassembly of section .foo:
-
-02001014 <bar>:
- 2001014: 1eff2fe1 bx lr
Index: opcodes/arm-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/arm-dis.c,v
retrieving revision 1.93
diff -u -p -r1.93 arm-dis.c
--- opcodes/arm-dis.c 23 Feb 2009 14:58:34 -0000 1.93
+++ opcodes/arm-dis.c 13 Mar 2009 13:55:41 -0000
@@ -4111,7 +4111,11 @@ print_insn (bfd_vma pc, struct disassemb
   if (force_thumb)
     is_thumb = TRUE;
 
-  info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
+  if (is_data)
+    info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
+  else
+    info->display_endian = little_code ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
+
   info->bytes_per_line = 4;
 
   if (is_data)
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Nick Clifton
Hi Christophe,

> I propose the attached patch.
> I did not remove the arm-be8.d test because there is no non-be8 variant.

Approved - please apply.

Cheers
   Nick


Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Daniel Jacobowitz-2
In reply to this post by Christophe Lyon
On Fri, Mar 13, 2009 at 03:16:06PM +0100, Christophe LYON wrote:
> I propose the attached patch.

Thank you!

--
Daniel Jacobowitz
CodeSourcery
Reply | Threaded
Open this post in threaded view
|

Re: ARM long branch stubs: be8

Christophe Lyon
In reply to this post by Nick Clifton
On 01.04.2009 17:31, Nick Clifton wrote:
> Hi Christophe,
>
>> I propose the attached patch.
>> I did not remove the arm-be8.d test because there is no non-be8 variant.
>
> Approved - please apply.
>

Thanks, committed.

Christophe