This is the mail archive of the binutils-cvs@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]

[binutils-gdb] [ARM] Purecode compatible long branch veneer for M-profile targets with MOVW.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d5a67c02901c0abe946546f2b3b1a3b67a876136

commit d5a67c02901c0abe946546f2b3b1a3b67a876136
Author: Andre Vieria <andre.simoesdiasvieira@arm.com>
Date:   Tue Jul 5 11:39:06 2016 +0100

    [ARM] Purecode compatible long branch veneer for M-profile targets with MOVW.
    
    2016-07-05  Andre Vieria  <andre.simoesdiasvieira@arm.com>
    
    	* elf32-arm.c (THUMB32_MOVT): New veneer macro.
    	(THUMB32_MOVW): Likewise.
    	(elf32_arm_stub_long_branch_thumb2_only_pure): New.
    	(DEF_STUBS): Define long_branch_thumb2_only_pure.
    	(arm_stub_is_thumb): Add new veneer stub.
    	(arm_type_of_stub): Use new veneer.
    	(arm_stub_required_alignment): Add new veneer.
    
    2016-07-05  Andre Vieria  <andre.simoesdiasvieira@arm.com>
    
    	* testsuite/ld-arm/farcall-thumb2-purecode.d: New test result.
    	* testsuite/ld-arm/farcall-thumb2-purecode.s: New test.
    	* testsuite/ld-arm/arm-elf.exp: Run it.

Diff:
---
 bfd/ChangeLog                                 | 10 ++++
 bfd/elf32-arm.c                               | 73 ++++++++++++++++++++++++---
 ld/ChangeLog                                  |  6 +++
 ld/testsuite/ld-arm/arm-elf.exp               |  3 ++
 ld/testsuite/ld-arm/farcall-thumb2-purecode.d | 22 ++++++++
 ld/testsuite/ld-arm/farcall-thumb2-purecode.s | 19 +++++++
 6 files changed, 127 insertions(+), 6 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index cff9b32..4031171 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
 2016-07-05  Andre Vieria  <andre.simoesdiasvieira@arm.com>
 
+	* elf32-arm.c (THUMB32_MOVT): New veneer macro.
+	(THUMB32_MOVW): Likewise.
+	(elf32_arm_stub_long_branch_thumb2_only_pure): New.
+	(DEF_STUBS): Define long_branch_thumb2_only_pure.
+	(arm_stub_is_thumb): Add new veneer stub.
+	(arm_type_of_stub): Use new veneer.
+	(arm_stub_required_alignment): Add new veneer.
+
+2016-07-05  Andre Vieria  <andre.simoesdiasvieira@arm.com>
+
 	* bfd-in2.h (SEC_ELF_NOREAD): Rename to ...
 	(SEC_ELF_PURECODE): ... this.
 	* elf32-arm.c (elf32_arm_post_process_headers): Rename SEC_ELF_NOREAD
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 9331471..834d615 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2360,6 +2360,8 @@ enum stub_insn_type
    is inserted in arm_build_one_stub().  */
 #define THUMB16_BCOND_INSN(X)	{(X), THUMB16_TYPE, R_ARM_NONE, 1}
 #define THUMB32_INSN(X)		{(X), THUMB32_TYPE, R_ARM_NONE, 0}
+#define THUMB32_MOVT(X)		{(X), THUMB32_TYPE, R_ARM_THM_MOVT_ABS, 0}
+#define THUMB32_MOVW(X)		{(X), THUMB32_TYPE, R_ARM_THM_MOVW_ABS_NC, 0}
 #define THUMB32_B_INSN(X, Z)	{(X), THUMB32_TYPE, R_ARM_THM_JUMP24, (Z)}
 #define ARM_INSN(X)		{(X), ARM_TYPE, R_ARM_NONE, 0}
 #define ARM_REL_INSN(X, Z)	{(X), ARM_TYPE, R_ARM_JUMP24, (Z)}
@@ -2409,6 +2411,15 @@ static const insn_sequence elf32_arm_stub_long_branch_thumb2_only[] =
   DATA_WORD (0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(x) */
 };
 
+/* Thumb -> Thumb long branch stub. Used for PureCode sections on Thumb2
+   M-profile architectures.  */
+static const insn_sequence elf32_arm_stub_long_branch_thumb2_only_pure[] =
+{
+  THUMB32_MOVW (0xf2400c00),	     /* mov.w ip, R_ARM_MOVW_ABS_NC */
+  THUMB32_MOVT (0xf2c00c00),	     /* movt  ip, R_ARM_MOVT_ABS << 16 */
+  THUMB16_INSN (0x4760),             /* bx   ip */
+};
+
 /* V4T Thumb -> Thumb long branch stub. Using the stack is not
    allowed.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
@@ -2634,6 +2645,7 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
   DEF_STUB(a8_veneer_bl) \
   DEF_STUB(a8_veneer_blx) \
   DEF_STUB(long_branch_thumb2_only) \
+  DEF_STUB(long_branch_thumb2_only_pure)
 
 #define DEF_STUB(x) arm_stub_##x,
 enum elf32_arm_stub_type
@@ -3808,6 +3820,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
     {
     case arm_stub_long_branch_thumb_only:
     case arm_stub_long_branch_thumb2_only:
+    case arm_stub_long_branch_thumb2_only_pure:
     case arm_stub_long_branch_v4t_thumb_arm:
     case arm_stub_short_branch_v4t_thumb_arm:
     case arm_stub_long_branch_v4t_thumb_arm_pic:
@@ -3847,6 +3860,8 @@ arm_type_of_stub (struct bfd_link_info *info,
   enum arm_st_branch_type branch_type = *actual_branch_type;
   union gotplt_union *root_plt;
   struct arm_plt_info *arm_plt;
+  int arch;
+  int thumb2_movw;
 
   if (branch_type == ST_BRANCH_LONG)
     return stub_type;
@@ -3859,6 +3874,11 @@ arm_type_of_stub (struct bfd_link_info *info,
   thumb2 = using_thumb2 (globals);
   thumb2_bl = using_thumb2_bl (globals);
 
+  arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, Tag_CPU_arch);
+
+  /* True for architectures that implement the thumb2 movw instruction.  */
+  thumb2_movw = thumb2 || (arch  == TAG_CPU_ARCH_V8M_BASE);
+
   /* Determine where the call point is.  */
   location = (input_sec->output_offset
 	      + input_sec->output_section->vma
@@ -3945,6 +3965,15 @@ arm_type_of_stub (struct bfd_link_info *info,
 	      /* Thumb to thumb.  */
 	      if (!thumb_only)
 		{
+		  if (input_sec->flags & SEC_ELF_PURECODE)
+		    (*_bfd_error_handler) (_("%B(%s): warning: long branch "
+					     " veneers used in section with "
+					     "SHF_ARM_PURECODE section "
+					     "attribute is only supported"
+					     " for M-profile targets that "
+					     "implement the movw "
+					     "instruction."));
+
 		  stub_type = (bfd_link_pic (info) | globals->pic_veneer)
 		    /* PIC stubs.  */
 		    ? ((globals->use_blx
@@ -3967,16 +3996,39 @@ arm_type_of_stub (struct bfd_link_info *info,
 		}
 	      else
 		{
-		  stub_type = (bfd_link_pic (info) | globals->pic_veneer)
-		    /* PIC stub.  */
-		    ? arm_stub_long_branch_thumb_only_pic
-		    /* non-PIC stub.  */
-		    : (thumb2 ? arm_stub_long_branch_thumb2_only
-			      : arm_stub_long_branch_thumb_only);
+		  if (thumb2_movw && (input_sec->flags & SEC_ELF_PURECODE))
+		      stub_type = arm_stub_long_branch_thumb2_only_pure;
+		  else
+		    {
+		      if (input_sec->flags & SEC_ELF_PURECODE)
+			(*_bfd_error_handler) (_("%B(%s): warning: long branch "
+						 " veneers used in section with "
+						 "SHF_ARM_PURECODE section "
+						 "attribute is only supported"
+						 " for M-profile targets that "
+						 "implement the movw "
+						 "instruction."));
+
+		      stub_type = (bfd_link_pic (info) | globals->pic_veneer)
+			/* PIC stub.  */
+			? arm_stub_long_branch_thumb_only_pic
+			/* non-PIC stub.  */
+			: (thumb2 ? arm_stub_long_branch_thumb2_only
+				  : arm_stub_long_branch_thumb_only);
+		    }
 		}
 	    }
 	  else
 	    {
+	      if (input_sec->flags & SEC_ELF_PURECODE)
+		(*_bfd_error_handler) (_("%B(%s): warning: long branch "
+					 " veneers used in section with "
+					 "SHF_ARM_PURECODE section "
+					 "attribute is only supported"
+					 " for M-profile targets that "
+					 "implement the movw "
+					 "instruction."));
+
 	      /* Thumb to arm.  */
 	      if (sym_sec != NULL
 		  && sym_sec->owner != NULL
@@ -4021,6 +4073,14 @@ arm_type_of_stub (struct bfd_link_info *info,
 	   || r_type == R_ARM_PLT32
 	   || r_type == R_ARM_TLS_CALL)
     {
+      if (input_sec->flags & SEC_ELF_PURECODE)
+	(*_bfd_error_handler) (_("%B(%s): warning: long branch "
+				 " veneers used in section with "
+				 "SHF_ARM_PURECODE section "
+				 "attribute is only supported"
+				 " for M-profile targets that "
+				 "implement the movw "
+				 "instruction."));
       if (branch_type == ST_BRANCH_TO_THUMB)
 	{
 	  /* Arm to thumb.  */
@@ -4446,6 +4506,7 @@ arm_stub_required_alignment (enum elf32_arm_stub_type stub_type)
     case arm_stub_long_branch_v4t_arm_thumb:
     case arm_stub_long_branch_thumb_only:
     case arm_stub_long_branch_thumb2_only:
+    case arm_stub_long_branch_thumb2_only_pure:
     case arm_stub_long_branch_v4t_thumb_thumb:
     case arm_stub_long_branch_v4t_thumb_arm:
     case arm_stub_short_branch_v4t_thumb_arm:
diff --git a/ld/ChangeLog b/ld/ChangeLog
index cc598af..6ee54fc 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,11 @@
 2016-07-05  Andre Vieria  <andre.simoesdiasvieira@arm.com>
 
+	* testsuite/ld-arm/farcall-thumb2-purecode.d: New test result.
+	* testsuite/ld-arm/farcall-thumb2-purecode.s: New test.
+	* testsuite/ld-arm/arm-elf.exp: Run it.
+
+2016-07-05  Andre Vieria  <andre.simoesdiasvieira@arm.com>
+
 	* testsuite/ld-arm/arm_noread.ld: Renamed to ...
 	testsuite/ld-arm/arm_purecode.ld: ... this, and replaced
 	all noread's by purecode.
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 597bdcf..d0c9a2f 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -505,6 +505,9 @@ set armeabitests_nonacl {
      {farcall-thumb-thumb-m-no-profile-a.s farcall-thumb-thumb-m-no-profile-b.s}
      {{objdump -d farcall-thumb-thumb-m-no-profile.d}}
      "farcall-thumb-thumb-m-no-profile"}
+    {"Thumb2 purecode farcall" "-Ttext 0x1000 --section-start .foo=0x2001020" "" "" {farcall-thumb2-purecode.s}
+     {{objdump -d farcall-thumb2-purecode.d}}
+     "farcall-thumb2-purecode"}
 
     {"Thumb-ARM farcall" "-Ttext 0x1c01010 --section-start .foo=0x2001014" "" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
diff --git a/ld/testsuite/ld-arm/farcall-thumb2-purecode.d b/ld/testsuite/ld-arm/farcall-thumb2-purecode.d
new file mode 100644
index 0000000..2a62fe4
--- /dev/null
+++ b/ld/testsuite/ld-arm/farcall-thumb2-purecode.d
@@ -0,0 +1,22 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <bar>:
+    1000:	4770      	bx	lr
+
+Disassembly of section .foo:
+
+02001020 <_start>:
+ 2001020:	f000 f802 	bl	2001028 <__bar_veneer>
+ 2001024:	0000      	movs	r0, r0
+	\.\.\.
+
+02001028 <__bar_veneer>:
+ 2001028:	f241 0c01 	movw	ip, #4097	; 0x1001
+ 200102c:	f2c0 0c00 	movt	ip, #0
+ 2001030:	4760      	bx	ip
+ 2001032:	0000      	movs	r0, r0
+ 2001034:	0000      	movs	r0, r0
+	\.\.\.
+
diff --git a/ld/testsuite/ld-arm/farcall-thumb2-purecode.s b/ld/testsuite/ld-arm/farcall-thumb2-purecode.s
new file mode 100644
index 0000000..a16731a
--- /dev/null
+++ b/ld/testsuite/ld-arm/farcall-thumb2-purecode.s
@@ -0,0 +1,19 @@
+@ Test to ensure that a purecode Thumb2 call exceeding 4Mb generates a stub.
+
+	.global _start
+	.syntax unified
+	.arch armv7-m
+	.thumb
+	.thumb_func
+
+@ We will place the section .text at 0x1000.
+
+	.text
+bar:
+	bx lr
+
+@ We will place the section .foo at 0x02001014.
+
+	.section .foo, "0x20000006"
+_start:
+	bl bar


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