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]

ARMv4 EABi support


The ARM EABI requires that code be interworking safe. However ARMv4 cores do 
not support the BX instruction necessary for this.  The solution to this is 
the R_ARM_V4BX relocation, which allows the static linker to turn interworked 
v4t code into plain v4 code.

The attached patch makes gas generate these relocations. In addition it adds 
a --fix-v4bx option that allows bx on ARMv4 cores.  The name of this option 
was chosen to match the existing linker option.

I've also added a new --with-v4bx-interworking option.  This is aimed at 
systems like Debian where running the same binaries/shared libraries on all 
systems is important.  As described in the documentation, this replaces a bx 
instruction with a branch to a veneer that supports both interworking and 
ARMv4 simultaneously.

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

Paul

2008-02-20  Paul Brook  <paul@codesourcery.com>

	ld/
	* emultempl/armelf.em (OPTION_FIX_V4BX_INTERWORKING): Define.
	(PARSE_AND_LIST_LONGOPTS): Add fix-v4bx-interworking.
	(PARSE_AND_LIST_OPTIONS): Ditto.
	(PARSE_AND_LIST_ARGS_CASES): Handle OPTION_FIX_V4BX_INTERWORKING.
	* emulparams/armelf.sh (OTHER_TEXT_SECTIONS): Add .v4_bx.
	* emulparams/armelf_linux.sh (OTHER_TEXT_SECTIONS): Ditto.
	* emulparams/armnto.sh (OTHER_TEXT_SECTIONS): Ditto.
	* ld.texinfo: Document --fix-v4bx-interworking.

	ld/testsuite/
	* ld-arm/armv4-bx.d: New test.
	* ld-arm/armv4-bx.s: New test.
	* ld-arm/arm.ld: Add .v4bx.
	* ld-arm/arm-elf.exp: Add armv4-bx.

	gas/testsuite/
	* gas/arm/thumb.d: Exclude EABI targets.
	* gas/arm/arch4t.d: Exclude EABI targts.
	* gas/arm/v4bx.d: New test.
	* gas/arm/v4bx.s: New test.
	* gas/arm/thumb-eabi.d: New test.
	* gas/arm/arch4t-eabi.d: New test.

	gas/
	* config/tc-arm.c (fix_v4bx): New variable.
	(do_bx): Generate V4BX relocations.
	(md_assemble): Allow bx on v4 codes when fix_v4bx.
	(md_apply_fix): Handle BFD_RELOC_ARM_V4BX.
	(tc_gen_reloc): Ditto.
	(OPTION_FIX_V4BX): Define.
	(md_longopts): Add fix-v4bx.
	(md_parse_option): Handle OPTION_FIX_V4BX.
	(md_show_usage): Document --fix-v4bx.
	* doc/c-arm.texi: Document --fix-v4bx.

	bfd/
	* reloc.c: Add BFD_RELOC_ARM_V4BX.
	* elf32-arm.c (elf32_arm_reloc_map): Add BFD_RELOC_ARM_V4BX.
	(ARM_BX_GLUE_SECTION_NAME, ARM_BX_GLUE_SECTION_NAME): Define.
	(elf32_arm_link_hash_table): Add bx_glue_size and bx_glue_offset.
	Update comment for fix_v4bx.
	(elf32_arm_link_hash_table_create): Zero bx_glue_size and
	bx_glue_offset.
	(ARM_BX_VENEER_SIZE, armbx1_tst_insn, armbx2_moveq_insn,
	armbx3_bx_insn): New.
	(bfd_elf32_arm_allocate_interworking_sections): Allocate BX veneer
	section.
	(bfd_elf32_arm_add_glue_sections_to_bfd): Ditto.
	(bfd_elf32_arm_process_before_allocation): Record BX veneers.
	(record_arm_bx_glue, elf32_arm_bx_glue): New functions.
	(elf32_arm_final_link_relocate): Handle BX veneers.
	(elf32_arm_output_arch_local_syms): Output mapping symbol for .v4_bx.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.439
diff -u -p -r1.439 bfd-in2.h
--- bfd/bfd-in2.h	15 Feb 2008 10:35:46 -0000	1.439
+++ bfd/bfd-in2.h	20 Feb 2008 14:47:37 -0000
@@ -3089,6 +3089,9 @@ pc-relative or some form of GOT-indirect
   BFD_RELOC_ARM_LDC_SB_G1,
   BFD_RELOC_ARM_LDC_SB_G2,
 
+/* Annotation of BX instructions.  */
+  BFD_RELOC_ARM_V4BX,
+
 /* These relocs are only used within the ARM assembler.  They are not
 (at present) written to any object files.  */
   BFD_RELOC_ARM_IMMEDIATE,
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.134
diff -u -p -r1.134 elf32-arm.c
--- bfd/elf32-arm.c	12 Feb 2008 11:32:30 -0000	1.134
+++ bfd/elf32-arm.c	20 Feb 2008 14:47:39 -0000
@@ -1773,7 +1773,8 @@ static const struct elf32_arm_reloc_map 
     {BFD_RELOC_ARM_LDRS_SB_G2, R_ARM_LDRS_SB_G2},
     {BFD_RELOC_ARM_LDC_SB_G0, R_ARM_LDC_SB_G0},
     {BFD_RELOC_ARM_LDC_SB_G1, R_ARM_LDC_SB_G1},
-    {BFD_RELOC_ARM_LDC_SB_G2, R_ARM_LDC_SB_G2}
+    {BFD_RELOC_ARM_LDC_SB_G2, R_ARM_LDC_SB_G2},
+    {BFD_RELOC_ARM_V4BX,	     R_ARM_V4BX}
   };
 
 static reloc_howto_type *
@@ -1904,6 +1905,9 @@ typedef unsigned short int insn16;
 #define VFP11_ERRATUM_VENEER_SECTION_NAME ".vfp11_veneer"
 #define VFP11_ERRATUM_VENEER_ENTRY_NAME   "__vfp11_veneer_%x"
 
+#define ARM_BX_GLUE_SECTION_NAME ".v4_bx"
+#define ARM_BX_GLUE_ENTRY_NAME   "__bx_r%d"
+
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
 #define ELF_DYNAMIC_INTERPRETER     "/usr/lib/ld.so.1"
@@ -2171,6 +2175,13 @@ struct elf32_arm_link_hash_table
     /* The size in bytes of the section containing the ARM-to-Thumb glue.  */
     bfd_size_type arm_glue_size;
 
+    /* The size in bytes of section containing the ARMv4 BX veneers.  */
+    bfd_size_type bx_glue_size;
+
+    /* Offsets of ARMv4 BX veneers.  Bit1 set if present, and Bit0 set when
+       veneer has been populated.  */
+    bfd_vma bx_glue_offset[15];
+
     /* The size in bytes of the section containing glue for VFP11 erratum
        veneers.  */
     bfd_size_type vfp11_erratum_glue_size;
@@ -2188,7 +2199,9 @@ struct elf32_arm_link_hash_table
     /* The relocation to use for R_ARM_TARGET2 relocations.  */
     int target2_reloc;
 
-    /* Nonzero to fix BX instructions for ARMv4 targets.  */
+    /* 0 = Ignore R_ARM_V4BX.
+       1 = Convert BX to MOV PC.
+       2 = Generate v4 interworing stubs.  */
     int fix_v4bx;
 
     /* Nonzero if the ARM/Thumb BLX instructions are available for use.  */
@@ -2469,6 +2482,8 @@ elf32_arm_link_hash_table_create (bfd *a
   ret->srelplt2 = NULL;
   ret->thumb_glue_size = 0;
   ret->arm_glue_size = 0;
+  ret->bx_glue_size = 0;
+  memset (ret->bx_glue_offset, 0, sizeof(ret->bx_glue_offset));
   ret->vfp11_fix = BFD_ARM_VFP11_FIX_NONE;
   ret->vfp11_erratum_glue_size = 0;
   ret->num_vfp11_fixes = 0;
@@ -2626,6 +2641,11 @@ static const insn32 t2a3_b_insn = 0xea00
 
 #define VFP11_ERRATUM_VENEER_SIZE 8
 
+#define ARM_BX_VENEER_SIZE 12
+static const insn32 armbx1_tst_insn = 0xe3100001;
+static const insn32 armbx2_moveq_insn = 0x01a0f000;
+static const insn32 armbx3_bx_insn = 0xe12fff10;
+
 #ifndef ELFARM_NABI_C_INCLUDED
 bfd_boolean
 bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info * info)
@@ -2684,6 +2704,21 @@ bfd_elf32_arm_allocate_interworking_sect
       s->contents = foo;
     }
 
+  if (globals->bx_glue_size != 0)
+    {
+      BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
+
+      s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
+				   ARM_BX_GLUE_SECTION_NAME);
+
+      BFD_ASSERT (s != NULL);
+
+      foo = bfd_alloc (globals->bfd_of_glue_owner, globals->bx_glue_size);
+
+      BFD_ASSERT (s->size == globals->bx_glue_size);
+      s->contents = foo;
+    }
+
   return TRUE;
 }
 
@@ -2835,6 +2870,64 @@ record_thumb_to_arm_glue (struct bfd_lin
 }
 
 
+/* Allocate space for ARMv4 BX veneers.  */
+
+static void
+record_arm_bx_glue (struct bfd_link_info * link_info, int reg)
+{
+  asection * s;
+  struct elf32_arm_link_hash_table *globals;
+  char *tmp_name;
+  struct elf_link_hash_entry *myh;
+  struct bfd_link_hash_entry *bh;
+  bfd_vma val;
+
+  /* BX PC does not need a veneer.  */
+  if (reg == 15)
+    return;
+
+  globals = elf32_arm_hash_table (link_info);
+
+  BFD_ASSERT (globals != NULL);
+  BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
+
+  /* Check if this veneer has already been allocated.  */
+  if (globals->bx_glue_offset[reg])
+    return;
+
+  s = bfd_get_section_by_name
+    (globals->bfd_of_glue_owner, ARM_BX_GLUE_SECTION_NAME);
+
+  BFD_ASSERT (s != NULL);
+
+  /* Add symbol for veneer.  */
+  tmp_name = bfd_malloc ((bfd_size_type) strlen (ARM_BX_GLUE_ENTRY_NAME) + 1);
+  
+  BFD_ASSERT (tmp_name);
+  
+  sprintf (tmp_name, ARM_BX_GLUE_ENTRY_NAME, reg);
+  
+  myh = elf_link_hash_lookup
+    (&(globals)->root, tmp_name, FALSE, FALSE, FALSE);
+  
+  BFD_ASSERT (myh == NULL);
+  
+  bh = NULL;
+  val = globals->bx_glue_size;
+  _bfd_generic_link_add_one_symbol (link_info, globals->bfd_of_glue_owner,
+                                    tmp_name, BSF_FUNCTION | BSF_LOCAL, s, val,
+                                    NULL, TRUE, FALSE, &bh);
+
+  myh = (struct elf_link_hash_entry *) bh;
+  myh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
+  myh->forced_local = 1;
+
+  s->size += ARM_BX_VENEER_SIZE;
+  globals->bx_glue_offset[reg] = globals->bx_glue_size | 2;
+  globals->bx_glue_size += ARM_BX_VENEER_SIZE;
+}
+
+
 /* Add an entry to the code/data map for section SEC.  */
 
 static void
@@ -3058,6 +3151,24 @@ bfd_elf32_arm_add_glue_sections_to_bfd (
       sec->gc_mark = 1;
     }
 
+  sec = bfd_get_section_by_name (abfd, ARM_BX_GLUE_SECTION_NAME);
+
+  if (sec == NULL)
+    {
+      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+	       | SEC_CODE | SEC_READONLY);
+
+      sec = bfd_make_section_with_flags (abfd,
+					 ARM_BX_GLUE_SECTION_NAME,
+                                         flags);
+
+      if (sec == NULL
+	  || !bfd_set_section_alignment (abfd, sec, 2))
+	return FALSE;
+
+      sec->gc_mark = 1;
+    }
+
   return TRUE;
 }
 
@@ -3177,7 +3288,8 @@ bfd_elf32_arm_process_before_allocation 
 	      && r_type != R_ARM_CALL
 	      && r_type != R_ARM_JUMP24
 	      && r_type != R_ARM_THM_CALL
-	      && r_type != R_ARM_THM_JUMP24)
+	      && r_type != R_ARM_THM_JUMP24
+	      && (r_type != R_ARM_V4BX || globals->fix_v4bx < 2))
 	    continue;
 
 	  /* Get the section contents if we haven't done so already.  */
@@ -3194,6 +3306,15 @@ bfd_elf32_arm_process_before_allocation 
 		}
 	    }
 
+	  if (r_type == R_ARM_V4BX)
+	    {
+	      int reg;
+
+	      reg = bfd_get_32 (abfd, contents + irel->r_offset) & 0xf;
+	      record_arm_bx_glue (link_info, reg);
+	      continue;
+	    }
+
 	  /* If the relocation is not against a symbol it cannot concern us.  */
 	  h = NULL;
 
@@ -4332,6 +4453,43 @@ elf32_arm_to_thumb_export_stub (struct e
   return TRUE;
 }
 
+/* Populate ARMv4 BX veneers.  Returns the absolute adress of the veneer.  */
+
+static bfd_vma
+elf32_arm_bx_glue (struct bfd_link_info * info, int reg)
+{
+  bfd_byte *p;
+  bfd_vma glue_addr;
+  asection *s;
+  struct elf32_arm_link_hash_table *globals;
+
+  globals = elf32_arm_hash_table (info);
+
+  BFD_ASSERT (globals != NULL);
+  BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
+
+  s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
+			       ARM_BX_GLUE_SECTION_NAME);
+  BFD_ASSERT (s != NULL);
+  BFD_ASSERT (s->contents != NULL);
+  BFD_ASSERT (s->output_section != NULL);
+
+  BFD_ASSERT (globals->bx_glue_offset[reg] & 2);
+
+  glue_addr = globals->bx_glue_offset[reg] & ~(bfd_vma)3;
+
+  if ((globals->bx_glue_offset[reg] & 1) == 0)
+    {
+      p = s->contents + glue_addr;
+      bfd_put_32 (globals->obfd, armbx1_tst_insn + (reg << 16), p);
+      bfd_put_32 (globals->obfd, armbx2_moveq_insn + reg, p + 4);
+      bfd_put_32 (globals->obfd, armbx3_bx_insn + reg, p + 8);
+      globals->bx_glue_offset[reg] |= 1;
+    }
+
+  return glue_addr + s->output_section->vma + s->output_offset;
+}
+
 /* Generate Arm stubs for exported Thumb symbols.  */
 static void
 elf32_arm_begin_write_processing (bfd *abfd ATTRIBUTE_UNUSED, 
@@ -5710,18 +5868,32 @@ elf32_arm_final_link_relocate (reloc_how
 
     case R_ARM_V4BX:
       if (globals->fix_v4bx)
-        {
-          bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
+	{
+	  bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
 
-          /* Ensure that we have a BX instruction.  */
-          BFD_ASSERT ((insn & 0x0ffffff0) == 0x012fff10);
+	  /* Ensure that we have a BX instruction.  */
+	  BFD_ASSERT ((insn & 0x0ffffff0) == 0x012fff10);
 
-          /* Preserve Rm (lowest four bits) and the condition code
-             (highest four bits). Other bits encode MOV PC,Rm.  */
-          insn = (insn & 0xf000000f) | 0x01a0f000;
+	  if (globals->fix_v4bx == 2 && (insn & 0xf) != 0xf)
+	    {
+	      /* Branch to veneer.  */
+	      bfd_vma glue_addr;
+	      glue_addr = elf32_arm_bx_glue (info, insn & 0xf);
+	      glue_addr -= input_section->output_section->vma
+			   + input_section->output_offset
+			   + rel->r_offset + 8;
+	      insn = (insn & 0xf0000000) | 0x0a000000
+		     | ((glue_addr >> 2) & 0x00ffffff);
+	    }
+	  else
+	    {
+	      /* Preserve Rm (lowest four bits) and the condition code
+		 (highest four bits). Other bits encode MOV PC,Rm.  */
+	      insn = (insn & 0xf000000f) | 0x01a0f000;
+	    }
 
-          bfd_put_32 (input_bfd, insn, hit_data);
-        }
+	  bfd_put_32 (input_bfd, insn, hit_data);
+	}
       return bfd_reloc_ok;
 
     case R_ARM_MOVW_ABS_NC:
@@ -9732,6 +9904,18 @@ elf32_arm_output_arch_local_syms (bfd *o
 	}
     }
 
+  /* ARMv4 BX veneers.  */
+  if (htab->bx_glue_size > 0)
+    {
+      osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner,
+					 ARM_BX_GLUE_SECTION_NAME);
+
+      osi.sec_shndx = _bfd_elf_section_from_bfd_section
+	  (output_bfd, osi.sec->output_section);
+
+      elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_ARM, 0);
+    }
+
   /* Finally, output mapping symbols for the PLT.  */
   if (!htab->splt || htab->splt->size == 0)
     return TRUE;
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.199
diff -u -p -r1.199 libbfd.h
--- bfd/libbfd.h	30 Oct 2007 15:18:29 -0000	1.199
+++ bfd/libbfd.h	20 Feb 2008 14:47:40 -0000
@@ -1282,6 +1282,7 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_ARM_LDC_SB_G0",
   "BFD_RELOC_ARM_LDC_SB_G1",
   "BFD_RELOC_ARM_LDC_SB_G2",
+  "BFD_RELOC_ARM_V4BX",
   "BFD_RELOC_ARM_IMMEDIATE",
   "BFD_RELOC_ARM_ADRL_IMMEDIATE",
   "BFD_RELOC_ARM_T32_IMMEDIATE",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.172
diff -u -p -r1.172 reloc.c
--- bfd/reloc.c	30 Oct 2007 15:18:29 -0000	1.172
+++ bfd/reloc.c	20 Feb 2008 14:47:41 -0000
@@ -2925,6 +2925,11 @@ ENUMDOC
   ARM group relocations.
 
 ENUM
+  BFD_RELOC_ARM_V4BX
+ENUMDOC
+  Annotation of BX instructions.
+
+ENUM
   BFD_RELOC_ARM_IMMEDIATE
 ENUMX
   BFD_RELOC_ARM_ADRL_IMMEDIATE
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.345
diff -u -p -r1.345 tc-arm.c
--- gas/config/tc-arm.c	14 Feb 2008 16:35:50 -0000	1.345
+++ gas/config/tc-arm.c	20 Feb 2008 14:47:46 -0000
@@ -143,6 +143,7 @@ static int atpcs	     = FALSE;
 static int support_interwork = FALSE;
 static int uses_apcs_float   = FALSE;
 static int pic_code	     = FALSE;
+static int fix_v4bx	     = FALSE;
 
 /* Variables that we set while parsing command-line options.  Once all
    options have been read we re-process these values to set the real
@@ -6760,10 +6761,23 @@ do_blx (void)
 static void
 do_bx (void)
 {
+  bfd_boolean want_reloc;
+
   if (inst.operands[0].reg == REG_PC)
     as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
 
   inst.instruction |= inst.operands[0].reg;
+  /* Output R_ARM_V4BX relocations if is an EABI object that looks like
+     it is for ARMv4t or earlier.  */
+  want_reloc = !ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v5);
+  if (object_arch && !ARM_CPU_HAS_FEATURE (*object_arch, arm_ext_v5))
+      want_reloc = TRUE;
+
+  if (EF_ARM_EABI_VERSION (meabi_flags) < EF_ARM_EABI_VER4)
+    want_reloc = FALSE;
+
+  if (want_reloc)
+    inst.reloc.type = BFD_RELOC_ARM_V4BX;
 }
 
 
@@ -14272,9 +14286,15 @@ md_assemble (char *str)
     }
   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1))
     {
+      bfd_boolean is_bx;
+
+      /* bx is allowed on v5 cores, and sometimes on v4 cores.  */
+      is_bx = (opcode->aencode == do_bx);
+
       /* Check that this instruction is supported for this CPU.  */
-      if (!opcode->avariant ||
-	  !ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant))
+      if (!(is_bx && fix_v4bx)
+	  && !(opcode->avariant &&
+	       ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant)))
 	{
 	  as_bad (_("selected processor does not support `%s'"), str);
 	  return;
@@ -14296,8 +14316,7 @@ md_assemble (char *str)
 	opcode->aencode ();
       /* Arm mode bx is marked as both v4T and v5 because it's still required
          on a hypothetical non-thumb v5 core.  */
-      if (ARM_CPU_HAS_FEATURE (*opcode->avariant, arm_ext_v4t)
-	  || ARM_CPU_HAS_FEATURE (*opcode->avariant, arm_ext_v5))
+      if (is_bx)
 	ARM_MERGE_FEATURE_SETS (arm_arch_used, arm_arch_used, arm_ext_v4t);
       else
 	ARM_MERGE_FEATURE_SETS (arm_arch_used, arm_arch_used,
@@ -18969,6 +18988,11 @@ md_apply_fix (fixS *	fixP,
         }
       break;
 
+    case BFD_RELOC_ARM_V4BX:
+      /* This will need to go in the object file.  */
+      fixP->fx_done = 0;
+      break;
+
     case BFD_RELOC_UNUSED:
     default:
       as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -19119,6 +19143,7 @@ tc_gen_reloc (asection *section, fixS *f
     case BFD_RELOC_ARM_LDC_SB_G0:
     case BFD_RELOC_ARM_LDC_SB_G1:
     case BFD_RELOC_ARM_LDC_SB_G2:
+    case BFD_RELOC_ARM_V4BX:
       code = fixp->fx_r_type;
       break;
 
@@ -19806,6 +19831,7 @@ const char * md_shortopts = "m:k";
 #define OPTION_EL (OPTION_MD_BASE + 1)
 #endif
 #endif
+#define OPTION_FIX_V4BX (OPTION_MD_BASE + 2)
 
 struct option md_longopts[] =
 {
@@ -19815,6 +19841,7 @@ struct option md_longopts[] =
 #ifdef OPTION_EL
   {"EL", no_argument, NULL, OPTION_EL},
 #endif
+  {"fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX},
   {NULL, no_argument, NULL, 0}
 };
 
@@ -20430,6 +20457,10 @@ md_parse_option (int c, char * arg)
       break;
 #endif
 
+    case OPTION_FIX_V4BX:
+      fix_v4bx = TRUE;
+      break;
+
     case 'a':
       /* Listing option.  Just ignore these, we don't support additional
 	 ones.	*/
@@ -20527,6 +20558,9 @@ md_show_usage (FILE * fp)
   fprintf (fp, _("\
   -EL                     assemble code for a little-endian cpu\n"));
 #endif
+
+  fprintf (fp, _("\
+  --fix-v4bx              Allow BX in ARMv4 code\n"));
 }
 
 
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-arm.texi,v
retrieving revision 1.46
diff -u -p -r1.46 c-arm.texi
--- gas/doc/c-arm.texi	23 Aug 2007 02:05:58 -0000	1.46
+++ gas/doc/c-arm.texi	20 Feb 2008 14:47:46 -0000
@@ -276,6 +276,11 @@ be marked as being encoded for a little-
 This option specifies that the output of the assembler should be marked
 as position-independent code (PIC).
 
+@cindex @code{--fix-v4bx} command line option, ARM
+@item --fix-v4bx
+Allow @code{BX} instructions in ARMv4 code.  This is intended for use with
+the linker option of the same name.
+
 @end table
 
 
Index: gas/testsuite/gas/arm/arch4t-eabi.d
===================================================================
RCS file: gas/testsuite/gas/arm/arch4t-eabi.d
diff -N gas/testsuite/gas/arm/arch4t-eabi.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arch4t-eabi.d	20 Feb 2008 14:47:46 -0000
@@ -0,0 +1,40 @@
+# name: ARM architecture 4t instructions (EABI)
+# as: -march=armv4t
+# objdump: -dr --prefix-addresses --show-raw-insn
+# source: arch4t.s
+# target: *-*-*eabi *-*-symbianelf
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+00 <[^>]+> e12fff10 ?	bx	r0
+.*: R_ARM_V4BX.*
+0+04 <[^>]+> 012fff11 ?	bxeq	r1
+.*: R_ARM_V4BX.*
+0+08 <[^>]+> e15f30b8 ?	ldrh	r3, \[pc, #-8\]	; 0+08 <[^>]+>
+0+0c <[^>]+> e1d540f0 ?	ldrsh	r4, \[r5\]
+0+10 <[^>]+> e19140d3 ?	ldrsb	r4, \[r1, r3\]
+0+14 <[^>]+> e1b410f4 ?	ldrsh	r1, \[r4, r4\]!
+0+18 <[^>]+> 011510d3 ?	ldrsbeq	r1, \[r5, -r3\]
+0+1c <[^>]+> 109620b7 ?	ldrhne	r2, \[r6\], r7
+0+20 <[^>]+> 309720f8 ?	ldrshcc	r2, \[r7\], r8
+0+24 <[^>]+> e1d32fdf ?	ldrsb	r2, \[r3, #255\]
+0+28 <[^>]+> e1541ffa ?	ldrsh	r1, \[r4, #-250\]
+0+2c <[^>]+> e1d51fd0 ?	ldrsb	r1, \[r5, #240\]
+0+30 <[^>]+> e1cf23b0 ?	strh	r2, \[pc, #48\]	; 0+68 <[^>]+>
+0+34 <[^>]+> 11c330b0 ?	strhne	r3, \[r3\]
+0+38 <[^>]+> e328f002 ?	msr	CPSR_f, #2	; 0x2
+0+3c <[^>]+> e121f003 ?	msr	CPSR_c, r3
+0+40 <[^>]+> e122f004 ?	msr	CPSR_x, r4
+0+44 <[^>]+> e124f005 ?	msr	CPSR_s, r5
+0+48 <[^>]+> e128f006 ?	msr	CPSR_f, r6
+0+4c <[^>]+> e129f007 ?	msr	CPSR_fc, r7
+0+50 <[^>]+> e368f004 ?	msr	SPSR_f, #4	; 0x4
+0+54 <[^>]+> e161f008 ?	msr	SPSR_c, r8
+0+58 <[^>]+> e162f009 ?	msr	SPSR_x, r9
+0+5c <[^>]+> e164f00a ?	msr	SPSR_s, sl
+0+60 <[^>]+> e168f00b ?	msr	SPSR_f, fp
+0+64 <[^>]+> e169f00c ?	msr	SPSR_fc, ip
+0+68 <[^>]+> e1a00000 ?	nop			\(mov r0,r0\)
+0+6c <[^>]+> e1a00000 ?	nop			\(mov r0,r0\)
+
Index: gas/testsuite/gas/arm/arch4t.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/arch4t.d,v
retrieving revision 1.3
diff -u -p -r1.3 arch4t.d
--- gas/testsuite/gas/arm/arch4t.d	21 Apr 2007 19:45:05 -0000	1.3
+++ gas/testsuite/gas/arm/arch4t.d	20 Feb 2008 14:47:46 -0000
@@ -1,6 +1,8 @@
 # name: ARM architecture 4t instructions
 # as: -march=armv4t
 # objdump: -dr --prefix-addresses --show-raw-insn
+# EABI targets have their own variant.
+# not-target: *-*-*eabi *-*-symbianelf
 
 .*: +file format .*arm.*
 
Index: gas/testsuite/gas/arm/thumb-eabi.d
===================================================================
RCS file: gas/testsuite/gas/arm/thumb-eabi.d
diff -N gas/testsuite/gas/arm/thumb-eabi.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/thumb-eabi.d	20 Feb 2008 14:47:46 -0000
@@ -0,0 +1,165 @@
+# name: Thumb instructions (EABI)
+# as: -mcpu=arm7t
+# objdump: -dr --prefix-addresses --show-raw-insn
+# source: thumb.s
+# target: *-*-*eabi *-*-symbianelf
+
+.*: +file format .*arm.*
+
+Disassembly of section \.text:
+0+000 <[^>]+> 00ca      	lsls	r2, r1, #3
+0+002 <[^>]+> 0fe3      	lsrs	r3, r4, #31
+0+004 <[^>]+> 1147      	asrs	r7, r0, #5
+0+006 <[^>]+> 0011      	lsls	r1, r2, #0
+0+008 <[^>]+> 0023      	lsls	r3, r4, #0
+0+00a <[^>]+> 002c      	lsls	r4, r5, #0
+0+00c <[^>]+> 083e      	lsrs	r6, r7, #32
+0+00e <[^>]+> 1008      	asrs	r0, r1, #32
+0+010 <[^>]+> 18d1      	adds	r1, r2, r3
+0+012 <[^>]+> 1ca2      	adds	r2, r4, #2
+0+014 <[^>]+> 1beb      	subs	r3, r5, r7
+0+016 <[^>]+> 1fe2      	subs	r2, r4, #7
+0+018 <[^>]+> 24ff      	movs	r4, #255
+0+01a <[^>]+> 2bfa      	cmp	r3, #250
+0+01c <[^>]+> 367b      	adds	r6, #123
+0+01e <[^>]+> 3d80      	subs	r5, #128
+0+020 <[^>]+> 402b      	ands	r3, r5
+0+022 <[^>]+> 4074      	eors	r4, r6
+0+024 <[^>]+> 4081      	lsls	r1, r0
+0+026 <[^>]+> 40da      	lsrs	r2, r3
+0+028 <[^>]+> 4134      	asrs	r4, r6
+0+02a <[^>]+> 417d      	adcs	r5, r7
+0+02c <[^>]+> 41a0      	sbcs	r0, r4
+0+02e <[^>]+> 41e1      	rors	r1, r4
+0+030 <[^>]+> 422a      	tst	r2, r5
+0+032 <[^>]+> 4249      	negs	r1, r1
+0+034 <[^>]+> 429a      	cmp	r2, r3
+0+036 <[^>]+> 42e1      	cmn	r1, r4
+0+038 <[^>]+> 4318      	orrs	r0, r3
+0+03a <[^>]+> 436c      	muls	r4, r5
+0+03c <[^>]+> 43bd      	bics	r5, r7
+0+03e <[^>]+> 43ed      	mvns	r5, r5
+0+040 <[^>]+> 4469      	add	r1, sp
+0+042 <[^>]+> 4494      	add	ip, r2
+0+044 <[^>]+> 44c9      	add	r9, r9
+0+046 <[^>]+> 4571      	cmp	r1, lr
+0+048 <[^>]+> 4580      	cmp	r8, r0
+0+04a <[^>]+> 45f4      	cmp	ip, lr
+0+04c <[^>]+> 4648      	mov	r0, r9
+0+04e <[^>]+> 46a1      	mov	r9, r4
+0+050 <[^>]+> 46c0      	nop			\(mov r8, r8\)
+0+052 <[^>]+> 4738      	bx	r7
+0+054 <[^>]+> 4740      	bx	r8
+0+056 <[^>]+> 46c0      	nop			\(mov r8, r8\)
+0+058 <[^>]+> 4778      	bx	pc
+0+05a <[^>]+> 4b20      	ldr	r3, \[pc, #128\]	\(0+0dc <[^>]+>\)
+0+05c <[^>]+> 4c02      	ldr	r4, \[pc, #8\]	\(0+068 <[^>]+>\)
+0+05e <[^>]+> 5088      	str	r0, \[r1, r2\]
+0+060 <[^>]+> 5511      	strb	r1, \[r2, r4\]
+0+062 <[^>]+> 59f5      	ldr	r5, \[r6, r7\]
+0+064 <[^>]+> 5d62      	ldrb	r2, \[r4, r5\]
+0+066 <[^>]+> 46c0      	nop			\(mov r8, r8\)
+0+068 <[^>]+> 52d1      	strh	r1, \[r2, r3\]
+0+06a <[^>]+> 5a23      	ldrh	r3, \[r4, r0\]
+0+06c <[^>]+> 57f1      	ldrsb	r1, \[r6, r7\]
+0+06e <[^>]+> 5f42      	ldrsh	r2, \[r0, r5\]
+0+070 <[^>]+> 67db      	str	r3, \[r3, #124\]
+0+072 <[^>]+> 6fe1      	ldr	r1, \[r4, #124\]
+0+074 <[^>]+> 682d      	ldr	r5, \[r5, #0\]
+0+076 <[^>]+> 77e9      	strb	r1, \[r5, #31\]
+0+078 <[^>]+> 7161      	strb	r1, \[r4, #5\]
+0+07a <[^>]+> 7032      	strb	r2, \[r6, #0\]
+0+07c <[^>]+> 87ec      	strh	r4, \[r5, #62\]
+0+07e <[^>]+> 8885      	ldrh	r5, \[r0, #4\]
+0+080 <[^>]+> 8813      	ldrh	r3, \[r2, #0\]
+0+082 <[^>]+> 93ff      	str	r3, \[sp, #1020\]
+0+084 <[^>]+> 990b      	ldr	r1, \[sp, #44\]
+0+086 <[^>]+> 9a00      	ldr	r2, \[sp, #0\]
+0+088 <[^>]+> a7ff      	add	r7, pc, #1020	\(adr r7, 0+488 <[^>]+>\)
+0+08a <[^>]+> ac80      	add	r4, sp, #512
+0+08c <[^>]+> b043      	add	sp, #268
+0+08e <[^>]+> b09a      	sub	sp, #104
+0+090 <[^>]+> b0c3      	sub	sp, #268
+0+092 <[^>]+> b01b      	add	sp, #108
+0+094 <[^>]+> b417      	push	{r0, r1, r2, r4}
+0+096 <[^>]+> b5f9      	push	{r0, r3, r4, r5, r6, r7, lr}
+0+098 <[^>]+> bc98      	pop	{r3, r4, r7}
+0+09a <[^>]+> bdff      	pop	{r0, r1, r2, r3, r4, r5, r6, r7, pc}
+0+09c <[^>]+> c3f3      	stmia	r3!, {r0, r1, r4, r5, r6, r7}
+0+09e <[^>]+> c8fe      	ldmia	r0!, {r1, r2, r3, r4, r5, r6, r7}
+0+0a0 <[^>]+> d0e2      	beq.n	0+068 <[^>]+>
+0+0a2 <[^>]+> d1e1      	bne.n	0+068 <[^>]+>
+0+0a4 <[^>]+> d2e0      	bcs.n	0+068 <[^>]+>
+0+0a6 <[^>]+> d3df      	bcc.n	0+068 <[^>]+>
+0+0a8 <[^>]+> d4de      	bmi.n	0+068 <[^>]+>
+0+0aa <[^>]+> d5dd      	bpl.n	0+068 <[^>]+>
+0+0ac <[^>]+> d6dc      	bvs.n	0+068 <[^>]+>
+0+0ae <[^>]+> d7db      	bvc.n	0+068 <[^>]+>
+0+0b0 <[^>]+> d8da      	bhi.n	0+068 <[^>]+>
+0+0b2 <[^>]+> d9d9      	bls.n	0+068 <[^>]+>
+0+0b4 <[^>]+> dad8      	bge.n	0+068 <[^>]+>
+0+0b6 <[^>]+> dcd7      	bgt.n	0+068 <[^>]+>
+0+0b8 <[^>]+> dbd6      	blt.n	0+068 <[^>]+>
+0+0ba <[^>]+> dcd5      	bgt.n	0+068 <[^>]+>
+0+0bc <[^>]+> ddd4      	ble.n	0+068 <[^>]+>
+0+0be <[^>]+> d8d3      	bhi.n	0+068 <[^>]+>
+0+0c0 <[^>]+> d3d2      	bcc.n	0+068 <[^>]+>
+0+0c2 <[^>]+> d3d1      	bcc.n	0+068 <[^>]+>
+0+0c4 <[^>]+> e7d0      	b.n	0+068 <[^>]+>
+0+0c6 <[^>]+> 00ac      	lsls	r4, r5, #2
+0+0c8 <[^>]+> 1c9a      	adds	r2, r3, #2
+0+0ca <[^>]+> b07f      	add	sp, #508
+0+0cc <[^>]+> b0ff      	sub	sp, #508
+0+0ce <[^>]+> a8ff      	add	r0, sp, #1020
+0+0d0 <[^>]+> a0ff      	add	r0, pc, #1020	\(adr r0, 0+4d0 <[^>]+>\)
+0+0d2 <[^>]+> b01a      	add	sp, #104
+0+0d4 <[^>]+> b09a      	sub	sp, #104
+0+0d6 <[^>]+> a81a      	add	r0, sp, #104
+0+0d8 <[^>]+> a01a      	add	r0, pc, #104	\(adr r0, 0+144 <[^>]+>\)
+0+0da <[^>]+> 3168      	adds	r1, #104
+0+0dc <[^>]+> 2668      	movs	r6, #104
+0+0de <[^>]+> 2f68      	cmp	r7, #104
+0+0e0 <[^>]+> 46c0      	nop			\(mov r8, r8\)
+0+0e2 <[^>]+> 46c0      	nop			\(mov r8, r8\)
+0+0e4 <[^>]+> eafffffe 	b	0+0e4 <[^>]+>
+0+0e8 <[^>]+> ea000011 	b	0+134 <[^>]+>
+0+0ec <[^>]+> ebfffffc 	bl	0+0e4 <[^>]+>
+0+0f0 <[^>]+> eb00000f 	bl	0+134 <[^>]+>
+0+0f4 <[^>]+> e12fff10 	bx	r0
+.*: R_ARM_V4BX.*
+0+0f8 <[^>]+> ef123456 	(swi|svc)	0x00123456
+0+0fc <[^>]+> a004      	add	r0, pc, #16	\(adr r0, 0+110 <[^>]+>\)
+0+0fe <[^>]+> e77f      	b.n	0+000 <[^>]+>
+0+100 <[^>]+> e018      	b.n	0+134 <[^>]+>
+0+102 <[^>]+> f7ff ff7d 	bl	0+000 <[^>]+>
+0+106 <[^>]+> f000 f815 	bl	0+134 <[^>]+>
+0+10a <[^>]+> 4700      	bx	r0
+0+10c <[^>]+> dfff      	(swi|svc)	255
+0+10e <[^>]+> 46c0      	nop			\(mov r8, r8\)
+0+110 <[^>]+> d010      	beq.n	0+134 <[^>]+>
+0+112 <[^>]+> d10f      	bne.n	0+134 <[^>]+>
+0+114 <[^>]+> d20e      	bcs.n	0+134 <[^>]+>
+0+116 <[^>]+> d30d      	bcc.n	0+134 <[^>]+>
+0+118 <[^>]+> d40c      	bmi.n	0+134 <[^>]+>
+0+11a <[^>]+> d50b      	bpl.n	0+134 <[^>]+>
+0+11c <[^>]+> d60a      	bvs.n	0+134 <[^>]+>
+0+11e <[^>]+> d709      	bvc.n	0+134 <[^>]+>
+0+120 <[^>]+> d808      	bhi.n	0+134 <[^>]+>
+0+122 <[^>]+> d907      	bls.n	0+134 <[^>]+>
+0+124 <[^>]+> da06      	bge.n	0+134 <[^>]+>
+0+126 <[^>]+> dc05      	bgt.n	0+134 <[^>]+>
+0+128 <[^>]+> db04      	blt.n	0+134 <[^>]+>
+0+12a <[^>]+> dc03      	bgt.n	0+134 <[^>]+>
+0+12c <[^>]+> dd02      	ble.n	0+134 <[^>]+>
+0+12e <[^>]+> d801      	bhi.n	0+134 <[^>]+>
+0+130 <[^>]+> d300      	bcc.n	0+134 <[^>]+>
+0+132 <[^>]+> d3ff      	bcc.n	0+134 <[^>]+>
+0+134 <[^>]+> f000 fc00 	bl	0+938 <[^>]+>
+	\.\.\.
+0+938 <[^>]+> f7ff fbfc 	bl	0+134 <[^>]+>
+0+93c <[^>]+> 4801      	ldr	r0, \[pc, #4\]	\(0+944 <[^>]+>\)
+0+93e <[^>]+> 4801      	ldr	r0, \[pc, #4\]	\(0+944 <[^>]+>\)
+0+940 <[^>]+> 4801      	ldr	r0, \[pc, #4\]	\(0+948 <[^>]+>\)
+0+942 <[^>]+> 4801      	ldr	r0, \[pc, #4\]	\(0+948 <[^>]+>\)
+0+944 <[^>]+> 46c0      	nop			\(mov r8, r8\)
+0+946 <[^>]+> 46c0      	nop			\(mov r8, r8\)
Index: gas/testsuite/gas/arm/thumb.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb.d,v
retrieving revision 1.10
diff -u -p -r1.10 thumb.d
--- gas/testsuite/gas/arm/thumb.d	6 Jun 2007 17:36:54 -0000	1.10
+++ gas/testsuite/gas/arm/thumb.d	20 Feb 2008 14:47:46 -0000
@@ -2,7 +2,8 @@
 # as: -mcpu=arm7t
 # objdump: -dr --prefix-addresses --show-raw-insn
 # The arm-aout and arm-pe ports do not support Thumb branch relocations.
-# not-target: *-*-*aout* *-*-pe
+# EABI targets have their own variant.
+# not-target: *-*-*aout* *-*-pe *-*-*eabi *-*-symbianelf
 
 .*: +file format .*arm.*
 
Index: gas/testsuite/gas/arm/v4bx.d
===================================================================
RCS file: gas/testsuite/gas/arm/v4bx.d
diff -N gas/testsuite/gas/arm/v4bx.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/v4bx.d	20 Feb 2008 14:47:46 -0000
@@ -0,0 +1,10 @@
+# objdump: -dr --prefix-addresses --show-raw-insn
+# as: -meabi=4 --fix-v4bx
+# This test is only valid on ELF based ports.
+#not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+00 <[^>]+> e12fff1e 	bx	lr
+			0: R_ARM_V4BX	\*ABS\*
Index: gas/testsuite/gas/arm/v4bx.s
===================================================================
RCS file: gas/testsuite/gas/arm/v4bx.s
diff -N gas/testsuite/gas/arm/v4bx.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/v4bx.s	20 Feb 2008 14:47:46 -0000
@@ -0,0 +1,4 @@
+	.arch armv4
+	.text
+foo:	
+	bx	lr
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.206
diff -u -p -r1.206 ld.texinfo
--- ld/ld.texinfo	25 Jan 2008 12:03:37 -0000	1.206
+++ ld/ld.texinfo	20 Feb 2008 14:47:49 -0000
@@ -5584,6 +5584,21 @@ linker, which causes v4t @code{BX rM} in
 In the former case, the switch should not be used, and @samp{R_ARM_V4BX}
 relocations are ignored.
 
+@cindex FIX_V4BX_INTERWORKING
+@kindex --fix-v4bx-interworking
+Replace @code{BX rM} instructions identified by @samp{R_ARM_V4BX}
+relocations with a branch to the following veneer:
+
+@smallexample
+TST rM, #1
+MOVEQ PC, rM
+BX Rn
+@end smallexample
+
+This allows generation of libraries/applications that work on ARMv4 cores
+and are still interworking safe.  Note that the above veneer clobbers the
+condition flags, so may cause incorrect progrm behavior in rare cases.
+
 @cindex USE_BLX
 @kindex --use-blx
 The @samp{--use-blx} switch enables the linker to use ARM/Thumb
Index: ld/emulparams/armelf.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/armelf.sh,v
retrieving revision 1.20
diff -u -p -r1.20 armelf.sh
--- ld/emulparams/armelf.sh	29 Jun 2007 16:29:17 -0000	1.20
+++ ld/emulparams/armelf.sh	20 Feb 2008 14:47:49 -0000
@@ -6,7 +6,7 @@ LITTLE_OUTPUT_FORMAT="elf32-littlearm"
 TEXT_START_ADDR=0x8000
 TEMPLATE_NAME=elf32
 EXTRA_EM_FILE=armelf
-OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer)'
+OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)'
 OTHER_BSS_SYMBOLS='__bss_start__ = .;'
 OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
 OTHER_END_SYMBOLS='__end__ = . ;'
Index: ld/emulparams/armelf_linux.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/armelf_linux.sh,v
retrieving revision 1.17
diff -u -p -r1.17 armelf_linux.sh
--- ld/emulparams/armelf_linux.sh	29 Jan 2007 16:28:40 -0000	1.17
+++ ld/emulparams/armelf_linux.sh	20 Feb 2008 14:47:49 -0000
@@ -11,7 +11,7 @@ GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
 
 DATA_START_SYMBOLS='__data_start = . ;';
-OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer)'
+OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)'
 OTHER_BSS_SYMBOLS='__bss_start__ = .;'
 OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
 OTHER_END_SYMBOLS='__end__ = . ;'
Index: ld/emulparams/armnto.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/armnto.sh,v
retrieving revision 1.6
diff -u -p -r1.6 armnto.sh
--- ld/emulparams/armnto.sh	29 Jan 2007 16:28:40 -0000	1.6
+++ ld/emulparams/armnto.sh	20 Feb 2008 14:47:49 -0000
@@ -6,7 +6,7 @@ LITTLE_OUTPUT_FORMAT="elf32-littlearm"
 TEXT_START_ADDR=0x00100000
 TEMPLATE_NAME=elf32
 EXTRA_EM_FILE=armelf
-OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer)'
+OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)'
 OTHER_BSS_SYMBOLS='__bss_start__ = .;'
 OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
 OTHER_END_SYMBOLS='__end__ = . ;'
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.60
diff -u -p -r1.60 armelf.em
--- ld/emultempl/armelf.em	15 Feb 2008 03:35:53 -0000	1.60
+++ ld/emultempl/armelf.em	20 Feb 2008 14:47:50 -0000
@@ -264,6 +264,7 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_VFP11_DENORM_FIX		308
 #define OPTION_NO_ENUM_SIZE_WARNING	309
 #define OPTION_PIC_VENEER		310
+#define OPTION_FIX_V4BX_INTERWORKING	311
 '
 
 PARSE_AND_LIST_SHORTOPTS=p
@@ -276,6 +277,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "target1-abs", no_argument, NULL, OPTION_TARGET1_ABS},
   { "target2", required_argument, NULL, OPTION_TARGET2},
   { "fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX},
+  { "fix-v4bx-interworking", no_argument, NULL, OPTION_FIX_V4BX_INTERWORKING},
   { "use-blx", no_argument, NULL, OPTION_USE_BLX},
   { "vfp11-denorm-fix", required_argument, NULL, OPTION_VFP11_DENORM_FIX},
   { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
@@ -289,6 +291,7 @@ PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("  --target1=abs               Interpret R_ARM_TARGET1 as R_ARM_ABS32\n"));
   fprintf (file, _("  --target2=<type>            Specify definition of R_ARM_TARGET2\n"));
   fprintf (file, _("  --fix-v4bx                  Rewrite BX rn as MOV pc, rn for ARMv4\n"));
+  fprintf (file, _("  --fix-v4bx-interworking     Rewrite BX rn branch to ARMv4 interworking veneer\n"));
   fprintf (file, _("  --use-blx                   Enable use of BLX instructions\n"));
   fprintf (file, _("  --vfp11-denorm-fix          Specify how to fix VFP11 denorm erratum\n"));
   fprintf (file, _("  --no-enum-size-warning      Don'\''t warn about objects with incompatible"
@@ -325,6 +328,10 @@ PARSE_AND_LIST_ARGS_CASES='
       fix_v4bx = 1;
       break;
 
+    case OPTION_FIX_V4BX_INTERWORKING:
+      fix_v4bx = 2;
+      break;
+
     case OPTION_USE_BLX:
       use_blx = 1;
       break;
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.31
diff -u -p -r1.31 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	24 Jul 2007 12:45:58 -0000	1.31
+++ ld/testsuite/ld-arm/arm-elf.exp	20 Feb 2008 14:47:50 -0000
@@ -173,6 +173,9 @@ set armelftests {
      {"callweak" "-static -T arm.ld" "" {callweak.s}
       {{objdump -dr callweak.d}}
       "callweak"}
+    {"ARMv4 interworking" "-static -T arm.ld --fix-v4bx-interworking" "--fix-v4bx -meabi=4" {armv4-bx.s}
+     {{objdump -d armv4-bx.d}}
+     "armv4-bx"}
 }
 
 run_ld_link_tests $armelftests
Index: ld/testsuite/ld-arm/arm.ld
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm.ld,v
retrieving revision 1.3
diff -u -p -r1.3 arm.ld
--- ld/testsuite/ld-arm/arm.ld	11 May 2006 15:17:34 -0000	1.3
+++ ld/testsuite/ld-arm/arm.ld	20 Feb 2008 14:47:50 -0000
@@ -11,6 +11,7 @@ SECTIONS
     *(.text)
     *(.after)
     *(.glue_7)
+    *(.v4_bx)
   } =0
   . = 0x9000;
   .got            : { *(.got) *(.got.plt)}
Index: ld/testsuite/ld-arm/armv4-bx.d
===================================================================
RCS file: ld/testsuite/ld-arm/armv4-bx.d
diff -N ld/testsuite/ld-arm/armv4-bx.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/armv4-bx.d	20 Feb 2008 14:47:50 -0000
@@ -0,0 +1,19 @@
+
+.*: .*file format elf32-(big|little)arm
+
+Disassembly of section \.text:
+
+00008000 <_start>:
+    8000:	ea000001 	b	800c \<__bx_r14\>
+    8004:	ea000003 	b	8018 \<__bx_r0\>
+    8008:	0a000002 	beq	8018 \<__bx_r0\>
+
+0000800c <__bx_r14>:
+    800c:	e31e0001 	tst	lr, #1	; 0x1
+    8010:	01a0f00e 	moveq	pc, lr
+    8014:	e12fff1e 	bx	lr
+
+00008018 <__bx_r0>:
+    8018:	e3100001 	tst	r0, #1	; 0x1
+    801c:	01a0f000 	moveq	pc, r0
+    8020:	e12fff10 	bx	r0
Index: ld/testsuite/ld-arm/armv4-bx.s
===================================================================
RCS file: ld/testsuite/ld-arm/armv4-bx.s
diff -N ld/testsuite/ld-arm/armv4-bx.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/armv4-bx.s	20 Feb 2008 14:47:50 -0000
@@ -0,0 +1,8 @@
+.text
+.arch armv4
+.global _start
+.type _start, %function
+_start:
+bx lr
+bx r0
+bxeq r0

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