This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[RFA/ARM]: Patch to workaround ARM1176 BLX (immediate) Thumb to ARM issue
- From: Matthew Gretton-Dann <matthew dot gretton-dann at arm dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: Richard Earnshaw <Richard dot Earnshaw at arm dot com>
- Date: Wed, 27 Jul 2011 17:07:57 +0100
- Subject: [RFA/ARM]: Patch to workaround ARM1176 BLX (immediate) Thumb to ARM issue
Hi,
Please can someone review and approve the attached patch?
The patch does the following:
* Adds a command line option to ld --[no-]fix-erratum-760522, which
is enabled by default.
* When the option is on the linker will only use BLX if the target
architecture (derived from the object files) is v6T2, v7, or
greater.
* --use-blx keeps its current meaning and will override this
option.
A description of the issue can be found on the ARM website at:
http://infocenter.arm.com/help/topic/com.arm.doc.uan0002a/UAN002A_1176-pan_use_of_blx.pdf
Alternatively by following:
http://infocenter.arm.com/
User Assistance Notes
ARM11 Processors
ARM1176JZ-S and ARM1176JFZ-S Programmer Advice Note
The workaround has been applied to more cores than just ARM1176 to
ensure appropriate forwards compatibility from earlier CPUs.
Thanks,
Matt
bfd/ChangeLog:
2011-07-27 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* bfd-in.h (bfd_elf32_arm_set_target_relocs): Update prototype.
* bfd-in2.h (bfd_elf32_arm_set_target_relocs): Likewise.
* elf32-arm.c (elf32_arm_link_hash_table): New field.
(elf232_arm_link_hash_table_create): Initialise new field.
(check_use_blx): Change test depending on fix_erratum_760522.
(bfd_elf32_arm_set_target_relocs): Set fix_erratum_760522 from
command line options.
ld/ChangeLog:
2011-07-27 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* emultempl/armelf.em (fix_erratum_760522): New variable.
(arm_elf_create_output_section_statements): Pass
fix_erratum_760522 option to bfd backend.
(OPTION_FIX_ERRATUM_760522): New define.
(OPTION_NO_FIX_ERRATUM_760522): Likewise.
(PARSE_AND_LIST_LONGOPTS): Add --[no-]fix-erratum-760522
command line options.
(PARSE_AND_LIST_OPTIONS): Likewise.
(PARSE_AND_LIST_ARGS_CASES): Likewise.
ld/testsuite/ChangeLog:
2011-07-27 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* ld-arm/arm-elf.exp (armelftests): Update for new command-line
options.
(armeabitests): Update for new command-line options, and add
new test cases.
* ld-arm/erratum-760522-off.d: New test case.
* ld-arm/erratum-760522-on.d: Likewise.
* ld-arm/erratum-760522.s: Likewise.
Thanks,
Matt
--
Matthew Gretton-Dann
Principal Engineer, PD Software - Tools, ARM Ltd
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 21b7cc2..f375d2f 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -869,7 +869,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
void bfd_elf32_arm_set_target_relocs
(bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
- int, int, int, int);
+ int, int, int, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 6b7be67..3d5759d 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -876,7 +876,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
void bfd_elf32_arm_set_target_relocs
(bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
- int, int, int, int);
+ int, int, int, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 0ddd0cf..c6370c2 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2776,6 +2776,9 @@ struct elf32_arm_link_hash_table
/* Whether we should fix the Cortex-A8 Thumb-2 branch/TLB erratum. */
int fix_cortex_a8;
+ /* Whether we should fix erratum 760522. */
+ int fix_erratum_760522;
+
/* Nonzero if the ARM/Thumb BLX instructions are available for use. */
int use_blx;
@@ -3315,6 +3318,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
ret->vfp11_erratum_glue_size = 0;
ret->num_vfp11_fixes = 0;
ret->fix_cortex_a8 = 0;
+ ret->fix_erratum_760522 = 0;
ret->bfd_of_glue_owner = NULL;
ret->byteswap_code = 0;
ret->target1_is_rel = 0;
@@ -5930,9 +5934,21 @@ bfd_elf32_arm_get_bfd_for_interworking (bfd *abfd, struct bfd_link_info *info)
static void
check_use_blx (struct elf32_arm_link_hash_table *globals)
{
- if (bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
- Tag_CPU_arch) > 2)
- globals->use_blx = 1;
+ int cpu_arch;
+
+ cpu_arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch);
+
+ if (globals->fix_erratum_760522)
+ {
+ if (cpu_arch == 8 || cpu_arch > 9)
+ globals->use_blx = 1;
+ }
+ else
+ {
+ if (cpu_arch > 2)
+ globals->use_blx = 1;
+ }
}
bfd_boolean
@@ -6786,7 +6802,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
int use_blx,
bfd_arm_vfp11_fix vfp11_fix,
int no_enum_warn, int no_wchar_warn,
- int pic_veneer, int fix_cortex_a8)
+ int pic_veneer, int fix_cortex_a8,
+ int fix_erratum_760522)
{
struct elf32_arm_link_hash_table *globals;
@@ -6811,6 +6828,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
globals->vfp11_fix = vfp11_fix;
globals->pic_veneer = pic_veneer;
globals->fix_cortex_a8 = fix_cortex_a8;
+ globals->fix_erratum_760522 = fix_erratum_760522;
BFD_ASSERT (is_arm_elf (output_bfd));
elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 948bf8d..b2063d7 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -42,6 +42,7 @@ static int no_enum_size_warning = 0;
static int no_wchar_size_warning = 0;
static int pic_veneer = 0;
static int merge_exidx_entries = -1;
+static int fix_erratum_760522 = 1;
static void
gld${EMULATION_NAME}_before_parse (void)
@@ -464,7 +465,8 @@ arm_elf_create_output_section_statements (void)
target2_type, fix_v4bx, use_blx,
vfp11_denorm_fix, no_enum_size_warning,
no_wchar_size_warning,
- pic_veneer, fix_cortex_a8);
+ pic_veneer, fix_cortex_a8,
+ fix_erratum_760522);
stub_file = lang_add_input_file ("linker stubs",
lang_input_file_is_fake_enum,
@@ -529,6 +531,8 @@ PARSE_AND_LIST_PROLOGUE='
#define OPTION_FIX_CORTEX_A8 314
#define OPTION_NO_FIX_CORTEX_A8 315
#define OPTION_NO_MERGE_EXIDX_ENTRIES 316
+#define OPTION_FIX_ERRATUM_760522 317
+#define OPTION_NO_FIX_ERRATUM_760522 318
'
PARSE_AND_LIST_SHORTOPTS=p
@@ -551,6 +555,8 @@ PARSE_AND_LIST_LONGOPTS='
{ "fix-cortex-a8", no_argument, NULL, OPTION_FIX_CORTEX_A8 },
{ "no-fix-cortex-a8", no_argument, NULL, OPTION_NO_FIX_CORTEX_A8 },
{ "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES },
+ { "fix-erratum-760522", no_argument, NULL, OPTION_FIX_ERRATUM_760522 },
+ { "no-fix-erratum-760522", no_argument, NULL, OPTION_NO_FIX_ERRATUM_760522 },
'
PARSE_AND_LIST_OPTIONS='
@@ -579,7 +585,7 @@ PARSE_AND_LIST_OPTIONS='
));
fprintf (file, _(" --[no-]fix-cortex-a8 Disable/enable Cortex-A8 Thumb-2 branch erratum fix\n"));
fprintf (file, _(" --no-merge-exidx-entries Disable merging exidx entries\n"));
-
+ fprintf (file, _(" --[no-]fix-erratum-760522 Disable/enable Erratum 760522 fix\n"));
'
PARSE_AND_LIST_ARGS_CASES='
@@ -662,7 +668,15 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_NO_MERGE_EXIDX_ENTRIES:
merge_exidx_entries = 0;
+ break;
+ case OPTION_FIX_ERRATUM_760522:
+ fix_erratum_760522 = 1;
+ break;
+
+ case OPTION_NO_FIX_ERRATUM_760522:
+ fix_erratum_760522 = 0;
+ break;
'
# We have our own before_allocation etc. functions, but they call
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 8b8495e..4d1002c 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -137,7 +137,7 @@ set armelftests {
{"arm-rel32" "-shared -T arm-dyn.ld" "" {arm-rel32.s}
{{objdump -Rsj.data arm-rel32.d}}
"arm-rel32"}
- {"arm-call" "-static -T arm.ld" "-meabi=4" {arm-call1.s arm-call2.s}
+ {"arm-call" "--no-fix-erratum-760522 -static -T arm.ld" "-meabi=4" {arm-call1.s arm-call2.s}
{{objdump -d arm-call.d}}
"arm-call"}
{"TLS shared library" "-shared -T arm-lib.ld" "" {tls-lib.s}
@@ -149,16 +149,16 @@ set armelftests {
{"TLS gnu shared library got" "-shared -T arm-dyn.ld" "" {tls-gdesc-got.s}
{{objdump "-fDR -j .got" tls-gdesc-got.d}}
"tls-lib2-got.so"}
- {"TLS gnu shared library inlined trampoline" "-shared -T arm-dyn.ld" "" {tls-descseq.s}
+ {"TLS gnu shared library inlined trampoline" "--no-fix-erratum-760522 -shared -T arm-dyn.ld" "" {tls-descseq.s}
{{objdump -fdw tls-descseq.d} {objdump -Rw tls-descseq.r}}
"tls-lib2inline.so"}
- {"TLS shared library gdesc local" "-shared -T arm-dyn.ld" "" {tls-lib-loc.s}
+ {"TLS shared library gdesc local" "--no-fix-erratum-760522 -shared -T arm-dyn.ld" "" {tls-lib-loc.s}
{{objdump -fdw tls-lib-loc.d} {objdump -Rw tls-lib-loc.r}}
"tls-lib-loc.so"}
{"TLS gnu GD to IE relaxation" "-static -T arm-dyn.ld" "" {tls-gdierelax.s}
{{objdump -fdw tls-gdierelax.d}}
"tls-app-rel-ie"}
- {"TLS gnu GD to IE shared relaxation" "-shared -T arm-dyn.ld" "" {tls-gdierelax2.s}
+ {"TLS gnu GD to IE shared relaxation" "--no-fix-erratum-760522 -shared -T arm-dyn.ld" "" {tls-gdierelax2.s}
{{objdump -fdw tls-gdierelax2.d}}
"tls-app-rel-ie2"}
{"TLS gnu GD to LE relaxation" "-T arm-dyn.ld" "" {tls-gdlerelax.s}
@@ -507,7 +507,7 @@ set armeabitests {
{"MOVW/MOVT against shared libraries" "tmpdir/arm-lib.so" "" {arm-app-movw.s}
{{objdump -Rw arm-app.r}}
"arm-app-movw"}
- {"Thumb-2-as-Thumb-1 BL" "-Ttext 0x1000 --section-start .foo=0x100100c" "" {thumb2-bl-as-thumb1-bad.s}
+ {"Thumb-2-as-Thumb-1 BL" "--no-fix-erratum-760522 -Ttext 0x1000 --section-start .foo=0x100100c" "" {thumb2-bl-as-thumb1-bad.s}
{{objdump -d thumb2-bl-as-thumb1-bad.d}}
"thumb2-bl-as-thumb1-bad"}
{"Thumb-2 BL" "-Ttext 0x1000 --section-start .foo=0x100100c" "" {thumb2-bl-bad.s}
@@ -530,7 +530,7 @@ set armeabitests {
{"ARM-Thumb farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "" {farcall-arm-thumb.s}
{{objdump -d farcall-arm-thumb.d}}
"farcall-arm-thumb"}
- {"ARM-Thumb farcall with BLX" "-Ttext 0x1000 --section-start .foo=0x2001014" "-march=armv5t" {farcall-arm-thumb.s}
+ {"ARM-Thumb farcall with BLX" "--no-fix-erratum-760522 -Ttext 0x1000 --section-start .foo=0x2001014" "-march=armv5t" {farcall-arm-thumb.s}
{{objdump -d farcall-arm-thumb-blx.d}}
"farcall-arm-thumb-blx"}
{"ARM-Thumb farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "" {farcall-arm-thumb.s}
@@ -540,7 +540,7 @@ set armeabitests {
{{objdump -d farcall-arm-thumb-blx-pic-veneer.d}}
"farcall-arm-thumb-blx-pic-veneer"}
- {"Thumb-Thumb farcall with BLX" "-Ttext 0x1000 --section-start .foo=0x2001014" "-march=armv5t" {farcall-thumb-thumb.s}
+ {"Thumb-Thumb farcall with BLX" "--no-fix-erratum-760522 -Ttext 0x1000 --section-start .foo=0x2001014" "-march=armv5t" {farcall-thumb-thumb.s}
{{objdump -d farcall-thumb-thumb-blx.d}}
"farcall-thumb-thumb-blx"}
{"Thumb-Thumb farcall M profile" "-Ttext 0x1000 --section-start .foo=0x2001014" "-march=armv7-m" {farcall-thumb-thumb.s}
@@ -552,7 +552,7 @@ set armeabitests {
{"Thumb-Thumb farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-march=armv4t" {farcall-thumb-thumb.s}
{{objdump -d farcall-thumb-thumb.d}}
"farcall-thumb-thumb"}
- {"Thumb-Thumb farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv5t" {farcall-thumb-thumb.s}
+ {"Thumb-Thumb farcall with BLX (PIC veneer)" "--no-fix-erratum-760522 -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv5t" {farcall-thumb-thumb.s}
{{objdump -d farcall-thumb-thumb-blx-pic-veneer.d}}
"farcall-thumb-thumb-blx-pic-veneer"}
{"Thumb-Thumb farcall M profile (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv7-m" {farcall-thumb-thumb.s}
@@ -574,10 +574,10 @@ set armeabitests {
{"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"}
- {"Thumb-ARM farcall with BLX" "-Ttext 0x1c01010 --section-start .foo=0x2001014" "-W -march=armv5t" {farcall-thumb-arm.s}
+ {"Thumb-ARM farcall with BLX" "--no-fix-erratum-760522 -Ttext 0x1c01010 --section-start .foo=0x2001014" "-W -march=armv5t" {farcall-thumb-arm.s}
{{objdump -d farcall-thumb-arm-blx.d}}
"farcall-thumb-arm-blx"}
- {"Thumb-ARM farcall with BLX (PIC veneer)" "-Ttext 0x1c01010 --section-start .foo=0x2001014 --pic-veneer" "-W -march=armv5t" {farcall-thumb-arm.s}
+ {"Thumb-ARM farcall with BLX (PIC veneer)" "--no-fix-erratum-760522 -Ttext 0x1c01010 --section-start .foo=0x2001014 --pic-veneer" "-W -march=armv5t" {farcall-thumb-arm.s}
{{objdump -d farcall-thumb-arm-blx-pic-veneer.d}}
"farcall-thumb-arm-blx-pic-veneer"}
{"Thumb-ARM farcall (PIC veneer)" "-Ttext 0x1c01010 --section-start .foo=0x2001014 --pic-veneer" "-W" {farcall-thumb-arm.s}
@@ -617,7 +617,7 @@ set armeabitests {
{{objdump -fdw farcall-mixed-lib-v4t.d}}
"farcall-mixed-lib.so"}
- {"Mixed ARM/Thumb shared library with long branches (v5t)" "-shared -T arm-lib.ld" "-march=armv5t"
+ {"Mixed ARM/Thumb shared library with long branches (v5t)" "--no-fix-erratum-760522 -shared -T arm-lib.ld" "-march=armv5t"
{farcall-mixed-lib1.s farcall-mixed-lib2.s}
{{objdump -fdw farcall-mixed-lib.d}}
"farcall-mixed-lib.so"}
@@ -627,24 +627,24 @@ set armeabitests {
"farcall-data"}
{"R_ARM_THM_JUMP24 Relocation veneers: Short 1"
- "--section-start destsect=0x00009000 --section-start .text=0x8000"
+ "--no-fix-erratum-760522 --section-start destsect=0x00009000 --section-start .text=0x8000"
"-march=armv7-a -mthumb"
{jump-reloc-veneers.s}
{{objdump -d jump-reloc-veneers-short1.d}}
"jump-reloc-veneers-short1"}
{"R_ARM_THM_JUMP24 Relocation veneers: Short 2"
- "--section-start destsect=0x00900000 --section-start .text=0x8000"
+ "--no-fix-erratum-760522 --section-start destsect=0x00900000 --section-start .text=0x8000"
"-march=armv7-a -mthumb"
{jump-reloc-veneers.s}
{{objdump -d jump-reloc-veneers-short2.d}}
"jump-reloc-veneers-short2"}
{"R_ARM_THM_JUMP24 Relocation veneers: Long"
- "--section-start destsect=0x09000000 --section-start .text=0x8000"
+ "--no-fix-erratum-760522 --section-start destsect=0x09000000 --section-start .text=0x8000"
"-march=armv7-a -mthumb"
{jump-reloc-veneers.s}
{{objdump -d jump-reloc-veneers-long.d}}
"jump-reloc-veneers-long"}
- {"TLS gnu shared library" "-shared -T arm-dyn.ld" "" {tls-gdesc.s}
+ {"TLS gnu shared library" "--no-fix-erratum-760522 -shared -T arm-dyn.ld" "" {tls-gdesc.s}
{{objdump -fdw tls-gdesc.d} {objdump -Rw tls-gdesc.r}}
"tls-lib2.so"}
{"TLS gnu shared library non-lazy" "-z now -shared -T arm-dyn.ld" "" {tls-gdesc.s}
@@ -659,6 +659,31 @@ set armeabitests {
{"TLS thumb1" "-shared -T arm-dyn.ld --section-start .foo=0x4001000" "" {tls-thumb1.s}
{{objdump -fdw tls-thumb1.d}}
"tls-thumb1"}
+
+ {"erratum 760522 fix (default for v6z)" "--section-start=.foo=0x2001014"
+ "-march=armv6z" {erratum-760522.s}
+ {{objdump -d erratum-760522-on.d}}
+ "erratum-760522-1"}
+ {"erratum 760522 fix (explicitly on at v6z)" "--section-start=.foo=0x2001014 --fix-erratum-760522"
+ "-march=armv6z" {erratum-760522.s}
+ {{objdump -d erratum-760522-on.d}}
+ "erratum-760522-2"}
+ {"erratum 760522 fix (explicitly off at v6z)" "--section-start=.foo=0x2001014 --no-fix-erratum-760522"
+ "-march=armv6z" {erratum-760522.s}
+ {{objdump -d erratum-760522-off.d}}
+ "erratum-760522-3"}
+ {"erratum 760522 fix (default for v5)" "--section-start=.foo=0x2001014 "
+ "-march=armv5te" {erratum-760522.s}
+ {{objdump -d erratum-760522-on.d}}
+ "erratum-760522-4"}
+ {"erratum 760522 fix (default for v7-a)" "--section-start=.foo=0x2001014 "
+ "-march=armv7-a" {erratum-760522.s}
+ {{objdump -d erratum-760522-off.d}}
+ "erratum-760522-5"}
+ {"erratum 760522 fix (default for ARM1156)" "--section-start=.foo=0x2001014 "
+ "-mcpu=arm1156t2f-s" {erratum-760522.s}
+ {{objdump -d erratum-760522-off.d}}
+ "erratum-760522-6"}
}
run_ld_link_tests $armeabitests
diff --git a/ld/testsuite/ld-arm/erratum-760522-off.d b/ld/testsuite/ld-arm/erratum-760522-off.d
new file mode 100644
index 0000000..3b45a3b
--- /dev/null
+++ b/ld/testsuite/ld-arm/erratum-760522-off.d
@@ -0,0 +1,17 @@
+
+.*: file format elf32-littlearm
+
+
+Disassembly of section .foo:
+
+[0-9a-f]+ <_start>:
+ [0-9a-f]+: f000 e800 blx 2001018 <__func_to_branch_to_veneer>
+
+[0-9a-f]+ <__func_to_branch_to_veneer>:
+ [0-9a-f]+: e51ff004 ldr pc, \[pc, #-4\] ; 200101c <__func_to_branch_to_veneer\+0x4>
+ [0-9a-f]+: 00008000 .word 0x00008000
+
+Disassembly of section .text:
+
+[0-9a-f]+ <func_to_branch_to>:
+ [0-9a-f]+: e12fff1e bx lr
diff --git a/ld/testsuite/ld-arm/erratum-760522-on.d b/ld/testsuite/ld-arm/erratum-760522-on.d
new file mode 100644
index 0000000..c4e7870
--- /dev/null
+++ b/ld/testsuite/ld-arm/erratum-760522-on.d
@@ -0,0 +1,20 @@
+
+.+: file format elf32-littlearm
+
+
+Disassembly of section .foo:
+
+[0-9a-f]+ <_start>:
+ [0-9a-f]+: f000 f800 bl 2001018 <__func_to_branch_to_veneer>
+
+[0-9a-f]+ <__func_to_branch_to_veneer>:
+ [0-9a-f]+: 4778 bx pc
+ [0-9a-f]+: 46c0 nop ; \(mov r8, r8\)
+ [0-9a-f]+: e51ff004 ldr pc, \[pc, #-4\] ; 2001020 <__func_to_branch_to_veneer\+0x8>
+ [0-9a-f]+: 00008000 .word 0x00008000
+ [0-9a-f]+: 00000000 .word 0x00000000
+
+Disassembly of section .text:
+
+[0-9a-f]+ <func_to_branch_to>:
+ [0-9a-f]+: e12fff1e bx lr
diff --git a/ld/testsuite/ld-arm/erratum-760522.s b/ld/testsuite/ld-arm/erratum-760522.s
new file mode 100644
index 0000000..96e0328
--- /dev/null
+++ b/ld/testsuite/ld-arm/erratum-760522.s
@@ -0,0 +1,15 @@
+ .syntax unified
+ .globl _start
+ .globl func_to_branch_to
+
+ .arm
+ .text
+func_to_branch_to:
+ bx lr
+
+ .thumb
+ .section .foo, "xa"
+ .thumb_func
+_start:
+ bl func_to_branch_to
+