mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-27 14:00:30 +00:00
[AArch64] Cortex-A53 erratum 835769 linker workaround
2014-10-22 Tejas Belagod <tejas.belagod@arm.com> bfd/ * bfd-in.h (bfd_elf64_aarch64_set_options): Add a parameter. * bfd-in2.h (bfd_elf64_aarch64_set_options): Likewise. * elfnn-aarch64.c (aarch64_erratum_835769_stub): New. (elf_aarch64_stub_type): Add new type aarch64_stub_erratum_835769_veneer. (elf_aarch64_stub_hash_entry): New fields for erratum 835769. (aarch64_erratum_835769_fix): New data struct to record erratum 835769. (elf_aarch64_link_hash_table: Global flags for 835769. (aarch64_build_one_stub): Add case for 835769. (aarch64_size_one_stub): Likewise. (aarch64_mem_op_p, aarch64_mlxl_p, aarch64_erratum_sequence,erratum_835769_scan): New. Decode and scan functions for erratum 835769. (elf_aarch64_create_or_find_stub_sec): New. (elfNN_aarch64_size_stubs): Look for erratum 835769 and record them. (bfd_elfNN_aarch64_set_options: Set global flag for 835769. (erratum_835769_branch_to_stub_data, make_branch_to_erratum_835769_stub):New. Connect up all the erratum stubs to occurances by branches. (elfNN_aarch64_write_section): New hook. (aarch64_map_one_stub): Output erratum stub symbol. (elfNN_aarch64_size_dynamic_sections): Init mapping symbol information for erratum 835769. (elf_backend_write_section): Define. ld/ * emultempl/aarch64elf.em: Add command-line option for erratum 835769. ld/testsuite/ * ld-aarch64/aarch64-elf.exp (aarch64elftests): Drive erratum 835769 tests. * ld-aarch64/erratum835769.d: New. * ld-aarch64/erratum835769.s: New.
This commit is contained in:
parent
79ccd89e58
commit
68fcca92b7
@ -1,3 +1,32 @@
|
||||
2014-10-24 Tejas Belagod <tejas.belagod@arm.com>
|
||||
|
||||
* bfd-in.h (bfd_elf64_aarch64_set_options): Add a parameter.
|
||||
* bfd-in2.h (bfd_elf64_aarch64_set_options): Likewise.
|
||||
* elfnn-aarch64.c (aarch64_erratum_835769_stub): New.
|
||||
(elf_aarch64_stub_type): Add new type
|
||||
aarch64_stub_erratum_835769_veneer.
|
||||
(elf_aarch64_stub_hash_entry): New fields for erratum 835769.
|
||||
(aarch64_erratum_835769_fix): New data struct to record erratum
|
||||
835769.
|
||||
(elf_aarch64_link_hash_table: Global flags for 835769.
|
||||
(aarch64_build_one_stub): Add case for 835769.
|
||||
(aarch64_size_one_stub): Likewise.
|
||||
(aarch64_mem_op_p, aarch64_mlxl_p,
|
||||
aarch64_erratum_sequence,erratum_835769_scan):
|
||||
New. Decode and scan functions for erratum 835769.
|
||||
(elf_aarch64_create_or_find_stub_sec): New.
|
||||
(elfNN_aarch64_size_stubs): Look for erratum 835769 and record
|
||||
them.
|
||||
(bfd_elfNN_aarch64_set_options: Set global flag for 835769.
|
||||
(erratum_835769_branch_to_stub_data,
|
||||
make_branch_to_erratum_835769_stub):New. Connect up all the
|
||||
erratum stubs to occurances by branches.
|
||||
(elfNN_aarch64_write_section): New hook.
|
||||
(aarch64_map_one_stub): Output erratum stub symbol.
|
||||
(elfNN_aarch64_size_dynamic_sections): Init mapping symbol
|
||||
information for erratum 835769.
|
||||
(elf_backend_write_section): Define.
|
||||
|
||||
2014-10-23 Victor Kamensky <victor.kamensky@linaro.org>
|
||||
|
||||
* elf32-arm.c (read_code32): New function to read 32 bit
|
||||
|
@ -937,10 +937,10 @@ extern void bfd_elf32_aarch64_init_maps
|
||||
(bfd *);
|
||||
|
||||
extern void bfd_elf64_aarch64_set_options
|
||||
(bfd *, struct bfd_link_info *, int, int, int);
|
||||
(bfd *, struct bfd_link_info *, int, int, int, int);
|
||||
|
||||
extern void bfd_elf32_aarch64_set_options
|
||||
(bfd *, struct bfd_link_info *, int, int, int);
|
||||
(bfd *, struct bfd_link_info *, int, int, int, int);
|
||||
|
||||
/* ELF AArch64 mapping symbol support. */
|
||||
#define BFD_AARCH64_SPECIAL_SYM_TYPE_MAP (1 << 0)
|
||||
|
@ -944,10 +944,10 @@ extern void bfd_elf32_aarch64_init_maps
|
||||
(bfd *);
|
||||
|
||||
extern void bfd_elf64_aarch64_set_options
|
||||
(bfd *, struct bfd_link_info *, int, int, int);
|
||||
(bfd *, struct bfd_link_info *, int, int, int, int);
|
||||
|
||||
extern void bfd_elf32_aarch64_set_options
|
||||
(bfd *, struct bfd_link_info *, int, int, int);
|
||||
(bfd *, struct bfd_link_info *, int, int, int, int);
|
||||
|
||||
/* ELF AArch64 mapping symbol support. */
|
||||
#define BFD_AARCH64_SPECIAL_SYM_TYPE_MAP (1 << 0)
|
||||
|
@ -1611,6 +1611,12 @@ static const uint32_t aarch64_long_branch_stub[] =
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
static const uint32_t aarch64_erratum_835769_stub[] =
|
||||
{
|
||||
0x00000000, /* Placeholder for multiply accumulate. */
|
||||
0x14000000, /* b <label> */
|
||||
};
|
||||
|
||||
/* Section name for stubs is the associated section name plus this
|
||||
string. */
|
||||
#define STUB_SUFFIX ".stub"
|
||||
@ -1620,6 +1626,7 @@ enum elf_aarch64_stub_type
|
||||
aarch64_stub_none,
|
||||
aarch64_stub_adrp_branch,
|
||||
aarch64_stub_long_branch,
|
||||
aarch64_stub_erratum_835769_veneer,
|
||||
};
|
||||
|
||||
struct elf_aarch64_stub_hash_entry
|
||||
@ -1654,6 +1661,10 @@ struct elf_aarch64_stub_hash_entry
|
||||
stub name in the hash table has to be unique; this does not, so
|
||||
it can be friendlier. */
|
||||
char *output_name;
|
||||
|
||||
/* The instruction which caused this stub to be generated (only valid for
|
||||
erratum 835769 workaround stubs at present). */
|
||||
uint32_t veneered_insn;
|
||||
};
|
||||
|
||||
/* Used to build a map of a section. This is required for mixed-endian
|
||||
@ -1679,6 +1690,17 @@ _aarch64_elf_section_data;
|
||||
#define elf_aarch64_section_data(sec) \
|
||||
((_aarch64_elf_section_data *) elf_section_data (sec))
|
||||
|
||||
/* A fix-descriptor for erratum 835769. */
|
||||
struct aarch64_erratum_835769_fix
|
||||
{
|
||||
bfd *input_bfd;
|
||||
asection *section;
|
||||
bfd_vma offset;
|
||||
uint32_t veneered_insn;
|
||||
char *stub_name;
|
||||
enum elf_aarch64_stub_type stub_type;
|
||||
};
|
||||
|
||||
/* The size of the thread control block which is defined to be two pointers. */
|
||||
#define TCB_SIZE (ARCH_SIZE/8)*2
|
||||
|
||||
@ -1799,6 +1821,15 @@ struct elf_aarch64_link_hash_table
|
||||
/* Nonzero to force PIC branch veneers. */
|
||||
int pic_veneer;
|
||||
|
||||
/* Fix erratum 835769. */
|
||||
int fix_erratum_835769;
|
||||
|
||||
/* A table of fix locations for erratum 835769. This holds erratum
|
||||
fix locations between elfNN_aarch64_size_stubs() and
|
||||
elfNN_aarch64_write_section(). */
|
||||
struct aarch64_erratum_835769_fix *aarch64_erratum_835769_fixes;
|
||||
unsigned int num_aarch64_erratum_835769_fixes;
|
||||
|
||||
/* The number of bytes in the initial entry in the PLT. */
|
||||
bfd_size_type plt_header_size;
|
||||
|
||||
@ -2343,6 +2374,9 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
bfd *stub_bfd;
|
||||
bfd_byte *loc;
|
||||
bfd_vma sym_value;
|
||||
bfd_vma veneered_insn_loc;
|
||||
bfd_vma veneer_entry_loc;
|
||||
bfd_signed_vma branch_offset = 0;
|
||||
unsigned int template_size;
|
||||
const uint32_t *template;
|
||||
unsigned int i;
|
||||
@ -2383,6 +2417,10 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
template = aarch64_long_branch_stub;
|
||||
template_size = sizeof (aarch64_long_branch_stub);
|
||||
break;
|
||||
case aarch64_stub_erratum_835769_veneer:
|
||||
template = aarch64_erratum_835769_stub;
|
||||
template_size = sizeof (aarch64_erratum_835769_stub);
|
||||
break;
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
return FALSE;
|
||||
@ -2425,6 +2463,23 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
stub_entry->stub_offset + 16,
|
||||
sym_value + 12, 0);
|
||||
break;
|
||||
|
||||
case aarch64_stub_erratum_835769_veneer:
|
||||
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;
|
||||
branch_offset = veneered_insn_loc - veneer_entry_loc;
|
||||
branch_offset >>= 2;
|
||||
branch_offset &= 0x3ffffff;
|
||||
bfd_putl32 (stub_entry->veneered_insn,
|
||||
stub_sec->contents + stub_entry->stub_offset);
|
||||
bfd_putl32 (template[1] | branch_offset,
|
||||
stub_sec->contents + stub_entry->stub_offset + 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2453,6 +2508,9 @@ aarch64_size_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
case aarch64_stub_long_branch:
|
||||
size = sizeof (aarch64_long_branch_stub);
|
||||
break;
|
||||
case aarch64_stub_erratum_835769_veneer:
|
||||
size = sizeof (aarch64_erratum_835769_stub);
|
||||
break;
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
return FALSE;
|
||||
@ -2641,6 +2699,388 @@ group_sections (struct elf_aarch64_link_hash_table *htab,
|
||||
|
||||
#undef PREV_SEC
|
||||
|
||||
#define AARCH64_BITS(x, pos, n) (((x) >> (pos)) & ((1 << (n)) - 1))
|
||||
|
||||
#define AARCH64_RT(insn) AARCH64_BITS (insn, 0, 5)
|
||||
#define AARCH64_RT2(insn) AARCH64_BITS (insn, 10, 5)
|
||||
#define AARCH64_RA(insn) AARCH64_BITS (insn, 10, 5)
|
||||
#define AARCH64_RD(insn) AARCH64_BITS (insn, 0, 5)
|
||||
#define AARCH64_RN(insn) AARCH64_BITS (insn, 5, 5)
|
||||
#define AARCH64_RM(insn) AARCH64_BITS (insn, 16, 5)
|
||||
|
||||
#define AARCH64_MAC(insn) (((insn) & 0xff000000) == 0x9b000000)
|
||||
#define AARCH64_BIT(insn, n) AARCH64_BITS (insn, n, 1)
|
||||
#define AARCH64_OP31(insn) AARCH64_BITS (insn, 21, 3)
|
||||
#define AARCH64_ZR 0x1f
|
||||
|
||||
/* All ld/st ops. See C4-182 of the ARM ARM. The encoding space for
|
||||
LD_PCREL, LDST_RO, LDST_UI and LDST_UIMM cover prefetch ops. */
|
||||
|
||||
#define AARCH64_LD(insn) (AARCH64_BIT (insn, 22) == 1)
|
||||
#define AARCH64_LDST(insn) (((insn) & 0x0a000000) == 0x08000000)
|
||||
#define AARCH64_LDST_EX(insn) (((insn) & 0x3f000000) == 0x08000000)
|
||||
#define AARCH64_LDST_PCREL(insn) (((insn) & 0x3b000000) == 0x18000000)
|
||||
#define AARCH64_LDST_NAP(insn) (((insn) & 0x3b800000) == 0x28000000)
|
||||
#define AARCH64_LDSTP_PI(insn) (((insn) & 0x3b800000) == 0x28800000)
|
||||
#define AARCH64_LDSTP_O(insn) (((insn) & 0x3b800000) == 0x29000000)
|
||||
#define AARCH64_LDSTP_PRE(insn) (((insn) & 0x3b800000) == 0x29800000)
|
||||
#define AARCH64_LDST_UI(insn) (((insn) & 0x3b200c00) == 0x38000000)
|
||||
#define AARCH64_LDST_PIIMM(insn) (((insn) & 0x3b200c00) == 0x38000400)
|
||||
#define AARCH64_LDST_U(insn) (((insn) & 0x3b200c00) == 0x38000800)
|
||||
#define AARCH64_LDST_PREIMM(insn) (((insn) & 0x3b200c00) == 0x38000c00)
|
||||
#define AARCH64_LDST_RO(insn) (((insn) & 0x3b200c00) == 0x38200800)
|
||||
#define AARCH64_LDST_UIMM(insn) (((insn) & 0x3b000000) == 0x39000000)
|
||||
#define AARCH64_LDST_SIMD_M(insn) (((insn) & 0xbfbf0000) == 0x0c000000)
|
||||
#define AARCH64_LDST_SIMD_M_PI(insn) (((insn) & 0xbfa00000) == 0x0c800000)
|
||||
#define AARCH64_LDST_SIMD_S(insn) (((insn) & 0xbf9f0000) == 0x0d000000)
|
||||
#define AARCH64_LDST_SIMD_S_PI(insn) (((insn) & 0xbf800000) == 0x0d800000)
|
||||
|
||||
/* Classify an INSN if it is indeed a load/store. Return TRUE if INSN
|
||||
is a load/store along with the Rt and Rtn. Return FALSE if not a
|
||||
load/store. */
|
||||
|
||||
static bfd_boolean
|
||||
aarch64_mem_op_p (uint32_t insn, unsigned int *rt, unsigned int *rtn,
|
||||
bfd_boolean *pair, bfd_boolean *load)
|
||||
{
|
||||
uint32_t opcode;
|
||||
unsigned int r;
|
||||
uint32_t opc = 0;
|
||||
uint32_t v = 0;
|
||||
uint32_t opc_v = 0;
|
||||
|
||||
/* Bail out quickly if INSN doesn't fall into the the load-store
|
||||
encoding space. */
|
||||
if (!AARCH64_LDST (insn))
|
||||
return FALSE;
|
||||
|
||||
*pair = FALSE;
|
||||
*load = FALSE;
|
||||
if (AARCH64_LDST_EX (insn))
|
||||
{
|
||||
*rt = AARCH64_RT (insn);
|
||||
*rtn = *rt;
|
||||
if (AARCH64_BIT (insn, 21) == 1)
|
||||
{
|
||||
*pair = TRUE;
|
||||
*rtn = AARCH64_RT2 (insn);
|
||||
}
|
||||
*load = AARCH64_LD (insn);
|
||||
return TRUE;
|
||||
}
|
||||
else if (AARCH64_LDST_NAP (insn)
|
||||
|| AARCH64_LDSTP_PI (insn)
|
||||
|| AARCH64_LDSTP_O (insn)
|
||||
|| AARCH64_LDSTP_PRE (insn))
|
||||
{
|
||||
*pair = TRUE;
|
||||
*rt = AARCH64_RT (insn);
|
||||
*rtn = AARCH64_RT2 (insn);
|
||||
*load = AARCH64_LD (insn);
|
||||
return TRUE;
|
||||
}
|
||||
else if (AARCH64_LDST_PCREL (insn)
|
||||
|| AARCH64_LDST_UI (insn)
|
||||
|| AARCH64_LDST_PIIMM (insn)
|
||||
|| AARCH64_LDST_U (insn)
|
||||
|| AARCH64_LDST_PREIMM (insn)
|
||||
|| AARCH64_LDST_RO (insn)
|
||||
|| AARCH64_LDST_UIMM (insn))
|
||||
{
|
||||
*rt = AARCH64_RT (insn);
|
||||
*rtn = *rt;
|
||||
if (AARCH64_LDST_PCREL (insn))
|
||||
*load = TRUE;
|
||||
opc = AARCH64_BITS (insn, 22, 2);
|
||||
v = AARCH64_BIT (insn, 26);
|
||||
opc_v = opc | (v << 2);
|
||||
*load = (opc_v == 1 || opc_v == 2 || opc_v == 3
|
||||
|| opc_v == 5 || opc_v == 7);
|
||||
return TRUE;
|
||||
}
|
||||
else if (AARCH64_LDST_SIMD_M (insn)
|
||||
|| AARCH64_LDST_SIMD_M_PI (insn))
|
||||
{
|
||||
*rt = AARCH64_RT (insn);
|
||||
*load = AARCH64_BIT (insn, 22);
|
||||
opcode = (insn >> 12) & 0xf;
|
||||
switch (opcode)
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
*rtn = *rt + 3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 6:
|
||||
*rtn = *rt + 2;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
*rtn = *rt;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 10:
|
||||
*rtn = *rt + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if (AARCH64_LDST_SIMD_S (insn)
|
||||
|| AARCH64_LDST_SIMD_S_PI (insn))
|
||||
{
|
||||
*rt = AARCH64_RT (insn);
|
||||
r = (insn >> 21) & 1;
|
||||
*load = AARCH64_BIT (insn, 22);
|
||||
opcode = (insn >> 13) & 0x7;
|
||||
switch (opcode)
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
*rtn = *rt + r;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
*rtn = *rt + (r == 0 ? 2 : 3);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
*rtn = *rt + r;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
*rtn = *rt + (r == 0 ? 2 : 3);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return TRUE if INSN is multiply-accumulate. */
|
||||
|
||||
static bfd_boolean
|
||||
aarch64_mlxl_p (uint32_t insn)
|
||||
{
|
||||
uint32_t op31 = AARCH64_OP31 (insn);
|
||||
|
||||
if (AARCH64_MAC (insn)
|
||||
&& (op31 == 0 || op31 == 1 || op31 == 5)
|
||||
/* Exclude MUL instructions which are encoded as a multiple accumulate
|
||||
with RA = XZR. */
|
||||
&& AARCH64_RA (insn) != AARCH64_ZR)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Some early revisions of the Cortex-A53 have an erratum (835769) whereby
|
||||
it is possible for a 64-bit multiply-accumulate instruction to generate an
|
||||
incorrect result. The details are quite complex and hard to
|
||||
determine statically, since branches in the code may exist in some
|
||||
circumstances, but all cases end with a memory (load, store, or
|
||||
prefetch) instruction followed immediately by the multiply-accumulate
|
||||
operation. We employ a linker patching technique, by moving the potentially
|
||||
affected multiply-accumulate instruction into a patch region and replacing
|
||||
the original instruction with a branch to the patch. This function checks
|
||||
if INSN_1 is the memory operation followed by a multiply-accumulate
|
||||
operation (INSN_2). Return TRUE if an erratum sequence is found, FALSE
|
||||
if INSN_1 and INSN_2 are safe. */
|
||||
|
||||
static bfd_boolean
|
||||
aarch64_erratum_sequence (uint32_t insn_1, uint32_t insn_2)
|
||||
{
|
||||
uint32_t rt;
|
||||
uint32_t rtn;
|
||||
uint32_t rn;
|
||||
uint32_t rm;
|
||||
uint32_t ra;
|
||||
bfd_boolean pair;
|
||||
bfd_boolean load;
|
||||
|
||||
if (aarch64_mlxl_p (insn_2)
|
||||
&& aarch64_mem_op_p (insn_1, &rt, &rtn, &pair, &load))
|
||||
{
|
||||
/* Any SIMD memory op is independent of the subsequent MLA
|
||||
by definition of the erratum. */
|
||||
if (AARCH64_BIT (insn_1, 26))
|
||||
return TRUE;
|
||||
|
||||
/* If not SIMD, check for integer memory ops and MLA relationship. */
|
||||
rn = AARCH64_RN (insn_2);
|
||||
ra = AARCH64_RA (insn_2);
|
||||
rm = AARCH64_RM (insn_2);
|
||||
|
||||
/* If this is a load and there's a true(RAW) dependency, we are safe
|
||||
and this is not an erratum sequence. */
|
||||
if (load &&
|
||||
(rt == rn || rt == rm || rt == ra
|
||||
|| (pair && (rtn == rn || rtn == rm || rtn == ra))))
|
||||
return FALSE;
|
||||
|
||||
/* We conservatively put out stubs for all other cases (including
|
||||
writebacks). */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
erratum_835769_scan (bfd *input_bfd,
|
||||
struct bfd_link_info *info,
|
||||
struct aarch64_erratum_835769_fix **fixes_p,
|
||||
unsigned int *num_fixes_p,
|
||||
unsigned int *fix_table_size_p)
|
||||
{
|
||||
asection *section;
|
||||
struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
|
||||
struct aarch64_erratum_835769_fix *fixes = *fixes_p;
|
||||
unsigned int num_fixes = *num_fixes_p;
|
||||
unsigned int fix_table_size = *fix_table_size_p;
|
||||
|
||||
if (htab == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (section = input_bfd->sections;
|
||||
section != NULL;
|
||||
section = section->next)
|
||||
{
|
||||
bfd_byte *contents = NULL;
|
||||
struct _aarch64_elf_section_data *sec_data;
|
||||
unsigned int span;
|
||||
|
||||
if (elf_section_type (section) != SHT_PROGBITS
|
||||
|| (elf_section_flags (section) & SHF_EXECINSTR) == 0
|
||||
|| (section->flags & SEC_EXCLUDE) != 0
|
||||
|| (section->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
|
||||
|| (section->output_section == bfd_abs_section_ptr))
|
||||
continue;
|
||||
|
||||
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 TRUE;
|
||||
|
||||
sec_data = elf_aarch64_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)
|
||||
? sec_data->map[0].vma + section->size
|
||||
: sec_data->map[span + 1].vma);
|
||||
unsigned int i;
|
||||
char span_type = sec_data->map[span].type;
|
||||
|
||||
if (span_type == 'd')
|
||||
continue;
|
||||
|
||||
for (i = span_start; i + 4 < span_end; i += 4)
|
||||
{
|
||||
uint32_t insn_1 = bfd_getl32 (contents + i);
|
||||
uint32_t insn_2 = bfd_getl32 (contents + i + 4);
|
||||
|
||||
if (aarch64_erratum_sequence (insn_1, insn_2))
|
||||
{
|
||||
char *stub_name = NULL;
|
||||
stub_name = (char *) bfd_malloc
|
||||
(strlen ("__erratum_835769_veneer_") + 16);
|
||||
if (stub_name != NULL)
|
||||
sprintf
|
||||
(stub_name,"__erratum_835769_veneer_%d", num_fixes);
|
||||
else
|
||||
return TRUE;
|
||||
|
||||
if (num_fixes == fix_table_size)
|
||||
{
|
||||
fix_table_size *= 2;
|
||||
fixes =
|
||||
(struct aarch64_erratum_835769_fix *)
|
||||
bfd_realloc (fixes,
|
||||
sizeof (struct aarch64_erratum_835769_fix)
|
||||
* fix_table_size);
|
||||
if (fixes == NULL)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
fixes[num_fixes].input_bfd = input_bfd;
|
||||
fixes[num_fixes].section = section;
|
||||
fixes[num_fixes].offset = i + 4;
|
||||
fixes[num_fixes].veneered_insn = insn_2;
|
||||
fixes[num_fixes].stub_name = stub_name;
|
||||
fixes[num_fixes].stub_type = aarch64_stub_erratum_835769_veneer;
|
||||
num_fixes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elf_section_data (section)->this_hdr.contents == NULL)
|
||||
free (contents);
|
||||
}
|
||||
|
||||
*fixes_p = fixes;
|
||||
*num_fixes_p = num_fixes;
|
||||
*fix_table_size_p = fix_table_size;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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 asection *
|
||||
elf_aarch64_create_or_find_stub_sec (asection **link_sec_p, asection *section,
|
||||
struct elf_aarch64_link_hash_table *htab)
|
||||
{
|
||||
asection *link_sec;
|
||||
asection *stub_sec;
|
||||
|
||||
link_sec = htab->stub_group[section->id].link_sec;
|
||||
BFD_ASSERT (link_sec != NULL);
|
||||
stub_sec = htab->stub_group[section->id].stub_sec;
|
||||
|
||||
if (stub_sec == NULL)
|
||||
{
|
||||
stub_sec = htab->stub_group[link_sec->id].stub_sec;
|
||||
if (stub_sec == NULL)
|
||||
{
|
||||
size_t namelen;
|
||||
bfd_size_type len;
|
||||
char *s_name;
|
||||
|
||||
namelen = strlen (link_sec->name);
|
||||
len = namelen + sizeof (STUB_SUFFIX);
|
||||
s_name = (char *) bfd_alloc (htab->stub_bfd, len);
|
||||
if (s_name == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (s_name, link_sec->name, namelen);
|
||||
memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
|
||||
stub_sec = (*htab->add_stub_section) (s_name, link_sec);
|
||||
|
||||
if (stub_sec == NULL)
|
||||
return NULL;
|
||||
htab->stub_group[link_sec->id].stub_sec = stub_sec;
|
||||
}
|
||||
htab->stub_group[section->id].stub_sec = stub_sec;
|
||||
}
|
||||
|
||||
if (link_sec_p)
|
||||
*link_sec_p = link_sec;
|
||||
|
||||
return stub_sec;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@ -2660,6 +3100,21 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
|
||||
bfd_boolean stubs_always_before_branch;
|
||||
bfd_boolean stub_changed = 0;
|
||||
struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
|
||||
struct aarch64_erratum_835769_fix *erratum_835769_fixes = NULL;
|
||||
unsigned int num_erratum_835769_fixes = 0;
|
||||
unsigned int erratum_835769_fix_table_size = 10;
|
||||
unsigned int i;
|
||||
|
||||
if (htab->fix_erratum_835769)
|
||||
{
|
||||
erratum_835769_fixes
|
||||
= (struct aarch64_erratum_835769_fix *)
|
||||
bfd_zmalloc
|
||||
(sizeof (struct aarch64_erratum_835769_fix) *
|
||||
erratum_835769_fix_table_size);
|
||||
if (erratum_835769_fixes == NULL)
|
||||
goto error_ret_free_local;
|
||||
}
|
||||
|
||||
/* Propagate mach to stub bfd, because it may not have been
|
||||
finalized when we created stub_bfd. */
|
||||
@ -2690,7 +3145,9 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
|
||||
bfd *input_bfd;
|
||||
unsigned int bfd_indx;
|
||||
asection *stub_sec;
|
||||
unsigned prev_num_erratum_835769_fixes = num_erratum_835769_fixes;
|
||||
|
||||
num_erratum_835769_fixes = 0;
|
||||
for (input_bfd = info->input_bfds, bfd_indx = 0;
|
||||
input_bfd != NULL; input_bfd = input_bfd->link.next, bfd_indx++)
|
||||
{
|
||||
@ -2943,8 +3400,20 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
|
||||
if (elf_section_data (section)->relocs == NULL)
|
||||
free (internal_relocs);
|
||||
}
|
||||
|
||||
if (htab->fix_erratum_835769)
|
||||
{
|
||||
/* Scan for sequences which might trigger erratum 835769. */
|
||||
if (erratum_835769_scan (input_bfd, info, &erratum_835769_fixes,
|
||||
&num_erratum_835769_fixes,
|
||||
&erratum_835769_fix_table_size) != 0)
|
||||
goto error_ret_free_local;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_num_erratum_835769_fixes != num_erratum_835769_fixes)
|
||||
stub_changed = TRUE;
|
||||
|
||||
if (!stub_changed)
|
||||
break;
|
||||
|
||||
@ -2952,15 +3421,76 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
|
||||
stub sections. */
|
||||
for (stub_sec = htab->stub_bfd->sections;
|
||||
stub_sec != NULL; stub_sec = stub_sec->next)
|
||||
stub_sec->size = 0;
|
||||
{
|
||||
/* Ignore non-stub sections. */
|
||||
if (!strstr (stub_sec->name, STUB_SUFFIX))
|
||||
continue;
|
||||
stub_sec->size = 0;
|
||||
}
|
||||
|
||||
bfd_hash_traverse (&htab->stub_hash_table, aarch64_size_one_stub, htab);
|
||||
|
||||
/* Add erratum 835769 veneers to stub section sizes too. */
|
||||
if (htab->fix_erratum_835769)
|
||||
for (i = 0; i < num_erratum_835769_fixes; i++)
|
||||
{
|
||||
stub_sec = elf_aarch64_create_or_find_stub_sec (NULL,
|
||||
erratum_835769_fixes[i].section, htab);
|
||||
|
||||
if (stub_sec == NULL)
|
||||
goto error_ret_free_local;
|
||||
|
||||
stub_sec->size += 8;
|
||||
}
|
||||
|
||||
/* Ask the linker to do its stuff. */
|
||||
(*htab->layout_sections_again) ();
|
||||
stub_changed = FALSE;
|
||||
}
|
||||
|
||||
/* Add stubs for erratum 835769 fixes now. */
|
||||
if (htab->fix_erratum_835769)
|
||||
{
|
||||
for (i = 0; i < num_erratum_835769_fixes; i++)
|
||||
{
|
||||
struct elf_aarch64_stub_hash_entry *stub_entry;
|
||||
char *stub_name = erratum_835769_fixes[i].stub_name;
|
||||
asection *section = erratum_835769_fixes[i].section;
|
||||
unsigned int section_id = erratum_835769_fixes[i].section->id;
|
||||
asection *link_sec = htab->stub_group[section_id].link_sec;
|
||||
asection *stub_sec = htab->stub_group[section_id].stub_sec;
|
||||
|
||||
stub_entry = aarch64_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 = erratum_835769_fixes[i].stub_type;
|
||||
stub_entry->target_section = section;
|
||||
stub_entry->target_value = erratum_835769_fixes[i].offset;
|
||||
stub_entry->veneered_insn = erratum_835769_fixes[i].veneered_insn;
|
||||
stub_entry->output_name = erratum_835769_fixes[i].stub_name;
|
||||
}
|
||||
|
||||
/* Stash the erratum 835769 fix array for use later in
|
||||
elfNN_aarch64_write_section(). */
|
||||
htab->aarch64_erratum_835769_fixes = erratum_835769_fixes;
|
||||
htab->num_aarch64_erratum_835769_fixes = num_erratum_835769_fixes;
|
||||
}
|
||||
else
|
||||
{
|
||||
htab->aarch64_erratum_835769_fixes = NULL;
|
||||
htab->num_aarch64_erratum_835769_fixes = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error_ret_free_local:
|
||||
@ -3053,7 +3583,7 @@ bfd_elfNN_aarch64_init_maps (bfd *abfd)
|
||||
return;
|
||||
|
||||
if ((abfd->flags & DYNAMIC) != 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
hdr = &elf_symtab_hdr (abfd);
|
||||
localsyms = hdr->sh_info;
|
||||
@ -3091,12 +3621,14 @@ void
|
||||
bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
|
||||
struct bfd_link_info *link_info,
|
||||
int no_enum_warn,
|
||||
int no_wchar_warn, int pic_veneer)
|
||||
int no_wchar_warn, int pic_veneer,
|
||||
int fix_erratum_835769)
|
||||
{
|
||||
struct elf_aarch64_link_hash_table *globals;
|
||||
|
||||
globals = elf_aarch64_hash_table (link_info);
|
||||
globals->pic_veneer = pic_veneer;
|
||||
globals->fix_erratum_835769 = fix_erratum_835769;
|
||||
|
||||
BFD_ASSERT (is_aarch64_elf (output_bfd));
|
||||
elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
|
||||
@ -3406,6 +3938,89 @@ symbol_tlsdesc_got_offset (bfd *input_bfd, struct elf_link_hash_entry *h,
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Data for make_branch_to_erratum_835769_stub(). */
|
||||
|
||||
struct erratum_835769_branch_to_stub_data
|
||||
{
|
||||
asection *output_section;
|
||||
bfd_byte *contents;
|
||||
};
|
||||
|
||||
/* Helper to insert branches to erratum 835769 stubs in the right
|
||||
places for a particular section. */
|
||||
|
||||
static bfd_boolean
|
||||
make_branch_to_erratum_835769_stub (struct bfd_hash_entry *gen_entry,
|
||||
void *in_arg)
|
||||
{
|
||||
struct elf_aarch64_stub_hash_entry *stub_entry;
|
||||
struct erratum_835769_branch_to_stub_data *data;
|
||||
bfd_byte *contents;
|
||||
unsigned long branch_insn = 0;
|
||||
bfd_vma veneered_insn_loc, veneer_entry_loc;
|
||||
bfd_signed_vma branch_offset;
|
||||
unsigned int target;
|
||||
bfd *abfd;
|
||||
|
||||
stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
|
||||
data = (struct erratum_835769_branch_to_stub_data *) in_arg;
|
||||
|
||||
if (stub_entry->target_section != data->output_section
|
||||
|| stub_entry->stub_type != aarch64_stub_erratum_835769_veneer)
|
||||
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;
|
||||
branch_offset = veneer_entry_loc - veneered_insn_loc;
|
||||
|
||||
abfd = stub_entry->target_section->owner;
|
||||
if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc))
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: error: Erratum 835769 stub out "
|
||||
"of range (input file too large)"), abfd);
|
||||
|
||||
target = stub_entry->target_value;
|
||||
branch_insn = 0x14000000;
|
||||
branch_offset >>= 2;
|
||||
branch_offset &= 0x3ffffff;
|
||||
branch_insn |= branch_offset;
|
||||
bfd_putl32 (branch_insn, &contents[target]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
elfNN_aarch64_write_section (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *link_info,
|
||||
asection *sec,
|
||||
bfd_byte *contents)
|
||||
|
||||
{
|
||||
struct elf_aarch64_link_hash_table *globals =
|
||||
elf_aarch64_hash_table (link_info);
|
||||
|
||||
if (globals == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Fix code to point to erratum 835769 stubs. */
|
||||
if (globals->fix_erratum_835769)
|
||||
{
|
||||
struct erratum_835769_branch_to_stub_data data;
|
||||
|
||||
data.output_section = sec;
|
||||
data.contents = contents;
|
||||
bfd_hash_traverse (&globals->stub_hash_table,
|
||||
make_branch_to_erratum_835769_stub, &data);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Perform a relocation as part of a final link. */
|
||||
static bfd_reloc_status_type
|
||||
elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
|
||||
@ -5748,6 +6363,13 @@ aarch64_map_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_DATA, addr + 16))
|
||||
return FALSE;
|
||||
break;
|
||||
case aarch64_stub_erratum_835769_veneer:
|
||||
if (!elfNN_aarch64_output_stub_sym (osi, stub_name, addr,
|
||||
sizeof (aarch64_erratum_835769_stub)))
|
||||
return FALSE;
|
||||
if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
|
||||
return FALSE;
|
||||
break;
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
}
|
||||
@ -6443,6 +7065,16 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
}
|
||||
}
|
||||
|
||||
/* Init mapping symbols information to use later to distingush between
|
||||
code and data while scanning for erratam 835769. */
|
||||
if (htab->fix_erratum_835769)
|
||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
|
||||
{
|
||||
if (!is_aarch64_elf (ibfd))
|
||||
continue;
|
||||
bfd_elfNN_aarch64_init_maps (ibfd);
|
||||
}
|
||||
|
||||
/* We now have determined the sizes of the various dynamic sections.
|
||||
Allocate memory for them. */
|
||||
relocs = FALSE;
|
||||
@ -7286,6 +7918,9 @@ const struct elf_size_info elfNN_aarch64_size_info =
|
||||
#define elf_backend_size_info \
|
||||
elfNN_aarch64_size_info
|
||||
|
||||
#define elf_backend_write_section \
|
||||
elfNN_aarch64_write_section
|
||||
|
||||
#define elf_backend_can_refcount 1
|
||||
#define elf_backend_can_gc_sections 1
|
||||
#define elf_backend_plt_readonly 1
|
||||
|
@ -1,3 +1,7 @@
|
||||
2014-10-24 Tejas Belagod <tejas.belagod@arm.com>
|
||||
|
||||
* emultempl/aarch64elf.em: Add command-line option for erratum 835769.
|
||||
|
||||
2014-10-17 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
Implement --print-sysroot in ld.
|
||||
|
@ -30,6 +30,7 @@ fragment <<EOF
|
||||
static int no_enum_size_warning = 0;
|
||||
static int no_wchar_size_warning = 0;
|
||||
static int pic_veneer = 0;
|
||||
static int fix_erratum_835769 = 0;
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_before_parse (void)
|
||||
@ -302,7 +303,7 @@ aarch64_elf_create_output_section_statements (void)
|
||||
bfd_elf${ELFSIZE}_aarch64_set_options (link_info.output_bfd, &link_info,
|
||||
no_enum_size_warning,
|
||||
no_wchar_size_warning,
|
||||
pic_veneer);
|
||||
pic_veneer, fix_erratum_835769);
|
||||
|
||||
stub_file = lang_add_input_file ("linker stubs",
|
||||
lang_input_file_is_fake_enum,
|
||||
@ -351,6 +352,7 @@ PARSE_AND_LIST_PROLOGUE='
|
||||
#define OPTION_PIC_VENEER 310
|
||||
#define OPTION_STUBGROUP_SIZE 311
|
||||
#define OPTION_NO_WCHAR_SIZE_WARNING 312
|
||||
#define OPTION_FIX_ERRATUM_835769 313
|
||||
'
|
||||
|
||||
PARSE_AND_LIST_SHORTOPTS=p
|
||||
@ -361,6 +363,7 @@ 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-a53-835769", no_argument, NULL, OPTION_FIX_ERRATUM_835769},
|
||||
'
|
||||
|
||||
PARSE_AND_LIST_OPTIONS='
|
||||
@ -378,6 +381,7 @@ PARSE_AND_LIST_OPTIONS='
|
||||
after each stub section. Values of +/-1 indicate\n\
|
||||
the linker should choose suitable defaults.\n"
|
||||
));
|
||||
fprintf (file, _(" --fix-cortex-a53-835769 Fix erratum 835769\n"));
|
||||
'
|
||||
|
||||
PARSE_AND_LIST_ARGS_CASES='
|
||||
@ -397,6 +401,10 @@ PARSE_AND_LIST_ARGS_CASES='
|
||||
pic_veneer = 1;
|
||||
break;
|
||||
|
||||
case OPTION_FIX_ERRATUM_835769:
|
||||
fix_erratum_835769 = 1;
|
||||
break;
|
||||
|
||||
case OPTION_STUBGROUP_SIZE:
|
||||
{
|
||||
const char *end;
|
||||
|
@ -6570,6 +6570,13 @@ The @samp{--fix-cortex-a8} switch enables a link-time workaround for an erratum
|
||||
|
||||
The erratum only affects Thumb-2 code. Please contact ARM for further details.
|
||||
|
||||
@cindex Cortex-A53 erratum 835769 workaround
|
||||
@kindex --fix-cortex-a53-835769
|
||||
@kindex --no-fix-cortex-a53-835769
|
||||
The @samp{--fix-cortex-a53-835769} switch enables a link-time workaround for erratum 835769 present on certain early revisions of Cortex-A53 processors. The workaround is disabled by default. It can be enabled by specifying @samp{--fix-cortex-a53-835769}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a53-835769}.
|
||||
|
||||
Please contact ARM for further details.
|
||||
|
||||
@kindex --merge-exidx-entries
|
||||
@kindex --no-merge-exidx-entries
|
||||
@cindex Merging exidx entries
|
||||
|
@ -1,3 +1,10 @@
|
||||
2014-10-24 Tejas Belagod <tejas.belagod@arm.com>
|
||||
|
||||
* ld-aarch64/aarch64-elf.exp (aarch64elftests): Drive erratum
|
||||
835769 tests.
|
||||
* ld-aarch64/erratum835769.d: New.
|
||||
* ld-aarch64/erratum835769.s: New.
|
||||
|
||||
2014-10-17 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* ld-scripts/sysroot-prefix.exp: Log $ld_sysroot. Handle sysroot
|
||||
|
@ -35,6 +35,14 @@ if { ![is_elf_format] || ![istarget "aarch64*-*-*"] } {
|
||||
set aarch64elftests {
|
||||
{"EH Frame merge" "-Ttext 0x8000" "" "" {eh-frame-bar.s eh-frame-foo.s}
|
||||
{{objdump --dwarf=frames eh-frame.d}} "eh-frame"}
|
||||
{"Erratum 835769 dump test"
|
||||
"--fix-cortex-a53-835769" "" "" {erratum835769.s}
|
||||
{{objdump -dr erratum835769.d}}
|
||||
"erratum835769"}
|
||||
{"Erratum 835769 dump test -shared"
|
||||
"--fix-cortex-a53-835769 -shared" "" "" {erratum835769.s}
|
||||
{{objdump -dr erratum835769.d}}
|
||||
"erratum835769"}
|
||||
}
|
||||
|
||||
run_ld_link_tests $aarch64elftests
|
||||
|
48
ld/testsuite/ld-aarch64/erratum835769.d
Normal file
48
ld/testsuite/ld-aarch64/erratum835769.d
Normal file
@ -0,0 +1,48 @@
|
||||
#...
|
||||
Disassembly of section .text:
|
||||
#...
|
||||
[0-9a-f]+ <a1ldr>:
|
||||
[ \t0-9a-f]+:[ \t]+b8408c87[ \t]+ldr[ \t]+w7, \[x4,#8\]\!
|
||||
[ \t0-9a-f]+:[ \t]+1b017c06[ \t]+mul[ \t]+w6, w0, w1
|
||||
[ \t0-9a-f]+:[ \t]+f9400084[ \t]+ldr[ \t]+x4, \[x4\]
|
||||
[ \t0-9a-f]+:[ \t0-9a-z]+[ \t]+b[ \t]+[0-9a-f]+ <__erratum_835769_veneer_0>
|
||||
[ \t0-9a-f]+:[ \t]+aa0503e0[ \t]+mov[ \t]+x0, x5
|
||||
[ \t0-9a-f]+:[ \t]+d65f03c0[ \t]+ret
|
||||
|
||||
[0-9a-f]+ <a5ldr>:
|
||||
[ \t0-9a-f]+:[ \t]+b8408c87[ \t]+ldr[ \t]+w7, \[x4,#8\]!
|
||||
[ \t0-9a-f]+:[ \t]+1b017c06[ \t]+mul[ \t]+w6, w0, w1
|
||||
[ \t0-9a-f]+:[ \t]+f9400084[ \t]+ldr[ \t]+x4, \[x4\]
|
||||
[ \t0-9a-f]+:[ \t0-9a-z]+[ \t]+b[ \t]+[0-9a-f]+ <__erratum_835769_veneer_1>
|
||||
[ \t0-9a-f]+:[ \t]+aa0503e0[ \t]+mov[ \t]+x0, x5
|
||||
[ \t0-9a-f]+:[ \t]+d65f03c0[ \t]+ret
|
||||
|
||||
[0-9a-f]+ <a6ldr>:
|
||||
[ \t0-9a-f]+:[ \t]+b8408c87[ \t]+ldr[ \t]+w7, \[x4,#8\]!
|
||||
[ \t0-9a-f]+:[ \t]+1b017c06[ \t]+mul[ \t]+w6, w0, w1
|
||||
[ \t0-9a-f]+:[ \t]+f9400084[ \t]+ldr[ \t]+x4, \[x4\]
|
||||
[ \t0-9a-f]+:[ \t]+9b031885[ \t]+madd[ \t]+x5, x4, x3, x6
|
||||
[ \t0-9a-f]+:[ \t]+aa0503e0[ \t]+mov[ \t]+x0, x5
|
||||
[ \t0-9a-f]+:[ \t]+d65f03c0[ \t]+ret
|
||||
|
||||
[0-9a-f]+ <a7str>:
|
||||
[ \t0-9a-f]+:[ \t]+b8408c87[ \t]+ldr[ \t]+w7, \[x4,#8\]!
|
||||
[ \t0-9a-f]+:[ \t]+1b017c06[ \t]+mul[ \t]+w6, w0, w1
|
||||
[ \t0-9a-f]+:[ \t]+f9000084[ \t]+str[ \t]+x4, \[x4\]
|
||||
[ \t0-9a-f]+:[ \t0-9a-z]+[ \t]+b[ \t]+[0-9a-f]+ <__erratum_835769_veneer_2>
|
||||
[ \t0-9a-f]+:[ \t]+aa0503e0[ \t]+mov[ \t]+x0, x5
|
||||
[ \t0-9a-f]+:[ \t]+d65f03c0[ \t]+ret
|
||||
[ \t0-9a-f]+:[ \t]+00000000[ \t]+.inst[ \t]+0x00000000 ; undefined
|
||||
|
||||
[0-9a-f]+ <__erratum_835769_veneer_2>:
|
||||
[ \t0-9a-f]+:[ \t]+9b031885[ \t]+madd[ \t]+x5, x4, x3, x6
|
||||
[ \t0-9a-f]+:[ \t0-9a-z]+[ \t]+b[ \t]+[0-9a-f]+ <a7str\+0x[0-9a-f]+>
|
||||
|
||||
[0-9a-f]+ <__erratum_835769_veneer_1>:
|
||||
[ \t0-9a-f]+:[ \t]+9ba31845[ \t]+umaddl[ \t]+x5, w2, w3, x6
|
||||
[ \t0-9a-f]+:[ \t0-9a-z]+[ \t]+b[ \t]+[0-9a-f]+ <a5ldr\+0x[0-9a-f]+>
|
||||
|
||||
[0-9a-f]+ <__erratum_835769_veneer_0>:
|
||||
[ \t0-9a-f]+:[ \t]+9b031845[ \t]+madd[ \t]+x5, x2, x3, x6
|
||||
[ \t0-9a-f]+:[ \t0-9a-z]+[ \t]+b[ \t]+[0-9a-f]+ <a1ldr\+0x[0-9a-f]+>
|
||||
#pass
|
75
ld/testsuite/ld-aarch64/erratum835769.s
Normal file
75
ld/testsuite/ld-aarch64/erratum835769.s
Normal file
@ -0,0 +1,75 @@
|
||||
.text
|
||||
.align 2
|
||||
.global main
|
||||
.type main, %function
|
||||
main:
|
||||
stp x29, x30, [sp, -32]!
|
||||
add x29, sp, 0
|
||||
mov x0, -26
|
||||
str x0, [x29,16]
|
||||
mov x0, 26
|
||||
str x0, [x29,24]
|
||||
add x4, x29, 16
|
||||
mov x0, -1
|
||||
mov x1, 2
|
||||
mov x2, -3
|
||||
mov x3, 4
|
||||
bl a1ldr
|
||||
add x4, x29, 16
|
||||
mov x0, -1
|
||||
mov x1, 2
|
||||
mov x2, -3
|
||||
mov x3, 4
|
||||
bl a5ldr
|
||||
mov w0, 0
|
||||
ldp x29, x30, [sp], 32
|
||||
ret
|
||||
.size main, .-main
|
||||
|
||||
.align 2
|
||||
.global a1ldr
|
||||
.type a1ldr, %function
|
||||
a1ldr:
|
||||
ldr w7, [x4,8]!
|
||||
mul w6, w0, w1
|
||||
ldr x4, [x4]
|
||||
madd x5, x2, x3, x6
|
||||
mov x0, x5
|
||||
ret
|
||||
.size a1ldr, .-a1ldr
|
||||
|
||||
.align 2
|
||||
.global a5ldr
|
||||
.type a5ldr, %function
|
||||
a5ldr:
|
||||
ldr w7, [x4,8]!
|
||||
mul w6, w0, w1
|
||||
ldr x4, [x4]
|
||||
umaddl x5, w2, w3, x6
|
||||
mov x0, x5
|
||||
ret
|
||||
.size a5ldr, .-a5ldr
|
||||
|
||||
.align 2
|
||||
.global a6ldr
|
||||
.type a6ldr, %function
|
||||
a6ldr:
|
||||
ldr w7, [x4,8]!
|
||||
mul w6, w0, w1
|
||||
ldr x4, [x4]
|
||||
madd x5, x4, x3, x6
|
||||
mov x0, x5
|
||||
ret
|
||||
.size a6ldr, .-a6ldr
|
||||
|
||||
.align 2
|
||||
.global a6ldr
|
||||
.type a6ldr, %function
|
||||
a7str:
|
||||
ldr w7, [x4,8]!
|
||||
mul w6, w0, w1
|
||||
str x4, [x4]
|
||||
madd x5, x4, x3, x6
|
||||
mov x0, x5
|
||||
ret
|
||||
.size a7str, .-a7str
|
Loading…
Reference in New Issue
Block a user