From 48229727d832a7181bfa8e36a77b480cd4efdf74 Mon Sep 17 00:00:00 2001 From: Julian Brown Date: Fri, 22 May 2009 11:58:45 +0000 Subject: [PATCH] ld/ * emultempl/armelf.em (fix_cortex_a8): New. (arm_elf_before_allocation): Call bfd_elf32_arm_set_cortex_a8_fix. (arm_elf_create_output_section_statements): Add fix_cortex_a8 to bfd_elf32_arm_set_target_relocs. (OPTION_FIX_CORTEX_A8, OPTION_NO_FIX_CORTEX_A8): New. (PARSE_AND_LIST_LONGOPTS): Add [no-]fix-cortex-a8 options. (PARSE_AND_LIST_OPTIONS): Add [no-]fix-cortex-a8 options. (PARSE_AND_LIST_ARGS_CASES): Handle OPTION_[NO_]FIX_CORTEX_A8. * ld.texinfo (--[no-]fix-cortex-a8): Briefly document new options. bfd/ * elf32-arm.c (THUMB16_BCOND_INSN, THUMB32_INSN, THUMB32_B_INSN): New macros. (elf32_arm_stub_a8_veneer_b_cond, elf32_arm_stub_a8_veneer_b) (elf32_arm_stub_a8_veneer_blx): New stub sequences. (elf32_arm_stub_type): Add arm_stub_a8_veneer_b_cond, arm_stub_a8_veneer_b and arm_stub_a8_veneer_blx. (elf32_arm_stub_hash_entry): Add target_addend, orig_insn fields. (a8_erratum_fix, a8_erratum_reloc): New structs. (elf32_arm_link_hash_table): Add a8_erratum_fixes, num_a8_erratum_fixes, fix_cortex_a8 fields. (elf32_arm_link_hash_table_create): Zero fix_cortex_a8. (elf32_arm_add_stub): Split into two parts, creating... (elf32_arm_create_or_find_stub_sec): New function. (elf32_arm_final_link_relocate): Add forward declaration. (arm_build_one_stub): Add support for THUMB32_TYPE, Thumb-2 relocations, multiple relocations per stub. (find_stub_size_and_template): New (using parts of arm_size_one_stub). (arm_size_one_stub): Use find_stub_size_and_template. (a8_reloc_compare): New. (find_thumb_glue): Add forward declaration. (cortex_a8_erratum_scan): New. (elf32_arm_size_stubs): Add Cortex-A8 erratum workaround support. (bfd_elf32_arm_set_cortex_a8_fix): New. (bfd_elf32_arm_set_target_relocs): Add fix_cortex_a8 argument. (arm_map_one_stub): Add THUMB32_TYPE support. (a8_branch_to_stub_data): New. (make_branch_to_a8_stub): New. (elf32_arm_write_section): Add Cortex-A8 erratum workaround support. * bfd-in.h (bfd_elf32_arm_set_cortex_a8_fix): New. (bfd_elf32_arm_set_target_relocs): Add argument for controlling Cortex-A8 erratum workaround. * bfd-in2.h: Regenerate. ld/testsuite/ * ld-arm/cortex-a8-arm-target.s: New. * ld-arm/cortex-a8-thumb-target.s: New. * ld-arm/cortex-a8-fix-b-rel.s: New. * ld-arm/cortex-a8-fix-b-rel-arm.d: New. * ld-arm/cortex-a8-fix-b-rel-thumb.d: New. * ld-arm/cortex-a8-fix-b.s: New. * ld-arm/cortex-a8-fix-b.d: New. * ld-arm/cortex-a8-fix-bl-rel.s: New. * ld-arm/cortex-a8-fix-bl-rel-arm.d: New. * ld-arm/cortex-a8-fix-bl-rel-thumb.d: New. * ld-arm/cortex-a8-fix-bl.s: New. * ld-arm/cortex-a8-fix-bl.d: New. * ld-arm/cortex-a8-fix-bcc-rel.s: New. * ld-arm/cortex-a8-fix-bcc-rel-thumb.d: New. * ld-arm/cortex-a8-fix-bcc.s: New. * ld-arm/cortex-a8-fix-bcc.d: New. * ld-arm/cortex-a8-fix-blx-rel.s: New. * ld-arm/cortex-a8-fix-blx-rel-arm.d: New. * ld-arm/cortex-a8-fix-blx-rel-thumb.d: New. * ld-arm/cortex-a8-fix-blx.s: New. * ld-arm/cortex-a8-fix-blx.d: New. * ld-arm/arm-elf.exp: Add new tests. --- bfd/ChangeLog | 35 + bfd/bfd-in.h | 5 +- bfd/bfd-in2.h | 5 +- bfd/elf32-arm.c | 1037 +++++++++++++++-- ld/ChangeLog | 12 + ld/emultempl/armelf.em | 19 +- ld/ld.texinfo | 7 + ld/testsuite/ChangeLog | 25 + ld/testsuite/ld-arm/arm-elf.exp | 44 + ld/testsuite/ld-arm/cortex-a8-arm-target.s | 9 + ld/testsuite/ld-arm/cortex-a8-fix-b-rel-arm.d | 83 ++ .../ld-arm/cortex-a8-fix-b-rel-thumb.d | 80 ++ ld/testsuite/ld-arm/cortex-a8-fix-b-rel.s | 41 + ld/testsuite/ld-arm/cortex-a8-fix-b.d | 75 ++ ld/testsuite/ld-arm/cortex-a8-fix-b.s | 39 + .../ld-arm/cortex-a8-fix-bcc-rel-thumb.d | 82 ++ ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel.s | 38 + ld/testsuite/ld-arm/cortex-a8-fix-bcc.d | 77 ++ ld/testsuite/ld-arm/cortex-a8-fix-bcc.s | 39 + .../ld-arm/cortex-a8-fix-bl-rel-arm.d | 79 ++ .../ld-arm/cortex-a8-fix-bl-rel-thumb.d | 80 ++ ld/testsuite/ld-arm/cortex-a8-fix-bl-rel.s | 40 + ld/testsuite/ld-arm/cortex-a8-fix-bl.d | 75 ++ ld/testsuite/ld-arm/cortex-a8-fix-bl.s | 39 + .../ld-arm/cortex-a8-fix-blx-rel-arm.d | 79 ++ .../ld-arm/cortex-a8-fix-blx-rel-thumb.d | 80 ++ ld/testsuite/ld-arm/cortex-a8-fix-blx-rel.s | 38 + ld/testsuite/ld-arm/cortex-a8-fix-blx.d | 79 ++ ld/testsuite/ld-arm/cortex-a8-fix-blx.s | 44 + ld/testsuite/ld-arm/cortex-a8-thumb-target.s | 10 + 30 files changed, 2271 insertions(+), 124 deletions(-) create mode 100644 ld/testsuite/ld-arm/cortex-a8-arm-target.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-b-rel-arm.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-b-rel-thumb.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-b-rel.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-b.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-b.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel-thumb.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bcc.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bcc.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-arm.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-thumb.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bl-rel.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bl.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-bl.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-arm.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-thumb.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-blx-rel.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-blx.d create mode 100644 ld/testsuite/ld-arm/cortex-a8-fix-blx.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-thumb-target.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1e2f99c67b..6e5652f22b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,38 @@ +2009-05-22 Julian Brown + + * elf32-arm.c (THUMB16_BCOND_INSN, THUMB32_INSN, THUMB32_B_INSN): New + macros. + (elf32_arm_stub_a8_veneer_b_cond, elf32_arm_stub_a8_veneer_b) + (elf32_arm_stub_a8_veneer_blx): New stub sequences. + (elf32_arm_stub_type): Add arm_stub_a8_veneer_b_cond, + arm_stub_a8_veneer_b and arm_stub_a8_veneer_blx. + (elf32_arm_stub_hash_entry): Add target_addend, orig_insn fields. + (a8_erratum_fix, a8_erratum_reloc): New structs. + (elf32_arm_link_hash_table): Add a8_erratum_fixes, + num_a8_erratum_fixes, fix_cortex_a8 fields. + (elf32_arm_link_hash_table_create): Zero fix_cortex_a8. + (elf32_arm_add_stub): Split into two parts, creating... + (elf32_arm_create_or_find_stub_sec): New function. + (elf32_arm_final_link_relocate): Add forward declaration. + (arm_build_one_stub): Add support for THUMB32_TYPE, Thumb-2 + relocations, multiple relocations per stub. + (find_stub_size_and_template): New (using parts of arm_size_one_stub). + (arm_size_one_stub): Use find_stub_size_and_template. + (a8_reloc_compare): New. + (find_thumb_glue): Add forward declaration. + (cortex_a8_erratum_scan): New. + (elf32_arm_size_stubs): Add Cortex-A8 erratum workaround support. + (bfd_elf32_arm_set_cortex_a8_fix): New. + (bfd_elf32_arm_set_target_relocs): Add fix_cortex_a8 argument. + (arm_map_one_stub): Add THUMB32_TYPE support. + (a8_branch_to_stub_data): New. + (make_branch_to_a8_stub): New. + (elf32_arm_write_section): Add Cortex-A8 erratum workaround support. + * bfd-in.h (bfd_elf32_arm_set_cortex_a8_fix): New. + (bfd_elf32_arm_set_target_relocs): Add argument for controlling + Cortex-A8 erratum workaround. + * bfd-in2.h: Regenerate. + 2009-05-22 Alan Modra * Makefile.am: Run "make dep-am". diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 34bd50e86a..9bd4e38b27 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -825,6 +825,9 @@ extern void bfd_elf32_arm_init_maps extern void bfd_elf32_arm_set_vfp11_fix (bfd *, struct bfd_link_info *); +extern void bfd_elf32_arm_set_cortex_a8_fix + (bfd *, struct bfd_link_info *); + extern bfd_boolean bfd_elf32_arm_vfp11_erratum_scan (bfd *, struct bfd_link_info *); @@ -860,7 +863,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); 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 9f0ff37e29..15135bdc01 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -832,6 +832,9 @@ extern void bfd_elf32_arm_init_maps extern void bfd_elf32_arm_set_vfp11_fix (bfd *, struct bfd_link_info *); +extern void bfd_elf32_arm_set_cortex_a8_fix + (bfd *, struct bfd_link_info *); + extern bfd_boolean bfd_elf32_arm_vfp11_erratum_scan (bfd *, struct bfd_link_info *); @@ -867,7 +870,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); 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 7c82966722..2a2d4611ab 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2026,11 +2026,15 @@ enum stub_insn_type DATA_TYPE }; -#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)} +#define THUMB16_INSN(X) {(X), THUMB16_TYPE, R_ARM_NONE, 0} +/* A bit of a hack. A Thumb conditional branch, in which the proper condition + 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_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)} +#define DATA_WORD(X,Y,Z) {(X), DATA_TYPE, (Y), (Z)} typedef struct { @@ -2164,6 +2168,39 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] = DATA_WORD(0, R_ARM_REL32, 0), /* dcd R_ARM_REL32(X) */ }; +/* Cortex-A8 erratum-workaround stubs. */ + +/* Stub used for conditional branches (which may be beyond +/-1MB away, so we + can't use a conditional branch to reach this stub). */ + +static const insn_sequence elf32_arm_stub_a8_veneer_b_cond[] = + { + THUMB16_BCOND_INSN(0xd001), /* b.n true. */ + THUMB32_B_INSN(0xf000b800, -4), /* b.w insn_after_original_branch. */ + THUMB32_B_INSN(0xf000b800, -4) /* true: b.w original_branch_dest. */ + }; + +/* Stub used for b.w and bl.w instructions. */ + +static const insn_sequence elf32_arm_stub_a8_veneer_b[] = + { + THUMB32_B_INSN(0xf000b800, -4) /* b.w original_branch_dest. */ + }; + +static const insn_sequence elf32_arm_stub_a8_veneer_bl[] = + { + THUMB32_B_INSN(0xf000b800, -4) /* b.w original_branch_dest. */ + }; + +/* Stub used for Thumb-2 blx.w instructions. We modified the original blx.w + instruction (which switches to ARM mode) to point to this stub. Jump to the + real destination using an ARM-mode branch. */ + +static const insn_sequence elf32_arm_stub_a8_veneer_blx[] = + { + ARM_REL_INSN(0xea000000, -8) /* b original_branch_dest. */ + }; + /* Section name for stubs is the associated section name plus this string. */ #define STUB_SUFFIX ".stub" @@ -2181,7 +2218,11 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] = DEF_STUB(long_branch_v4t_thumb_thumb_pic) \ DEF_STUB(long_branch_v4t_arm_thumb_pic) \ DEF_STUB(long_branch_v4t_thumb_arm_pic) \ - DEF_STUB(long_branch_thumb_only_pic) + DEF_STUB(long_branch_thumb_only_pic) \ + DEF_STUB(a8_veneer_b_cond) \ + DEF_STUB(a8_veneer_b) \ + DEF_STUB(a8_veneer_bl) \ + DEF_STUB(a8_veneer_blx) #define DEF_STUB(x) arm_stub_##x, enum elf32_arm_stub_type { @@ -2218,6 +2259,13 @@ struct elf32_arm_stub_hash_entry bfd_vma target_value; asection *target_section; + /* Offset to apply to relocation referencing target_value. */ + bfd_vma target_addend; + + /* The instruction which caused this stub to be generated (only valid for + Cortex-A8 erratum workaround stubs at present). */ + unsigned long orig_insn; + /* The stub type. */ enum elf32_arm_stub_type stub_type; /* Its encoding size in bytes. */ @@ -2337,6 +2385,34 @@ _arm_elf_section_data; #define elf32_arm_section_data(sec) \ ((_arm_elf_section_data *) elf_section_data (sec)) +/* A fix which might be required for Cortex-A8 Thumb-2 branch/TLB erratum. + These fixes are subject to a relaxation procedure (in elf32_arm_size_stubs), + so may be created multiple times: we use an array of these entries whilst + relaxing which we can refresh easily, then create stubs for each potentially + erratum-triggering instruction once we've settled on a solution. */ + +struct a8_erratum_fix { + bfd *input_bfd; + asection *section; + bfd_vma offset; + bfd_vma addend; + unsigned long orig_insn; + char *stub_name; + enum elf32_arm_stub_type stub_type; +}; + +/* A table of relocs applied to branches which might trigger Cortex-A8 + erratum. */ + +struct a8_erratum_reloc { + bfd_vma from; + bfd_vma destination; + unsigned int r_type; + unsigned char st_type; + const char *sym_name; + bfd_boolean non_a8_stub; +}; + /* The size of the thread control block. */ #define TCB_SIZE 8 @@ -2468,6 +2544,12 @@ struct elf32_arm_link_hash_table veneers. */ bfd_size_type vfp11_erratum_glue_size; + /* A table of fix locations for Cortex-A8 Thumb-2 branch/TLB erratum. This + holds Cortex-A8 erratum fix locations between elf32_arm_size_stubs() and + elf32_arm_write_section(). */ + struct a8_erratum_fix *a8_erratum_fixes; + unsigned int num_a8_erratum_fixes; + /* An arbitrary input BFD chosen to hold the glue sections. */ bfd * bfd_of_glue_owner; @@ -2486,6 +2568,9 @@ struct elf32_arm_link_hash_table 2 = Generate v4 interworing stubs. */ int fix_v4bx; + /* Whether we should fix the Cortex-A8 Thumb-2 branch/TLB erratum. */ + int fix_cortex_a8; + /* Nonzero if the ARM/Thumb BLX instructions are available for use. */ int use_blx; @@ -2825,6 +2910,7 @@ elf32_arm_link_hash_table_create (bfd *abfd) ret->vfp11_fix = BFD_ARM_VFP11_FIX_NONE; ret->vfp11_erratum_glue_size = 0; ret->num_vfp11_fixes = 0; + ret->fix_cortex_a8 = 0; ret->bfd_of_glue_owner = NULL; ret->byteswap_code = 0; ret->target1_is_rel = 0; @@ -3214,17 +3300,16 @@ elf32_arm_get_stub_entry (const asection *input_section, return stub_entry; } -/* Add a new stub entry to the stub hash. Not all fields of the new - stub entry are initialised. */ +/* Find or create a stub section. Returns a pointer to the stub section, and + the section to which the stub section will be attached (in *LINK_SEC_P). + LINK_SEC_P may be NULL. */ -static struct elf32_arm_stub_hash_entry * -elf32_arm_add_stub (const char *stub_name, - asection *section, - struct elf32_arm_link_hash_table *htab) +static asection * +elf32_arm_create_or_find_stub_sec (asection **link_sec_p, asection *section, + struct elf32_arm_link_hash_table *htab) { asection *link_sec; asection *stub_sec; - struct elf32_arm_stub_hash_entry *stub_entry; link_sec = htab->stub_group[section->id].link_sec; stub_sec = htab->stub_group[section->id].stub_sec; @@ -3252,6 +3337,28 @@ elf32_arm_add_stub (const char *stub_name, } htab->stub_group[section->id].stub_sec = stub_sec; } + + if (link_sec_p) + *link_sec_p = link_sec; + + return stub_sec; +} + +/* Add a new stub entry to the stub hash. Not all fields of the new + stub entry are initialised. */ + +static struct elf32_arm_stub_hash_entry * +elf32_arm_add_stub (const char *stub_name, + asection *section, + struct elf32_arm_link_hash_table *htab) +{ + asection *link_sec; + asection *stub_sec; + struct elf32_arm_stub_hash_entry *stub_entry; + + stub_sec = elf32_arm_create_or_find_stub_sec (&link_sec, section, htab); + if (stub_sec == NULL) + return NULL; /* Enter this entry into the linker stub hash table. */ stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, @@ -3297,10 +3404,16 @@ put_thumb_insn (struct elf32_arm_link_hash_table * htab, bfd_putb16 (val, ptr); } +static bfd_reloc_status_type elf32_arm_final_link_relocate + (reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, + Elf_Internal_Rela *, bfd_vma, struct bfd_link_info *, asection *, + const char *, int, struct elf_link_hash_entry *, bfd_boolean *, char **); + static bfd_boolean arm_build_one_stub (struct bfd_hash_entry *gen_entry, void * in_arg) { +#define MAXRELOCS 2 struct elf32_arm_stub_hash_entry *stub_entry; struct bfd_link_info *info; struct elf32_arm_link_hash_table *htab; @@ -3314,8 +3427,9 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, const insn_sequence *template; int i; struct elf32_arm_link_hash_table * globals; - int stub_reloc_idx = -1; - int stub_reloc_offset = 0; + int stub_reloc_idx[MAXRELOCS] = {-1, -1}; + int stub_reloc_offset[MAXRELOCS] = {0, 0}; + int nrelocs = 0; /* Massage our args to the form they really have. */ stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry; @@ -3350,26 +3464,50 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, switch (template[i].type) { case THUMB16_TYPE: - put_thumb_insn (globals, stub_bfd, template[i].data, loc + size); - size += 2; + { + bfd_vma data = template[i].data; + if (template[i].reloc_addend != 0) + { + /* We've borrowed the reloc_addend field to mean we should + insert a condition code into this (Thumb-1 branch) + instruction. See THUMB16_BCOND_INSN. */ + BFD_ASSERT ((data & 0xff00) == 0xd000); + data |= ((stub_entry->orig_insn >> 22) & 0xf) << 8; + } + put_thumb_insn (globals, stub_bfd, data, loc + size); + size += 2; + } break; + case THUMB32_TYPE: + put_thumb_insn (globals, stub_bfd, (template[i].data >> 16) & 0xffff, + loc + size); + put_thumb_insn (globals, stub_bfd, template[i].data & 0xffff, + loc + size + 2); + if (template[i].r_type != R_ARM_NONE) + { + stub_reloc_idx[nrelocs] = i; + stub_reloc_offset[nrelocs++] = size; + } + size += 4; + break; + 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].r_type == R_ARM_JUMP24) { - stub_reloc_idx = i; - stub_reloc_offset = size; + stub_reloc_idx[nrelocs] = i; + stub_reloc_offset[nrelocs++] = 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; + stub_reloc_idx[nrelocs] = i; + stub_reloc_offset[nrelocs++] = size; size += 4; break; @@ -3389,40 +3527,72 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, if (stub_entry->st_type == STT_ARM_TFUNC) sym_value |= 1; - /* Assume there is one and only one entry to relocate in each stub. */ - BFD_ASSERT (stub_reloc_idx != -1); + /* Assume there is at least one and at most MAXRELOCS entries to relocate + in each stub. */ + BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS); - _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].r_type), - stub_bfd, stub_sec, stub_sec->contents, - stub_entry->stub_offset + stub_reloc_offset, - sym_value, template[stub_reloc_idx].reloc_addend); + for (i = 0; i < nrelocs; i++) + if (template[stub_reloc_idx[i]].r_type == R_ARM_THM_JUMP24 + || template[stub_reloc_idx[i]].r_type == R_ARM_THM_JUMP19 + || template[stub_reloc_idx[i]].r_type == R_ARM_THM_CALL + || template[stub_reloc_idx[i]].r_type == R_ARM_THM_XPC22) + { + Elf_Internal_Rela rel; + bfd_boolean unresolved_reloc; + char *error_message; + int sym_flags + = (template[stub_reloc_idx[i]].r_type != R_ARM_THM_XPC22) + ? STT_ARM_TFUNC : 0; + bfd_vma points_to = sym_value + stub_entry->target_addend; + + rel.r_offset = stub_entry->stub_offset + stub_reloc_offset[i]; + rel.r_info = ELF32_R_INFO (0, template[stub_reloc_idx[i]].r_type); + rel.r_addend = template[stub_reloc_idx[i]].reloc_addend; + + if (stub_entry->stub_type == arm_stub_a8_veneer_b_cond && i == 0) + /* The first relocation in the elf32_arm_stub_a8_veneer_b_cond[] + template should refer back to the instruction after the original + branch. */ + points_to = sym_value; + + /* Note: _bfd_final_link_relocate doesn't handle these relocations + properly. We should probably use this function unconditionally, + rather than only for certain relocations listed in the enclosing + conditional, for the sake of consistency. */ + elf32_arm_final_link_relocate (elf32_arm_howto_from_type + (template[stub_reloc_idx[i]].r_type), + stub_bfd, info->output_bfd, stub_sec, stub_sec->contents, &rel, + points_to, info, stub_entry->target_section, "", sym_flags, + (struct elf_link_hash_entry *) stub_entry, &unresolved_reloc, + &error_message); + } + else + { + _bfd_final_link_relocate (elf32_arm_howto_from_type + (template[stub_reloc_idx[i]].r_type), stub_bfd, stub_sec, + stub_sec->contents, stub_entry->stub_offset + stub_reloc_offset[i], + sym_value + stub_entry->target_addend, + template[stub_reloc_idx[i]].reloc_addend); + } return TRUE; +#undef MAXRELOCS } -/* As above, but don't actually build the stub. Just bump offset so - we know stub section sizes. */ +/* Calculate the template, template size and instruction size for a stub. + Return value is the instruction size. */ -static bfd_boolean -arm_size_one_stub (struct bfd_hash_entry *gen_entry, - void * in_arg) +static unsigned int +find_stub_size_and_template (enum elf32_arm_stub_type stub_type, + const insn_sequence **stub_template, + int *stub_template_size) { - struct elf32_arm_stub_hash_entry *stub_entry; - struct elf32_arm_link_hash_table *htab; - const insn_sequence *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; + const insn_sequence *template = NULL; + int template_size = 0, i; + unsigned int size; - BFD_ASSERT((stub_entry->stub_type > arm_stub_none) - && stub_entry->stub_type < ARRAY_SIZE(stub_definitions)); - - template = stub_definitions[stub_entry->stub_type].template; - template_size = stub_definitions[stub_entry->stub_type].template_size; + template = stub_definitions[stub_type].template; + template_size = stub_definitions[stub_type].template_size; size = 0; for (i = 0; i < template_size; i++) @@ -3434,9 +3604,7 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry, break; case ARM_TYPE: - size += 4; - break; - + case THUMB32_TYPE: case DATA_TYPE: size += 4; break; @@ -3447,6 +3615,37 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry, } } + if (stub_template) + *stub_template = template; + + if (stub_template_size) + *stub_template_size = template_size; + + return size; +} + +/* As above, but don't actually build the stub. Just bump offset so + we know stub section sizes. */ + +static bfd_boolean +arm_size_one_stub (struct bfd_hash_entry *gen_entry, + void * in_arg) +{ + struct elf32_arm_stub_hash_entry *stub_entry; + struct elf32_arm_link_hash_table *htab; + const insn_sequence *template; + int template_size, size; + + /* 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; + + BFD_ASSERT((stub_entry->stub_type > arm_stub_none) + && stub_entry->stub_type < ARRAY_SIZE(stub_definitions)); + + size = find_stub_size_and_template (stub_entry->stub_type, &template, + &template_size); + stub_entry->stub_size = size; stub_entry->stub_template = template; stub_entry->stub_template_size = template_size; @@ -3663,6 +3862,290 @@ group_sections (struct elf32_arm_link_hash_table *htab, #undef NEXT_SEC } +/* Comparison function for sorting/searching relocations relating to Cortex-A8 + erratum fix. */ + +static int +a8_reloc_compare (const void *a, const void *b) +{ + const struct a8_erratum_reloc *ra = a, *rb = b; + + if (ra->from < rb->from) + return -1; + else if (ra->from > rb->from) + return 1; + else + return 0; +} + +static struct elf_link_hash_entry *find_thumb_glue (struct bfd_link_info *, + const char *, char **); + +/* Helper function to scan code for sequences which might trigger the Cortex-A8 + branch/TLB erratum. Fill in the table described by A8_FIXES_P, + NUM_A8_FIXES_P, A8_FIX_TABLE_SIZE_P. Return 1 if an error occurs, 0 + otherwise. */ + +static int +cortex_a8_erratum_scan (bfd *input_bfd, struct bfd_link_info *info, + struct a8_erratum_fix **a8_fixes_p, + unsigned int *num_a8_fixes_p, + unsigned int *a8_fix_table_size_p, + struct a8_erratum_reloc *a8_relocs, + unsigned int num_a8_relocs) +{ + asection *section; + struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info); + struct a8_erratum_fix *a8_fixes = *a8_fixes_p; + unsigned int num_a8_fixes = *num_a8_fixes_p; + unsigned int a8_fix_table_size = *a8_fix_table_size_p; + + for (section = input_bfd->sections; + section != NULL; + section = section->next) + { + bfd_byte *contents = NULL; + struct _arm_elf_section_data *sec_data; + unsigned int span; + bfd_vma base_vma; + + if (elf_section_type (section) != SHT_PROGBITS + || (elf_section_flags (section) & SHF_EXECINSTR) == 0 + || (section->flags & SEC_EXCLUDE) != 0 + || (section->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) + || (section->output_section == bfd_abs_section_ptr)) + continue; + + base_vma = section->output_section->vma + section->output_offset; + + if (elf_section_data (section)->this_hdr.contents != NULL) + contents = elf_section_data (section)->this_hdr.contents; + else if (! bfd_malloc_and_get_section (input_bfd, section, &contents)) + return 1; + + sec_data = elf32_arm_section_data (section); + + for (span = 0; span < sec_data->mapcount; span++) + { + unsigned int span_start = sec_data->map[span].vma; + unsigned int span_end = (span == sec_data->mapcount - 1) + ? section->size : sec_data->map[span + 1].vma; + unsigned int i; + char span_type = sec_data->map[span].type; + bfd_boolean last_was_32bit = FALSE, last_was_branch = FALSE; + + if (span_type != 't') + continue; + + /* Span is entirely within a single 4KB region: skip scanning. */ + if (((base_vma + span_start) & ~0xfff) + == ((base_vma + span_end) & ~0xfff)) + continue; + + /* Scan for 32-bit Thumb-2 branches which span two 4K regions, where: + + * The opcode is BLX.W, BL.W, B.W, Bcc.W + * The branch target is in the same 4KB region as the + first half of the branch. + * The instruction before the branch is a 32-bit + length non-branch instruction. + */ + + for (i = span_start; i < span_end;) + { + unsigned int insn = bfd_getl16 (&contents[i]); + bfd_boolean insn_32bit = FALSE, is_blx = FALSE, is_b = FALSE; + bfd_boolean is_bl = FALSE, is_bcc = FALSE, is_32bit_branch; + + if ((insn & 0xe000) == 0xe000 && (insn & 0x1800) != 0x0000) + insn_32bit = TRUE; + + if (insn_32bit) + { + /* Load the rest of the insn (in manual-friendly order). */ + insn = (insn << 16) | bfd_getl16 (&contents[i + 2]); + + /* Encoding T4: B.W. */ + is_b = (insn & 0xf800d000) == 0xf0009000; + /* Encoding T1: BL.W. */ + is_bl = (insn & 0xf800d000) == 0xf000d000; + /* Encoding T2: BLX.W. */ + is_blx = (insn & 0xf800d000) == 0xf000c000; + /* Encoding T3: B.W (not permitted in IT block). */ + is_bcc = (insn & 0xf800d000) == 0xf0008000 + && (insn & 0x07f00000) != 0x03800000; + } + + is_32bit_branch = is_b || is_bl || is_blx || is_bcc; + + if (((base_vma + i) & 0xfff) == 0xffe && insn_32bit + && is_32bit_branch && last_was_32bit && !last_was_branch) + { + bfd_vma offset; + bfd_boolean force_target_arm = FALSE; + bfd_boolean force_target_thumb = FALSE; + bfd_vma target; + enum elf32_arm_stub_type stub_type = arm_stub_none; + struct a8_erratum_reloc key, *found; + + key.from = base_vma + i; + found = bsearch (&key, a8_relocs, num_a8_relocs, + sizeof (struct a8_erratum_reloc), + &a8_reloc_compare); + + if (found) + { + char *error_message = NULL; + struct elf_link_hash_entry *entry; + + /* We don't care about the error returned from this + function, only if there is glue or not. */ + entry = find_thumb_glue (info, found->sym_name, + &error_message); + + if (entry) + found->non_a8_stub = TRUE; + + if (found->r_type == R_ARM_THM_CALL + && found->st_type != STT_ARM_TFUNC) + force_target_arm = TRUE; + else if (found->r_type == R_ARM_THM_CALL + && found->st_type == STT_ARM_TFUNC) + force_target_thumb = TRUE; + } + + /* Check if we have an offending branch instruction. */ + + if (found && found->non_a8_stub) + /* We've already made a stub for this instruction, e.g. + it's a long branch or a Thumb->ARM stub. Assume that + stub will suffice to work around the A8 erratum (see + setting of always_after_branch above). */ + ; + else if (is_bcc) + { + offset = (insn & 0x7ff) << 1; + offset |= (insn & 0x3f0000) >> 4; + offset |= (insn & 0x2000) ? 0x40000 : 0; + offset |= (insn & 0x800) ? 0x80000 : 0; + offset |= (insn & 0x4000000) ? 0x100000 : 0; + if (offset & 0x100000) + offset |= ~0xfffff; + stub_type = arm_stub_a8_veneer_b_cond; + } + else if (is_b || is_bl || is_blx) + { + int s = (insn & 0x4000000) != 0; + int j1 = (insn & 0x2000) != 0; + int j2 = (insn & 0x800) != 0; + int i1 = !(j1 ^ s); + int i2 = !(j2 ^ s); + + offset = (insn & 0x7ff) << 1; + offset |= (insn & 0x3ff0000) >> 4; + offset |= i2 << 22; + offset |= i1 << 23; + offset |= s << 24; + if (offset & 0x1000000) + offset |= ~0xffffff; + + if (is_blx) + offset &= ~3u; + + stub_type = is_blx ? arm_stub_a8_veneer_blx : + is_bl ? arm_stub_a8_veneer_bl : arm_stub_a8_veneer_b; + } + + if (stub_type != arm_stub_none) + { + bfd_vma pc_for_insn = base_vma + i + 4; + + /* The original instruction is a BL, but the target is + an ARM instruction. If we were not making a stub, + the BL would have been converted to a BLX. Use the + BLX stub instead in that case. */ + if (htab->use_blx && force_target_arm + && stub_type == arm_stub_a8_veneer_bl) + { + stub_type = arm_stub_a8_veneer_blx; + is_blx = TRUE; + is_bl = FALSE; + } + /* Conversely, if the original instruction was + BLX but the target is Thumb mode, use the BL + stub. */ + else if (force_target_thumb + && stub_type == arm_stub_a8_veneer_blx) + { + stub_type = arm_stub_a8_veneer_bl; + is_blx = FALSE; + is_bl = TRUE; + } + + if (is_blx) + pc_for_insn &= ~3u; + + /* If we found a relocation, use the proper destination, + not the offset in the (unrelocated) instruction. + Note this is always done if we switched the stub type + above. */ + if (found) + offset = found->destination - pc_for_insn; + + target = pc_for_insn + offset; + + /* The BLX stub is ARM-mode code. Adjust the offset to + take the different PC value (+8 instead of +4) into + account. */ + if (stub_type == arm_stub_a8_veneer_blx) + offset += 4; + + if (((base_vma + i) & ~0xfff) == (target & ~0xfff)) + { + char *stub_name; + + if (num_a8_fixes == a8_fix_table_size) + { + a8_fix_table_size *= 2; + a8_fixes = bfd_realloc (a8_fixes, + sizeof (struct a8_erratum_fix) + * a8_fix_table_size); + } + + stub_name = bfd_malloc (8 + 1 + 8 + 1); + if (stub_name != NULL) + sprintf (stub_name, "%x:%x", section->id, i); + + a8_fixes[num_a8_fixes].input_bfd = input_bfd; + a8_fixes[num_a8_fixes].section = section; + a8_fixes[num_a8_fixes].offset = i; + a8_fixes[num_a8_fixes].addend = offset; + a8_fixes[num_a8_fixes].orig_insn = insn; + a8_fixes[num_a8_fixes].stub_name = stub_name; + a8_fixes[num_a8_fixes].stub_type = stub_type; + + num_a8_fixes++; + } + } + } + + i += insn_32bit ? 4 : 2; + last_was_32bit = insn_32bit; + last_was_branch = is_32bit_branch; + } + } + + if (elf_section_data (section)->this_hdr.contents == NULL) + free (contents); + } + + *a8_fixes_p = a8_fixes; + *num_a8_fixes_p = num_a8_fixes; + *a8_fix_table_size_p = a8_fix_table_size; + + return 0; +} + /* Determine and set the size of the stub section for a final link. The basic idea here is to examine all the relocations looking for @@ -3681,6 +4164,18 @@ elf32_arm_size_stubs (bfd *output_bfd, bfd_boolean stubs_always_after_branch; bfd_boolean stub_changed = 0; struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info); + struct a8_erratum_fix *a8_fixes = NULL; + unsigned int num_a8_fixes = 0, prev_num_a8_fixes = 0, a8_fix_table_size = 10; + struct a8_erratum_reloc *a8_relocs = NULL; + unsigned int num_a8_relocs = 0, a8_reloc_table_size = 10, i; + + if (htab->fix_cortex_a8) + { + a8_fixes = bfd_zmalloc (sizeof (struct a8_erratum_fix) + * a8_fix_table_size); + a8_relocs = bfd_zmalloc (sizeof (struct a8_erratum_reloc) + * a8_reloc_table_size); + } /* Propagate mach to stub bfd, because it may not have been finalized when we created stub_bfd. */ @@ -3692,6 +4187,13 @@ elf32_arm_size_stubs (bfd *output_bfd, htab->add_stub_section = add_stub_section; htab->layout_sections_again = layout_sections_again; stubs_always_after_branch = group_size < 0; + + /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page + as the first half of a 32-bit branch straddling two 4K pages. This is a + crude way of enforcing that. */ + if (htab->fix_cortex_a8) + stubs_always_after_branch = 1; + if (group_size < 0) stub_group_size = -group_size; else @@ -3719,6 +4221,8 @@ elf32_arm_size_stubs (bfd *output_bfd, unsigned int bfd_indx; asection *stub_sec; + num_a8_fixes = 0; + for (input_bfd = info->input_bfds, bfd_indx = 0; input_bfd != NULL; input_bfd = input_bfd->link_next, bfd_indx++) @@ -3727,6 +4231,8 @@ elf32_arm_size_stubs (bfd *output_bfd, asection *section; Elf_Internal_Sym *local_syms = NULL; + num_a8_relocs = 0; + /* We'll need the symbol table in a second. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; if (symtab_hdr->sh_info == 0) @@ -3775,6 +4281,7 @@ elf32_arm_size_stubs (bfd *output_bfd, char *stub_name; const asection *id_sec; unsigned char st_type; + bfd_boolean created_stub = FALSE; r_type = ELF32_R_TYPE (irela->r_info); r_indx = ELF32_R_SYM (irela->r_info); @@ -3792,6 +4299,8 @@ elf32_arm_size_stubs (bfd *output_bfd, if ((r_type != (unsigned int) R_ARM_CALL) && (r_type != (unsigned int) R_ARM_THM_CALL) && (r_type != (unsigned int) R_ARM_JUMP24) + && (r_type != (unsigned int) R_ARM_THM_JUMP19) + && (r_type != (unsigned int) R_ARM_THM_XPC22) && (r_type != (unsigned int) R_ARM_THM_JUMP24) && (r_type != (unsigned int) R_ARM_PLT32)) continue; @@ -3892,81 +4401,146 @@ elf32_arm_size_stubs (bfd *output_bfd, sym_name = hash->root.root.root.string; } - /* Determine what (if any) linker stub is needed. */ - stub_type = arm_type_of_stub (info, section, irela, st_type, - hash, destination, sym_sec, - input_bfd, sym_name); - if (stub_type == arm_stub_none) - continue; - - /* Support for grouping stub sections. */ - id_sec = htab->stub_group[section->id].link_sec; - - /* Get the name of this stub. */ - stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela); - if (!stub_name) - goto error_ret_free_internal; - - stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, - stub_name, - FALSE, FALSE); - if (stub_entry != NULL) - { - /* The proper stub has already been created. */ - free (stub_name); - continue; - } - - stub_entry = elf32_arm_add_stub (stub_name, section, htab); - if (stub_entry == NULL) - { - free (stub_name); - goto error_ret_free_internal; - } - - stub_entry->target_value = sym_value; - stub_entry->target_section = sym_sec; - stub_entry->stub_type = stub_type; - stub_entry->h = hash; - stub_entry->st_type = st_type; - - if (sym_name == NULL) - sym_name = "unnamed"; - stub_entry->output_name - = bfd_alloc (htab->stub_bfd, - sizeof (THUMB2ARM_GLUE_ENTRY_NAME) - + strlen (sym_name)); - if (stub_entry->output_name == NULL) + do { - free (stub_name); - goto error_ret_free_internal; - } + /* Determine what (if any) linker stub is needed. */ + stub_type = arm_type_of_stub (info, section, irela, + st_type, hash, + destination, sym_sec, + input_bfd, sym_name); + if (stub_type == arm_stub_none) + break; + + /* Support for grouping stub sections. */ + id_sec = htab->stub_group[section->id].link_sec; + + /* Get the name of this stub. */ + stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, + irela); + if (!stub_name) + goto error_ret_free_internal; + + /* We've either created a stub for this reloc already, + or we are about to. */ + created_stub = TRUE; + + stub_entry = arm_stub_hash_lookup + (&htab->stub_hash_table, stub_name, + FALSE, FALSE); + if (stub_entry != NULL) + { + /* The proper stub has already been created. */ + free (stub_name); + break; + } - /* For historical reasons, use the existing names for - ARM-to-Thumb and Thumb-to-ARM stubs. */ - if ( ((r_type == (unsigned int) R_ARM_THM_CALL) - || (r_type == (unsigned int) R_ARM_THM_JUMP24)) - && st_type != STT_ARM_TFUNC) - sprintf (stub_entry->output_name, THUMB2ARM_GLUE_ENTRY_NAME, - sym_name); - else if ( ((r_type == (unsigned int) R_ARM_CALL) - || (r_type == (unsigned int) R_ARM_JUMP24)) - && st_type == STT_ARM_TFUNC) - sprintf (stub_entry->output_name, ARM2THUMB_GLUE_ENTRY_NAME, - sym_name); - else - sprintf (stub_entry->output_name, STUB_ENTRY_NAME, - sym_name); + stub_entry = elf32_arm_add_stub (stub_name, section, + htab); + if (stub_entry == NULL) + { + free (stub_name); + goto error_ret_free_internal; + } - stub_changed = TRUE; + stub_entry->target_value = sym_value; + stub_entry->target_section = sym_sec; + stub_entry->stub_type = stub_type; + stub_entry->h = hash; + stub_entry->st_type = st_type; + + if (sym_name == NULL) + sym_name = "unnamed"; + stub_entry->output_name + = bfd_alloc (htab->stub_bfd, + sizeof (THUMB2ARM_GLUE_ENTRY_NAME) + + strlen (sym_name)); + if (stub_entry->output_name == NULL) + { + free (stub_name); + goto error_ret_free_internal; + } + + /* For historical reasons, use the existing names for + ARM-to-Thumb and Thumb-to-ARM stubs. */ + if ( ((r_type == (unsigned int) R_ARM_THM_CALL) + || (r_type == (unsigned int) R_ARM_THM_JUMP24)) + && st_type != STT_ARM_TFUNC) + sprintf (stub_entry->output_name, + THUMB2ARM_GLUE_ENTRY_NAME, sym_name); + else if ( ((r_type == (unsigned int) R_ARM_CALL) + || (r_type == (unsigned int) R_ARM_JUMP24)) + && st_type == STT_ARM_TFUNC) + sprintf (stub_entry->output_name, + ARM2THUMB_GLUE_ENTRY_NAME, sym_name); + else + sprintf (stub_entry->output_name, STUB_ENTRY_NAME, + sym_name); + + stub_changed = TRUE; + } + while (0); + + /* Look for relocations which might trigger Cortex-A8 + erratum. */ + if (htab->fix_cortex_a8 + && (r_type == (unsigned int) R_ARM_THM_JUMP24 + || r_type == (unsigned int) R_ARM_THM_JUMP19 + || r_type == (unsigned int) R_ARM_THM_CALL + || r_type == (unsigned int) R_ARM_THM_XPC22)) + { + bfd_vma from = section->output_section->vma + + section->output_offset + + irela->r_offset; + + if ((from & 0xfff) == 0xffe) + { + /* Found a candidate. Note we haven't checked the + destination is within 4K here: if we do so (and + don't create an entry in a8_relocs) we can't tell + that a branch should have been relocated when + scanning later. */ + if (num_a8_relocs == a8_reloc_table_size) + { + a8_reloc_table_size *= 2; + a8_relocs = bfd_realloc (a8_relocs, + sizeof (struct a8_erratum_reloc) + * a8_reloc_table_size); + } + + a8_relocs[num_a8_relocs].from = from; + a8_relocs[num_a8_relocs].destination = destination; + a8_relocs[num_a8_relocs].r_type = r_type; + a8_relocs[num_a8_relocs].st_type = st_type; + a8_relocs[num_a8_relocs].sym_name = sym_name; + a8_relocs[num_a8_relocs].non_a8_stub = created_stub; + + num_a8_relocs++; + } + } } - /* We're done with the internal relocs, free them. */ - if (elf_section_data (section)->relocs == NULL) - free (internal_relocs); + /* We're done with the internal relocs, free them. */ + if (elf_section_data (section)->relocs == NULL) + free (internal_relocs); + } + + if (htab->fix_cortex_a8) + { + /* Sort relocs which might apply to Cortex-A8 erratum. */ + qsort (a8_relocs, num_a8_relocs, sizeof (struct a8_erratum_reloc), + &a8_reloc_compare); + + /* Scan for branches which might trigger Cortex-A8 erratum. */ + if (cortex_a8_erratum_scan (input_bfd, info, &a8_fixes, + &num_a8_fixes, &a8_fix_table_size, + a8_relocs, num_a8_relocs) != 0) + goto error_ret_free_local; } } + if (htab->fix_cortex_a8 && num_a8_fixes != prev_num_a8_fixes) + stub_changed = TRUE; + if (!stub_changed) break; @@ -3985,11 +4559,80 @@ elf32_arm_size_stubs (bfd *output_bfd, bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab); + /* Add Cortex-A8 erratum veneers to stub section sizes too. */ + if (htab->fix_cortex_a8) + for (i = 0; i < num_a8_fixes; i++) + { + stub_sec = elf32_arm_create_or_find_stub_sec (NULL, + a8_fixes[i].section, htab); + + if (stub_sec == NULL) + goto error_ret_free_local; + + stub_sec->size + += find_stub_size_and_template (a8_fixes[i].stub_type, NULL, + NULL); + } + + /* Ask the linker to do its stuff. */ (*htab->layout_sections_again) (); stub_changed = FALSE; + prev_num_a8_fixes = num_a8_fixes; } + /* Add stubs for Cortex-A8 erratum fixes now. */ + if (htab->fix_cortex_a8) + { + for (i = 0; i < num_a8_fixes; i++) + { + struct elf32_arm_stub_hash_entry *stub_entry; + char *stub_name = a8_fixes[i].stub_name; + asection *section = a8_fixes[i].section; + unsigned int section_id = a8_fixes[i].section->id; + asection *link_sec = htab->stub_group[section_id].link_sec; + asection *stub_sec = htab->stub_group[section_id].stub_sec; + const insn_sequence *template; + int template_size, size = 0; + + stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, + TRUE, FALSE); + if (stub_entry == NULL) + { + (*_bfd_error_handler) (_("%s: cannot create stub entry %s"), + section->owner, + stub_name); + return FALSE; + } + + stub_entry->stub_sec = stub_sec; + stub_entry->stub_offset = 0; + stub_entry->id_sec = link_sec; + stub_entry->stub_type = a8_fixes[i].stub_type; + stub_entry->target_section = a8_fixes[i].section; + stub_entry->target_value = a8_fixes[i].offset; + stub_entry->target_addend = a8_fixes[i].addend; + stub_entry->orig_insn = a8_fixes[i].orig_insn; + stub_entry->st_type = STT_ARM_TFUNC; + + size = find_stub_size_and_template (a8_fixes[i].stub_type, &template, + &template_size); + + stub_entry->stub_size = size; + stub_entry->stub_template = template; + stub_entry->stub_template_size = template_size; + } + + /* Stash the Cortex-A8 erratum fix array for use later in + elf32_arm_write_section(). */ + htab->a8_erratum_fixes = a8_fixes; + htab->num_a8_erratum_fixes = num_a8_fixes; + } + else + { + htab->a8_erratum_fixes = NULL; + htab->num_a8_erratum_fixes = 0; + } return TRUE; error_ret_free_local: @@ -4807,6 +5450,28 @@ bfd_elf32_arm_init_maps (bfd *abfd) } +/* Auto-select enabling of Cortex-A8 erratum fix if the user didn't explicitly + say what they wanted. */ + +void +bfd_elf32_arm_set_cortex_a8_fix (bfd *obfd, struct bfd_link_info *link_info) +{ + struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info); + obj_attribute *out_attr = elf_known_obj_attributes_proc (obfd); + + if (globals->fix_cortex_a8 == -1) + { + /* Turn on Cortex-A8 erratum workaround for ARMv7-A. */ + if (out_attr[Tag_CPU_arch].i == TAG_CPU_ARCH_V7 + && (out_attr[Tag_CPU_arch_profile].i == 'A' + || out_attr[Tag_CPU_arch_profile].i == 0)) + globals->fix_cortex_a8 = 1; + else + globals->fix_cortex_a8 = 0; + } +} + + void bfd_elf32_arm_set_vfp11_fix (bfd *obfd, struct bfd_link_info *link_info) { @@ -5416,7 +6081,7 @@ 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 pic_veneer, int fix_cortex_a8) { struct elf32_arm_link_hash_table *globals; @@ -5438,6 +6103,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, globals->use_blx |= use_blx; globals->vfp11_fix = vfp11_fix; globals->pic_veneer = pic_veneer; + globals->fix_cortex_a8 = fix_cortex_a8; BFD_ASSERT (is_arm_elf (output_bfd)); elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn; @@ -12172,13 +12838,14 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry, return FALSE; break; case THUMB16_TYPE: + case THUMB32_TYPE: if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, stub_entry->stub_size)) return FALSE; break; default: BFD_FAIL (); - return FALSE; + return 0; } prev_type = DATA_TYPE; @@ -12192,6 +12859,7 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry, break; case THUMB16_TYPE: + case THUMB32_TYPE: sym_type = ARM_MAP_THUMB; break; @@ -12214,6 +12882,7 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry, switch (template[i].type) { case ARM_TYPE: + case THUMB32_TYPE: size += 4; break; @@ -12440,6 +13109,120 @@ copy_exidx_entry (bfd *output_bfd, bfd_byte *to, bfd_byte *from, bfd_vma offset) bfd_put_32 (output_bfd, second_word, to + 4); } +/* Data for make_branch_to_a8_stub(). */ + +struct a8_branch_to_stub_data { + asection *writing_section; + bfd_byte *contents; +}; + + +/* Helper to insert branches to Cortex-A8 erratum stubs in the right + places for a particular section. */ + +static bfd_boolean +make_branch_to_a8_stub (struct bfd_hash_entry *gen_entry, + void *in_arg) +{ + struct elf32_arm_stub_hash_entry *stub_entry; + struct a8_branch_to_stub_data *data; + bfd_byte *contents; + unsigned long branch_insn; + bfd_vma veneered_insn_loc, veneer_entry_loc; + bfd_signed_vma branch_offset; + bfd *abfd; + unsigned int index; + + stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry; + data = (struct a8_branch_to_stub_data *) in_arg; + + if (stub_entry->target_section != data->writing_section + || stub_entry->stub_type < arm_stub_a8_veneer_b_cond) + return TRUE; + + contents = data->contents; + + veneered_insn_loc = stub_entry->target_section->output_section->vma + + stub_entry->target_section->output_offset + + stub_entry->target_value; + + veneer_entry_loc = stub_entry->stub_sec->output_section->vma + + stub_entry->stub_sec->output_offset + + stub_entry->stub_offset; + + if (stub_entry->stub_type == arm_stub_a8_veneer_blx) + veneered_insn_loc &= ~3u; + + branch_offset = veneer_entry_loc - veneered_insn_loc - 4; + + abfd = stub_entry->target_section->owner; + index = stub_entry->target_value; + + /* We attempt to avoid this condition by setting stubs_always_after_branch + in elf32_arm_size_stubs if we've enabled the Cortex-A8 erratum workaround. + This check is just to be on the safe side... */ + if ((veneered_insn_loc & ~0xfff) == (veneer_entry_loc & ~0xfff)) + { + (*_bfd_error_handler) (_("%B: error: Cortex-A8 erratum stub is " + "allocated in unsafe location"), abfd); + return FALSE; + } + + switch (stub_entry->stub_type) + { + case arm_stub_a8_veneer_b: + case arm_stub_a8_veneer_b_cond: + branch_insn = 0xf0009000; + goto jump24; + + case arm_stub_a8_veneer_blx: + branch_insn = 0xf000e800; + goto jump24; + + case arm_stub_a8_veneer_bl: + { + unsigned int i1, j1, i2, j2, s; + + branch_insn = 0xf000d000; + + jump24: + if (branch_offset < -16777216 || branch_offset > 16777214) + { + /* There's not much we can do apart from complain if this + happens. */ + (*_bfd_error_handler) (_("%B: error: Cortex-A8 erratum stub out " + "of range (input file too large)"), abfd); + return FALSE; + } + + /* i1 = not(j1 eor s), so: + not i1 = j1 eor s + j1 = (not i1) eor s. */ + + branch_insn |= (branch_offset >> 1) & 0x7ff; + branch_insn |= ((branch_offset >> 12) & 0x3ff) << 16; + i2 = (branch_offset >> 22) & 1; + i1 = (branch_offset >> 23) & 1; + s = (branch_offset >> 24) & 1; + j1 = (!i1) ^ s; + j2 = (!i2) ^ s; + branch_insn |= j2 << 11; + branch_insn |= j1 << 13; + branch_insn |= s << 26; + } + break; + + default: + BFD_FAIL (); + return FALSE; + } + + bfd_put_16 (abfd, (branch_insn >> 16) & 0xffff, &contents[index]); + bfd_put_16 (abfd, branch_insn & 0xffff, &contents[index + 2]); + + return TRUE; +} + /* Do code byteswapping. Return FALSE afterwards so that the section is written out as normal. */ @@ -12449,7 +13232,7 @@ elf32_arm_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents) { - int mapcount, errcount; + unsigned int mapcount, errcount; _arm_elf_section_data *arm_data; struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info); elf32_arm_section_map *map; @@ -12458,7 +13241,7 @@ elf32_arm_write_section (bfd *output_bfd, bfd_vma end; bfd_vma offset = sec->output_section->vma + sec->output_offset; bfd_byte tmp; - int i; + unsigned int i; /* If this section has not been allocated an _arm_elf_section_data structure then we cannot record anything. */ @@ -12633,6 +13416,18 @@ elf32_arm_write_section (bfd *output_bfd, return TRUE; } + /* Fix code to point to Cortex-A8 erratum stubs. */ + if (globals->fix_cortex_a8) + { + struct a8_branch_to_stub_data data; + + data.writing_section = sec; + data.contents = contents; + + bfd_hash_traverse (&globals->stub_hash_table, make_branch_to_a8_stub, + &data); + } + if (mapcount == 0) return FALSE; diff --git a/ld/ChangeLog b/ld/ChangeLog index 7e9991699e..0671b7f23d 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,15 @@ +2009-05-22 Julian Brown + + * emultempl/armelf.em (fix_cortex_a8): New. + (arm_elf_before_allocation): Call bfd_elf32_arm_set_cortex_a8_fix. + (arm_elf_create_output_section_statements): Add fix_cortex_a8 to + bfd_elf32_arm_set_target_relocs. + (OPTION_FIX_CORTEX_A8, OPTION_NO_FIX_CORTEX_A8): New. + (PARSE_AND_LIST_LONGOPTS): Add [no-]fix-cortex-a8 options. + (PARSE_AND_LIST_OPTIONS): Add [no-]fix-cortex-a8 options. + (PARSE_AND_LIST_ARGS_CASES): Handle OPTION_[NO_]FIX_CORTEX_A8. + * ld.texinfo (--[no-]fix-cortex-a8): Briefly document new options. + 2009-05-22 Nathan Sidwell * ldlang.c (lang_check_section_addresses): Ignore non-loadable diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index 2d63a63f10..de7fe689ff 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -37,6 +37,7 @@ static char *target2_type = "${TARGET2_TYPE}"; static int fix_v4bx = 0; static int use_blx = 0; static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT; +static int fix_cortex_a8 = -1; static int no_enum_size_warning = 0; static int no_wchar_size_warning = 0; static int pic_veneer = 0; @@ -60,6 +61,9 @@ arm_elf_before_allocation (void) due to architecture version. */ bfd_elf32_arm_set_vfp11_fix (link_info.output_bfd, &link_info); + /* Auto-select Cortex-A8 erratum fix if it wasn't explicitly specified. */ + bfd_elf32_arm_set_cortex_a8_fix (link_info.output_bfd, &link_info); + /* We should be able to set the size of the interworking stub section. We can't do it until later if we have dynamic sections, though. */ if (! elf_hash_table (&link_info)->dynamic_sections_created) @@ -458,7 +462,7 @@ 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); + pic_veneer, fix_cortex_a8); stub_file = lang_add_input_file ("linker stubs", lang_input_file_is_fake_enum, @@ -520,6 +524,8 @@ PARSE_AND_LIST_PROLOGUE=' #define OPTION_FIX_V4BX_INTERWORKING 311 #define OPTION_STUBGROUP_SIZE 312 #define OPTION_NO_WCHAR_SIZE_WARNING 313 +#define OPTION_FIX_CORTEX_A8 314 +#define OPTION_NO_FIX_CORTEX_A8 315 ' PARSE_AND_LIST_SHORTOPTS=p @@ -539,6 +545,8 @@ PARSE_AND_LIST_LONGOPTS=' { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER}, { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE }, { "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING}, + { "fix-cortex-a8", no_argument, NULL, OPTION_FIX_CORTEX_A8 }, + { "no-fix-cortex-a8", no_argument, NULL, OPTION_NO_FIX_CORTEX_A8 }, ' PARSE_AND_LIST_OPTIONS=' @@ -565,6 +573,7 @@ PARSE_AND_LIST_OPTIONS=' after each stub section. Values of +/-1 indicate\n\ the linker should choose suitable defaults.\n" )); + fprintf (file, _(" --[no-]fix-cortex-a8 Disable/enable Cortex-A8 Thumb-2 branch erratum fix\n")); ' PARSE_AND_LIST_ARGS_CASES=' @@ -636,6 +645,14 @@ PARSE_AND_LIST_ARGS_CASES=' einfo (_("%P%F: invalid number `%s'\''\n"), optarg); } break; + + case OPTION_FIX_CORTEX_A8: + fix_cortex_a8 = 1; + break; + + case OPTION_NO_FIX_CORTEX_A8: + fix_cortex_a8 = 0; + break; ' # We have our own before_allocation etc. functions, but they call diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 2121725664..fbda2657fe 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -5865,6 +5865,13 @@ instructions into @code{bal} instructions when it determines that the target subroutine is a leaf routine (that is, the target subroutine does not itself call any subroutines). +@cindex Cortex-A8 erratum workaround +@kindex --fix-cortex-a8 +@kindex --no-fix-cortex-a8 +The @samp{--fix-cortex-a8} switch enables a link-time workaround for an erratum in certain Cortex-A8 processors. The workaround is enabled by default if you are targeting the ARM v7-A architecture profile. It can be enabled otherwise by specifying @samp{--fix-cortex-a8}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a8}. + +The erratum only affects Thumb-2 code. Please contact ARM for further details. + @ifclear GENERIC @lowersections @end ifclear diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 0df5dbccac..1613b29365 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,28 @@ +2009-05-22 Julian Brown + + * ld-arm/cortex-a8-arm-target.s: New. + * ld-arm/cortex-a8-thumb-target.s: New. + * ld-arm/cortex-a8-fix-b-rel.s: New. + * ld-arm/cortex-a8-fix-b-rel-arm.d: New. + * ld-arm/cortex-a8-fix-b-rel-thumb.d: New. + * ld-arm/cortex-a8-fix-b.s: New. + * ld-arm/cortex-a8-fix-b.d: New. + * ld-arm/cortex-a8-fix-bl-rel.s: New. + * ld-arm/cortex-a8-fix-bl-rel-arm.d: New. + * ld-arm/cortex-a8-fix-bl-rel-thumb.d: New. + * ld-arm/cortex-a8-fix-bl.s: New. + * ld-arm/cortex-a8-fix-bl.d: New. + * ld-arm/cortex-a8-fix-bcc-rel.s: New. + * ld-arm/cortex-a8-fix-bcc-rel-thumb.d: New. + * ld-arm/cortex-a8-fix-bcc.s: New. + * ld-arm/cortex-a8-fix-bcc.d: New. + * ld-arm/cortex-a8-fix-blx-rel.s: New. + * ld-arm/cortex-a8-fix-blx-rel-arm.d: New. + * ld-arm/cortex-a8-fix-blx-rel-thumb.d: New. + * ld-arm/cortex-a8-fix-blx.s: New. + * ld-arm/cortex-a8-fix-blx.d: New. + * ld-arm/arm-elf.exp: Add new tests. + 2009-05-22 Nathan Sidwell * ld-scripts/rgn-at4.t: New. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 4e8a9339aa..de3628eb12 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -161,6 +161,50 @@ set armelftests { "-EL --vfp11-denorm-fix=scalar -Ttext=0x8000" "-EL -mfpu=vfpxd" {vfp11-fix-none.s} {{objdump -dr vfp11-fix-none.d}} "vfp11-fix-none"} + {"Cortex-A8 erratum fix, b.w" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-fix-b.s} + {{objdump -dr cortex-a8-fix-b.d}} + "cortex-a8-fix-b"} + {"Cortex-A8 erratum fix, bl.w" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-fix-bl.s} + {{objdump -dr cortex-a8-fix-bl.d}} + "cortex-a8-fix-bl"} + {"Cortex-A8 erratum fix, bcc.w" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-fix-bcc.s} + {{objdump -dr cortex-a8-fix-bcc.d}} + "cortex-a8-fix-bcc"} + {"Cortex-A8 erratum fix, blx.w" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-fix-blx.s} + {{objdump -dr cortex-a8-fix-blx.d}} + "cortex-a8-fix-blx"} + {"Cortex-A8 erratum fix, relocate b.w to ARM" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-arm-target.s cortex-a8-fix-b-rel.s} + {{objdump -dr cortex-a8-fix-b-rel-arm.d}} + "cortex-a8-fix-b-rel-arm"} + {"Cortex-A8 erratum fix, relocate b.w to Thumb" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-thumb-target.s cortex-a8-fix-b-rel.s} + {{objdump -dr cortex-a8-fix-b-rel-thumb.d}} + "cortex-a8-fix-b-rel-thumb"} + {"Cortex-A8 erratum fix, relocate bl.w to ARM" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-arm-target.s cortex-a8-fix-bl-rel.s} + {{objdump -dr cortex-a8-fix-bl-rel-arm.d}} + "cortex-a8-fix-bl-rel-arm"} + {"Cortex-A8 erratum fix, relocate bl.w to Thumb" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-thumb-target.s cortex-a8-fix-bl-rel.s} + {{objdump -dr cortex-a8-fix-bl-rel-thumb.d}} + "cortex-a8-fix-bl-rel-thumb"} + {"Cortex-A8 erratum fix, relocate b.w to Thumb" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-thumb-target.s cortex-a8-fix-bcc-rel.s} + {{objdump -dr cortex-a8-fix-bcc-rel-thumb.d}} + "cortex-a8-fix-bcc-rel-thumb"} + {"Cortex-A8 erratum fix, relocate blx.w to ARM" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-arm-target.s cortex-a8-fix-blx-rel.s} + {{objdump -dr cortex-a8-fix-blx-rel-arm.d}} + "cortex-a8-fix-blx-rel-arm"} + {"Cortex-A8 erratum fix, relocate blx.w to Thumb" + "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-thumb-target.s cortex-a8-fix-blx-rel.s} + {{objdump -dr cortex-a8-fix-blx-rel-thumb.d}} + "cortex-a8-fix-blx-rel-thumb"} {"Unwinding and -gc-sections" "-gc-sections" "" {gc-unwind.s} {{objdump -sj.data gc-unwind.d}} "gc-unwind"} diff --git a/ld/testsuite/ld-arm/cortex-a8-arm-target.s b/ld/testsuite/ld-arm/cortex-a8-arm-target.s new file mode 100644 index 0000000000..d5174c4f77 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-arm-target.s @@ -0,0 +1,9 @@ + .syntax unified + .cpu cortex-a8 + .text + .arm + .align 3 + .global targetfn + .type targetfn, %function +targetfn: + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-b-rel-arm.d b/ld/testsuite/ld-arm/cortex-a8-fix-b-rel-arm.d new file mode 100644 index 0000000000..0a2b0bd47f --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-b-rel-arm.d @@ -0,0 +1,83 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: e12fff1e bx lr + 8f04: e320f000 nop \{0\} + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f000 b87f b\.w 9010 <__targetfn_from_thumb> + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f000 b87b b\.w 9010 <__targetfn_from_thumb> + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f000 b877 b\.w 9010 <__targetfn_from_thumb> + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f000 b873 b\.w 9010 <__targetfn_from_thumb> + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f000 b86f b\.w 9010 <__targetfn_from_thumb> + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f000 b86b b\.w 9010 <__targetfn_from_thumb> + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f000 b867 b\.w 9010 <__targetfn_from_thumb> + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f000 b863 b\.w 9010 <__targetfn_from_thumb> + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f000 b85f b\.w 9010 <__targetfn_from_thumb> + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f000 b85b b\.w 9010 <__targetfn_from_thumb> + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f000 b857 b\.w 9010 <__targetfn_from_thumb> + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f000 b853 b\.w 9010 <__targetfn_from_thumb> + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f000 b84f b\.w 9010 <__targetfn_from_thumb> + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f000 b84b b\.w 9010 <__targetfn_from_thumb> + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f000 b847 b\.w 9010 <__targetfn_from_thumb> + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f000 b843 b\.w 9010 <__targetfn_from_thumb> + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f000 b83f b\.w 9010 <__targetfn_from_thumb> + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f000 b83b b\.w 9010 <__targetfn_from_thumb> + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f000 b837 b\.w 9010 <__targetfn_from_thumb> + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f000 b833 b\.w 9010 <__targetfn_from_thumb> + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f000 b82f b\.w 9010 <__targetfn_from_thumb> + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f000 b82b b\.w 9010 <__targetfn_from_thumb> + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f000 b827 b\.w 9010 <__targetfn_from_thumb> + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f000 b823 b\.w 9010 <__targetfn_from_thumb> + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f000 b81f b\.w 9010 <__targetfn_from_thumb> + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f000 b81b b\.w 9010 <__targetfn_from_thumb> + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f000 b817 b\.w 9010 <__targetfn_from_thumb> + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f000 b813 b\.w 9010 <__targetfn_from_thumb> + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f000 b80f b\.w 9010 <__targetfn_from_thumb> + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f000 b80b b\.w 9010 <__targetfn_from_thumb> + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 b807 b\.w 9010 <__targetfn_from_thumb> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f000 b803 b\.w 9010 <__targetfn_from_thumb> + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + +00009010 <__targetfn_from_thumb>: + 9010: 4778 bx pc + 9012: 46c0 nop \(mov r8, r8\) + 9014: eaffffb9 b 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-b-rel-thumb.d b/ld/testsuite/ld-arm/cortex-a8-fix-b-rel-thumb.d new file mode 100644 index 0000000000..60a254b85a --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-b-rel-thumb.d @@ -0,0 +1,80 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: 4770 bx lr + 8f02: bf00 nop + 8f04: f3af 8000 nop\.w + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff bff7 b\.w 8f00 + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff bff3 b\.w 8f00 + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff bfef b\.w 8f00 + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff bfeb b\.w 8f00 + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff bfe7 b\.w 8f00 + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff bfe3 b\.w 8f00 + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff bfdf b\.w 8f00 + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff bfdb b\.w 8f00 + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff bfd7 b\.w 8f00 + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff bfd3 b\.w 8f00 + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff bfcf b\.w 8f00 + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff bfcb b\.w 8f00 + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff bfc7 b\.w 8f00 + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff bfc3 b\.w 8f00 + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff bfbf b\.w 8f00 + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff bfbb b\.w 8f00 + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff bfb7 b\.w 8f00 + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff bfb3 b\.w 8f00 + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff bfaf b\.w 8f00 + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff bfab b\.w 8f00 + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff bfa7 b\.w 8f00 + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff bfa3 b\.w 8f00 + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff bf9f b\.w 8f00 + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff bf9b b\.w 8f00 + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff bf97 b\.w 8f00 + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff bf93 b\.w 8f00 + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff bf8f b\.w 8f00 + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff bf8b b\.w 8f00 + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff bf87 b\.w 8f00 + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff bf83 b\.w 8f00 + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 b807 b\.w 9010 <_start\+0x108> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f7ff bf7b b\.w 8f00 + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + 9010: f7ff bf76 b\.w 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-b-rel.s b/ld/testsuite/ld-arm/cortex-a8-fix-b-rel.s new file mode 100644 index 0000000000..3ec95abd56 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-b-rel.s @@ -0,0 +1,41 @@ + .syntax unified + .cpu cortex-a8 + .thumb + .text + + @ expansion 32 bytes + .macro bw1 +1: + add.w r0, r1, r2 + b.w targetfn + add.w r0, r1, r2 + b.w targetfn + add.w r0, r1, r2 + b.w targetfn + add.w r0, r1, r2 + b.w targetfn + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .align 3 + .global _start + .thumb + .thumb_func + .type _start, %function +_start: + nop + + @ If branching to an ARM destination, we *don't* want to create a + @ Cortex-A8 stub: the Thumb-to-ARM stub will suffice (and we need it + @ to change mode). + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-b.d b/ld/testsuite/ld-arm/cortex-a8-fix-b.d new file mode 100644 index 0000000000..b2d44817a9 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-b.d @@ -0,0 +1,75 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 <_start>: + 8f00: bf00 nop + 8f02: eb01 0002 add\.w r0, r1, r2 + 8f06: f7ff bffc b\.w 8f02 <_start\+0x2> + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff bff8 b\.w 8f02 <_start\+0x2> + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff bff4 b\.w 8f02 <_start\+0x2> + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff bff0 b\.w 8f02 <_start\+0x2> + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff bffc b\.w 8f22 <_start\+0x22> + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff bff8 b\.w 8f22 <_start\+0x22> + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff bff4 b\.w 8f22 <_start\+0x22> + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff bff0 b\.w 8f22 <_start\+0x22> + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff bffc b\.w 8f42 <_start\+0x42> + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff bff8 b\.w 8f42 <_start\+0x42> + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff bff4 b\.w 8f42 <_start\+0x42> + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff bff0 b\.w 8f42 <_start\+0x42> + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff bffc b\.w 8f62 <_start\+0x62> + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff bff8 b\.w 8f62 <_start\+0x62> + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff bff4 b\.w 8f62 <_start\+0x62> + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff bff0 b\.w 8f62 <_start\+0x62> + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff bffc b\.w 8f82 <_start\+0x82> + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff bff8 b\.w 8f82 <_start\+0x82> + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff bff4 b\.w 8f82 <_start\+0x82> + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff bff0 b\.w 8f82 <_start\+0x82> + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff bffc b\.w 8fa2 <_start\+0xa2> + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff bff8 b\.w 8fa2 <_start\+0xa2> + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff bff4 b\.w 8fa2 <_start\+0xa2> + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff bff0 b\.w 8fa2 <_start\+0xa2> + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff bffc b\.w 8fc2 <_start\+0xc2> + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff bff8 b\.w 8fc2 <_start\+0xc2> + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff bff4 b\.w 8fc2 <_start\+0xc2> + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff bff0 b\.w 8fc2 <_start\+0xc2> + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff bffc b\.w 8fe2 <_start\+0xe2> + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff bff8 b\.w 8fe2 <_start\+0xe2> + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff bff4 b\.w 8fe2 <_start\+0xe2> + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 b803 b\.w 9008 <_start\+0x108> + 9002: 4770 bx lr + 9004: f3af 8000 nop\.w + 9008: f7ff bfeb b\.w 8fe2 <_start\+0xe2> diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-b.s b/ld/testsuite/ld-arm/cortex-a8-fix-b.s new file mode 100644 index 0000000000..c0f21ac243 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-b.s @@ -0,0 +1,39 @@ + .syntax unified + .cpu cortex-a8 + .thumb + .text + + @ expansion 32 bytes + .macro bw1 +1: + add.w r0, r1, r2 + b.w 1b + add.w r0, r1, r2 + b.w 1b + add.w r0, r1, r2 + b.w 1b + add.w r0, r1, r2 + b.w 1b + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .align 3 + .global _start + .thumb + .thumb_func + .type _start, %function +_start: + nop + + @ Trigger Cortex-A8 erratum workaround with b instructions. + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel-thumb.d b/ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel-thumb.d new file mode 100644 index 0000000000..27a7fd42ac --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel-thumb.d @@ -0,0 +1,82 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: 4770 bx lr + 8f02: bf00 nop + 8f04: f3af 8000 nop\.w + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f53f aff7 bmi\.w 8f00 + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f53f aff3 bmi\.w 8f00 + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f53f afef bmi\.w 8f00 + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f53f afeb bmi\.w 8f00 + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f53f afe7 bmi\.w 8f00 + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f53f afe3 bmi\.w 8f00 + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f53f afdf bmi\.w 8f00 + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f53f afdb bmi\.w 8f00 + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f53f afd7 bmi\.w 8f00 + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f53f afd3 bmi\.w 8f00 + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f53f afcf bmi\.w 8f00 + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f53f afcb bmi\.w 8f00 + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f53f afc7 bmi\.w 8f00 + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f53f afc3 bmi\.w 8f00 + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f53f afbf bmi\.w 8f00 + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f53f afbb bmi\.w 8f00 + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f53f afb7 bmi\.w 8f00 + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f53f afb3 bmi\.w 8f00 + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f53f afaf bmi\.w 8f00 + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f53f afab bmi\.w 8f00 + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f53f afa7 bmi\.w 8f00 + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f53f afa3 bmi\.w 8f00 + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f53f af9f bmi\.w 8f00 + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f53f af9b bmi\.w 8f00 + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f53f af97 bmi\.w 8f00 + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f53f af93 bmi\.w 8f00 + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f53f af8f bmi\.w 8f00 + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f53f af8b bmi\.w 8f00 + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f53f af87 bmi\.w 8f00 + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f53f af83 bmi\.w 8f00 + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 b807 b\.w 9010 <_start\+0x108> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f53f af7b bmi\.w 8f00 + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + 9010: d401 bmi\.n 9016 <_start\+0x10e> + 9012: f7ff bff6 b\.w 9002 <_start\+0xfa> + 9016: f7ff bf73 b\.w 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel.s b/ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel.s new file mode 100644 index 0000000000..b7b945113a --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bcc-rel.s @@ -0,0 +1,38 @@ + .syntax unified + .cpu cortex-a8 + .thumb + .text + + @ expansion 32 bytes + .macro bw1 +1: + add.w r0, r1, r2 + bmi.w targetfn + add.w r0, r1, r2 + bmi.w targetfn + add.w r0, r1, r2 + bmi.w targetfn + add.w r0, r1, r2 + bmi.w targetfn + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .align 3 + .global _start + .thumb + .thumb_func + .type _start, %function +_start: + nop + + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bcc.d b/ld/testsuite/ld-arm/cortex-a8-fix-bcc.d new file mode 100644 index 0000000000..44b8110987 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bcc.d @@ -0,0 +1,77 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 <_start>: + 8f00: bf00 nop + 8f02: eb01 0002 add\.w r0, r1, r2 + 8f06: f4ff affc bcc\.w 8f02 <_start\+0x2> + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f4ff aff8 bcc\.w 8f02 <_start\+0x2> + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f4ff aff4 bcc\.w 8f02 <_start\+0x2> + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f4ff aff0 bcc\.w 8f02 <_start\+0x2> + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f4ff affc bcc\.w 8f22 <_start\+0x22> + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f4ff aff8 bcc\.w 8f22 <_start\+0x22> + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f4ff aff4 bcc\.w 8f22 <_start\+0x22> + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f4ff aff0 bcc\.w 8f22 <_start\+0x22> + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f4ff affc bcc\.w 8f42 <_start\+0x42> + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f4ff aff8 bcc\.w 8f42 <_start\+0x42> + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f4ff aff4 bcc\.w 8f42 <_start\+0x42> + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f4ff aff0 bcc\.w 8f42 <_start\+0x42> + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f4ff affc bcc\.w 8f62 <_start\+0x62> + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f4ff aff8 bcc\.w 8f62 <_start\+0x62> + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f4ff aff4 bcc\.w 8f62 <_start\+0x62> + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f4ff aff0 bcc\.w 8f62 <_start\+0x62> + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f4ff affc bcc\.w 8f82 <_start\+0x82> + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f4ff aff8 bcc\.w 8f82 <_start\+0x82> + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f4ff aff4 bcc\.w 8f82 <_start\+0x82> + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f4ff aff0 bcc\.w 8f82 <_start\+0x82> + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f4ff affc bcc\.w 8fa2 <_start\+0xa2> + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f4ff aff8 bcc\.w 8fa2 <_start\+0xa2> + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f4ff aff4 bcc\.w 8fa2 <_start\+0xa2> + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f4ff aff0 bcc\.w 8fa2 <_start\+0xa2> + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f4ff affc bcc\.w 8fc2 <_start\+0xc2> + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f4ff aff8 bcc\.w 8fc2 <_start\+0xc2> + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f4ff aff4 bcc\.w 8fc2 <_start\+0xc2> + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f4ff aff0 bcc\.w 8fc2 <_start\+0xc2> + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f4ff affc bcc\.w 8fe2 <_start\+0xe2> + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f4ff aff8 bcc\.w 8fe2 <_start\+0xe2> + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f4ff aff4 bcc\.w 8fe2 <_start\+0xe2> + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 b803 b\.w 9008 <_start\+0x108> + 9002: 4770 bx lr + 9004: f3af 8000 nop\.w + 9008: d301 bcc\.n 900e <_start\+0x10e> + 900a: f7ff bffa b\.w 9002 <_start\+0x102> + 900e: f7ff bfe8 b\.w 8fe2 <_start\+0xe2> diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bcc.s b/ld/testsuite/ld-arm/cortex-a8-fix-bcc.s new file mode 100644 index 0000000000..8a667a3fcf --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bcc.s @@ -0,0 +1,39 @@ + .syntax unified + .cpu cortex-a8 + .thumb + .text + + @ expansion 32 bytes + .macro bw1 +1: + add.w r0, r1, r2 + bcc.w 1b + add.w r0, r1, r2 + bcc.w 1b + add.w r0, r1, r2 + bcc.w 1b + add.w r0, r1, r2 + bcc.w 1b + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .align 3 + .global _start + .thumb + .thumb_func + .type _start, %function +_start: + nop + + @ Trigger Cortex-A8 erratum workaround with conditional branches. + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-arm.d b/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-arm.d new file mode 100644 index 0000000000..fcb3bab611 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-arm.d @@ -0,0 +1,79 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: e12fff1e bx lr + 8f04: e320f000 nop \{0\} + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff eff8 blx 8f00 + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff eff4 blx 8f00 + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff eff0 blx 8f00 + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff efec blx 8f00 + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff efe8 blx 8f00 + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff efe4 blx 8f00 + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff efe0 blx 8f00 + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff efdc blx 8f00 + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff efd8 blx 8f00 + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff efd4 blx 8f00 + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff efd0 blx 8f00 + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff efcc blx 8f00 + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff efc8 blx 8f00 + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff efc4 blx 8f00 + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff efc0 blx 8f00 + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff efbc blx 8f00 + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff efb8 blx 8f00 + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff efb4 blx 8f00 + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff efb0 blx 8f00 + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff efac blx 8f00 + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff efa8 blx 8f00 + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff efa4 blx 8f00 + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff efa0 blx 8f00 + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff ef9c blx 8f00 + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff ef98 blx 8f00 + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff ef94 blx 8f00 + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff ef90 blx 8f00 + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff ef8c blx 8f00 + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff ef88 blx 8f00 + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff ef84 blx 8f00 + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 e808 blx 9010 <_start\+0x108> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f7ff ef7c blx 8f00 + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + 9010: eaffffba b 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-thumb.d b/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-thumb.d new file mode 100644 index 0000000000..8cbd3e0bce --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel-thumb.d @@ -0,0 +1,80 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: 4770 bx lr + 8f02: bf00 nop + 8f04: f3af 8000 nop\.w + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff fff7 bl 8f00 + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff fff3 bl 8f00 + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff ffef bl 8f00 + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff ffeb bl 8f00 + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff ffe7 bl 8f00 + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff ffe3 bl 8f00 + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff ffdf bl 8f00 + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff ffdb bl 8f00 + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff ffd7 bl 8f00 + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff ffd3 bl 8f00 + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff ffcf bl 8f00 + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff ffcb bl 8f00 + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff ffc7 bl 8f00 + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff ffc3 bl 8f00 + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff ffbf bl 8f00 + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff ffbb bl 8f00 + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff ffb7 bl 8f00 + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff ffb3 bl 8f00 + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff ffaf bl 8f00 + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff ffab bl 8f00 + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff ffa7 bl 8f00 + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff ffa3 bl 8f00 + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff ff9f bl 8f00 + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff ff9b bl 8f00 + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff ff97 bl 8f00 + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff ff93 bl 8f00 + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff ff8f bl 8f00 + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff ff8b bl 8f00 + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff ff87 bl 8f00 + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff ff83 bl 8f00 + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 f807 bl 9010 <_start\+0x108> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f7ff ff7b bl 8f00 + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + 9010: f7ff bf76 b\.w 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel.s b/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel.s new file mode 100644 index 0000000000..2d21bbfb43 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bl-rel.s @@ -0,0 +1,40 @@ + .syntax unified + .cpu cortex-a8 + .thumb + .text + + @ expansion 32 bytes + .macro bw1 +1: + add.w r0, r1, r2 + bl.w targetfn + add.w r0, r1, r2 + bl.w targetfn + add.w r0, r1, r2 + bl.w targetfn + add.w r0, r1, r2 + bl.w targetfn + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .align 3 + .global _start + .thumb + .thumb_func + .type _start, %function +_start: + nop + + @ If calling an ARM destination, we *don't* want to create a + @ Cortex-A8 stub: the Thumb-to-ARM stub will suffice. + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bl.d b/ld/testsuite/ld-arm/cortex-a8-fix-bl.d new file mode 100644 index 0000000000..50dcd4ff20 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bl.d @@ -0,0 +1,75 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 <_start>: + 8f00: bf00 nop + 8f02: eb01 0002 add\.w r0, r1, r2 + 8f06: f7ff fffc bl 8f02 <_start\+0x2> + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff fff8 bl 8f02 <_start\+0x2> + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff fff4 bl 8f02 <_start\+0x2> + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff fff0 bl 8f02 <_start\+0x2> + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff fffc bl 8f22 <_start\+0x22> + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff fff8 bl 8f22 <_start\+0x22> + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff fff4 bl 8f22 <_start\+0x22> + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff fff0 bl 8f22 <_start\+0x22> + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff fffc bl 8f42 <_start\+0x42> + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff fff8 bl 8f42 <_start\+0x42> + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff fff4 bl 8f42 <_start\+0x42> + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff fff0 bl 8f42 <_start\+0x42> + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff fffc bl 8f62 <_start\+0x62> + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff fff8 bl 8f62 <_start\+0x62> + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff fff4 bl 8f62 <_start\+0x62> + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff fff0 bl 8f62 <_start\+0x62> + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff fffc bl 8f82 <_start\+0x82> + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff fff8 bl 8f82 <_start\+0x82> + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff fff4 bl 8f82 <_start\+0x82> + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff fff0 bl 8f82 <_start\+0x82> + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff fffc bl 8fa2 <_start\+0xa2> + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff fff8 bl 8fa2 <_start\+0xa2> + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff fff4 bl 8fa2 <_start\+0xa2> + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff fff0 bl 8fa2 <_start\+0xa2> + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff fffc bl 8fc2 <_start\+0xc2> + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff fff8 bl 8fc2 <_start\+0xc2> + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff fff4 bl 8fc2 <_start\+0xc2> + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff fff0 bl 8fc2 <_start\+0xc2> + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff fffc bl 8fe2 <_start\+0xe2> + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff fff8 bl 8fe2 <_start\+0xe2> + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff fff4 bl 8fe2 <_start\+0xe2> + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 f803 bl 9008 <_start\+0x108> + 9002: 4770 bx lr + 9004: f3af 8000 nop\.w + 9008: f7ff bfeb b\.w 8fe2 <_start\+0xe2> diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-bl.s b/ld/testsuite/ld-arm/cortex-a8-fix-bl.s new file mode 100644 index 0000000000..6e40fb8811 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-bl.s @@ -0,0 +1,39 @@ + .syntax unified + .cpu cortex-a8 + .thumb + .text + + @ expansion 32 bytes + .macro bw1 +1: + add.w r0, r1, r2 + bl.w 1b + add.w r0, r1, r2 + bl.w 1b + add.w r0, r1, r2 + bl.w 1b + add.w r0, r1, r2 + bl.w 1b + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .align 3 + .global _start + .thumb + .thumb_func + .type _start, %function +_start: + nop + + @ Trigger Cortex-A8 erratum workaround with bl instructions. + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-arm.d b/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-arm.d new file mode 100644 index 0000000000..fcb3bab611 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-arm.d @@ -0,0 +1,79 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: e12fff1e bx lr + 8f04: e320f000 nop \{0\} + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff eff8 blx 8f00 + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff eff4 blx 8f00 + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff eff0 blx 8f00 + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff efec blx 8f00 + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff efe8 blx 8f00 + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff efe4 blx 8f00 + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff efe0 blx 8f00 + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff efdc blx 8f00 + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff efd8 blx 8f00 + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff efd4 blx 8f00 + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff efd0 blx 8f00 + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff efcc blx 8f00 + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff efc8 blx 8f00 + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff efc4 blx 8f00 + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff efc0 blx 8f00 + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff efbc blx 8f00 + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff efb8 blx 8f00 + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff efb4 blx 8f00 + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff efb0 blx 8f00 + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff efac blx 8f00 + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff efa8 blx 8f00 + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff efa4 blx 8f00 + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff efa0 blx 8f00 + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff ef9c blx 8f00 + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff ef98 blx 8f00 + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff ef94 blx 8f00 + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff ef90 blx 8f00 + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff ef8c blx 8f00 + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff ef88 blx 8f00 + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff ef84 blx 8f00 + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 e808 blx 9010 <_start\+0x108> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f7ff ef7c blx 8f00 + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + 9010: eaffffba b 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-thumb.d b/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-thumb.d new file mode 100644 index 0000000000..8cbd3e0bce --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel-thumb.d @@ -0,0 +1,80 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: 4770 bx lr + 8f02: bf00 nop + 8f04: f3af 8000 nop\.w + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff fff7 bl 8f00 + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff fff3 bl 8f00 + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff ffef bl 8f00 + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff ffeb bl 8f00 + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff ffe7 bl 8f00 + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff ffe3 bl 8f00 + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff ffdf bl 8f00 + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff ffdb bl 8f00 + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff ffd7 bl 8f00 + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff ffd3 bl 8f00 + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff ffcf bl 8f00 + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff ffcb bl 8f00 + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff ffc7 bl 8f00 + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff ffc3 bl 8f00 + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff ffbf bl 8f00 + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff ffbb bl 8f00 + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff ffb7 bl 8f00 + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff ffb3 bl 8f00 + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff ffaf bl 8f00 + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff ffab bl 8f00 + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff ffa7 bl 8f00 + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff ffa3 bl 8f00 + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff ff9f bl 8f00 + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff ff9b bl 8f00 + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff ff97 bl 8f00 + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff ff93 bl 8f00 + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff ff8f bl 8f00 + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff ff8b bl 8f00 + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff ff87 bl 8f00 + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff ff83 bl 8f00 + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 f807 bl 9010 <_start\+0x108> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f7ff ff7b bl 8f00 + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + 9010: f7ff bf76 b\.w 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel.s b/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel.s new file mode 100644 index 0000000000..efbfb4b050 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-blx-rel.s @@ -0,0 +1,38 @@ + .syntax unified + .cpu cortex-a8 + .thumb + .text + + @ expansion 32 bytes + .macro bw1 +1: + add.w r0, r1, r2 + blx.w targetfn + add.w r0, r1, r2 + blx.w targetfn + add.w r0, r1, r2 + blx.w targetfn + add.w r0, r1, r2 + blx.w targetfn + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .align 3 + .global _start + .thumb + .thumb_func + .type _start, %function +_start: + nop + + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-blx.d b/ld/testsuite/ld-arm/cortex-a8-fix-blx.d new file mode 100644 index 0000000000..4805256cd9 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-blx.d @@ -0,0 +1,79 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00008f00 : + 8f00: e1a02413 lsl r2, r3, r4 + 8f04: e12fff1e bx lr + +00008f08 <_start>: + 8f08: bf00 nop + 8f0a: eb01 0002 add\.w r0, r1, r2 + 8f0e: f7ff eff8 blx 8f00 + 8f12: eb01 0002 add\.w r0, r1, r2 + 8f16: f7ff eff4 blx 8f00 + 8f1a: eb01 0002 add\.w r0, r1, r2 + 8f1e: f7ff eff0 blx 8f00 + 8f22: eb01 0002 add\.w r0, r1, r2 + 8f26: f7ff efec blx 8f00 + 8f2a: eb01 0002 add\.w r0, r1, r2 + 8f2e: f7ff efe8 blx 8f00 + 8f32: eb01 0002 add\.w r0, r1, r2 + 8f36: f7ff efe4 blx 8f00 + 8f3a: eb01 0002 add\.w r0, r1, r2 + 8f3e: f7ff efe0 blx 8f00 + 8f42: eb01 0002 add\.w r0, r1, r2 + 8f46: f7ff efdc blx 8f00 + 8f4a: eb01 0002 add\.w r0, r1, r2 + 8f4e: f7ff efd8 blx 8f00 + 8f52: eb01 0002 add\.w r0, r1, r2 + 8f56: f7ff efd4 blx 8f00 + 8f5a: eb01 0002 add\.w r0, r1, r2 + 8f5e: f7ff efd0 blx 8f00 + 8f62: eb01 0002 add\.w r0, r1, r2 + 8f66: f7ff efcc blx 8f00 + 8f6a: eb01 0002 add\.w r0, r1, r2 + 8f6e: f7ff efc8 blx 8f00 + 8f72: eb01 0002 add\.w r0, r1, r2 + 8f76: f7ff efc4 blx 8f00 + 8f7a: eb01 0002 add\.w r0, r1, r2 + 8f7e: f7ff efc0 blx 8f00 + 8f82: eb01 0002 add\.w r0, r1, r2 + 8f86: f7ff efbc blx 8f00 + 8f8a: eb01 0002 add\.w r0, r1, r2 + 8f8e: f7ff efb8 blx 8f00 + 8f92: eb01 0002 add\.w r0, r1, r2 + 8f96: f7ff efb4 blx 8f00 + 8f9a: eb01 0002 add\.w r0, r1, r2 + 8f9e: f7ff efb0 blx 8f00 + 8fa2: eb01 0002 add\.w r0, r1, r2 + 8fa6: f7ff efac blx 8f00 + 8faa: eb01 0002 add\.w r0, r1, r2 + 8fae: f7ff efa8 blx 8f00 + 8fb2: eb01 0002 add\.w r0, r1, r2 + 8fb6: f7ff efa4 blx 8f00 + 8fba: eb01 0002 add\.w r0, r1, r2 + 8fbe: f7ff efa0 blx 8f00 + 8fc2: eb01 0002 add\.w r0, r1, r2 + 8fc6: f7ff ef9c blx 8f00 + 8fca: eb01 0002 add\.w r0, r1, r2 + 8fce: f7ff ef98 blx 8f00 + 8fd2: eb01 0002 add\.w r0, r1, r2 + 8fd6: f7ff ef94 blx 8f00 + 8fda: eb01 0002 add\.w r0, r1, r2 + 8fde: f7ff ef90 blx 8f00 + 8fe2: eb01 0002 add\.w r0, r1, r2 + 8fe6: f7ff ef8c blx 8f00 + 8fea: eb01 0002 add\.w r0, r1, r2 + 8fee: f7ff ef88 blx 8f00 + 8ff2: eb01 0002 add\.w r0, r1, r2 + 8ff6: f7ff ef84 blx 8f00 + 8ffa: eb01 0002 add\.w r0, r1, r2 + 8ffe: f000 e808 blx 9010 <_start\+0x108> + 9002: eb01 0002 add\.w r0, r1, r2 + 9006: f7ff ef7c blx 8f00 + 900a: 4770 bx lr + 900c: f3af 8000 nop\.w + 9010: eaffffba b 8f00 diff --git a/ld/testsuite/ld-arm/cortex-a8-fix-blx.s b/ld/testsuite/ld-arm/cortex-a8-fix-blx.s new file mode 100644 index 0000000000..5d740248e9 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-fix-blx.s @@ -0,0 +1,44 @@ + .syntax unified + .cpu cortex-a8 + .text + + @ expansion 32 bytes + .macro bw1 + add.w r0, r1, r2 + blx.w armfn + add.w r0, r1, r2 + blx.w armfn + add.w r0, r1, r2 + blx.w armfn + add.w r0, r1, r2 + blx.w armfn + .endm + + @ expansion 128 bytes + .macro bw2 + bw1 + bw1 + bw1 + bw1 + .endm + + .arm + .align 2 +armfn: + mov r2, r3, asl r4 + bx lr + + .global _start + + .thumb + .thumb_func + .align 3 + .type _start, %function +_start: + nop + + @ Trigger Cortex-A8 erratum workaround with blx instructions. + bw2 + bw2 + + bx lr diff --git a/ld/testsuite/ld-arm/cortex-a8-thumb-target.s b/ld/testsuite/ld-arm/cortex-a8-thumb-target.s new file mode 100644 index 0000000000..96c180f1df --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-thumb-target.s @@ -0,0 +1,10 @@ + .syntax unified + .cpu cortex-a8 + .text + .thumb + .thumb_func + .align 3 + .global targetfn + .type targetfn, %function +targetfn: + bx lr -- 2.34.1