bfd/
* bfd-in.h (_bfd_elf_ppc_at_tls_transform): Declare. * bfd-in2.h: Regenerate. * elf64-ppc.c (ppc64_elf_relocate_section): Move code for R_PPC64_TLS insn optimisation to.. * elf32-ppc.c (_bfd_elf_ppc_at_tls_transform): ..here. New function. (ppc_elf_relocate_section): Use it. gas/ * config/tc-ppc.c (md_assemble): Report error on invalid @tls operands and opcode.
This commit is contained in:
parent
8cddccd3f1
commit
2d0f389600
7 changed files with 77 additions and 60 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
2009-11-18 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* bfd-in.h (_bfd_elf_ppc_at_tls_transform): Declare.
|
||||||
|
* bfd-in2.h: Regenerate.
|
||||||
|
* elf64-ppc.c (ppc64_elf_relocate_section): Move code for R_PPC64_TLS
|
||||||
|
insn optimisation to..
|
||||||
|
* elf32-ppc.c (_bfd_elf_ppc_at_tls_transform): ..here. New function.
|
||||||
|
(ppc_elf_relocate_section): Use it.
|
||||||
|
|
||||||
2009-11-18 Alan Modra <amodra@bigpond.net.au>
|
2009-11-18 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
* targets.c: Don't include alloca-conf.h.
|
* targets.c: Don't include alloca-conf.h.
|
||||||
|
|
|
@ -908,6 +908,10 @@ extern bfd_boolean elf32_arm_build_stubs
|
||||||
extern bfd_boolean elf32_arm_fix_exidx_coverage
|
extern bfd_boolean elf32_arm_fix_exidx_coverage
|
||||||
(struct bfd_section **, unsigned int, struct bfd_link_info *);
|
(struct bfd_section **, unsigned int, struct bfd_link_info *);
|
||||||
|
|
||||||
|
/* PowerPC @tls opcode transform/validate. */
|
||||||
|
extern unsigned int _bfd_elf_ppc_at_tls_transform
|
||||||
|
(unsigned int, unsigned int);
|
||||||
|
|
||||||
/* TI COFF load page support. */
|
/* TI COFF load page support. */
|
||||||
extern void bfd_ticoff_set_section_load_page
|
extern void bfd_ticoff_set_section_load_page
|
||||||
(struct bfd_section *, int);
|
(struct bfd_section *, int);
|
||||||
|
|
|
@ -915,6 +915,10 @@ extern bfd_boolean elf32_arm_build_stubs
|
||||||
extern bfd_boolean elf32_arm_fix_exidx_coverage
|
extern bfd_boolean elf32_arm_fix_exidx_coverage
|
||||||
(struct bfd_section **, unsigned int, struct bfd_link_info *);
|
(struct bfd_section **, unsigned int, struct bfd_link_info *);
|
||||||
|
|
||||||
|
/* PowerPC @tls opcode transform/validate. */
|
||||||
|
extern unsigned int _bfd_elf_ppc_at_tls_transform
|
||||||
|
(unsigned int, unsigned int);
|
||||||
|
|
||||||
/* TI COFF load page support. */
|
/* TI COFF load page support. */
|
||||||
extern void bfd_ticoff_set_section_load_page
|
extern void bfd_ticoff_set_section_load_page
|
||||||
(struct bfd_section *, int);
|
(struct bfd_section *, int);
|
||||||
|
|
|
@ -6613,6 +6613,46 @@ is_static_defined (struct elf_link_hash_entry *h)
|
||||||
&& h->root.u.def.section->output_section != NULL);
|
&& h->root.u.def.section->output_section != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If INSN is an opcode that may be used with an @tls operand, return
|
||||||
|
the transformed insn for TLS optimisation, otherwise return 0. If
|
||||||
|
REG is non-zero only match an insn with RB or RA equal to REG. */
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
_bfd_elf_ppc_at_tls_transform (unsigned int insn, unsigned int reg)
|
||||||
|
{
|
||||||
|
unsigned int rtra;
|
||||||
|
|
||||||
|
if ((insn & (0x3f << 26)) != 31 << 26)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (reg == 0 || ((insn >> 11) & 0x1f) == reg)
|
||||||
|
rtra = insn & ((1 << 26) - (1 << 16));
|
||||||
|
else if (((insn >> 16) & 0x1f) == reg)
|
||||||
|
rtra = (insn & (0x1f << 21)) | ((insn & (0x1f << 11)) << 5);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((insn & (0x3ff << 1)) == 266 << 1)
|
||||||
|
/* add -> addi. */
|
||||||
|
insn = 14 << 26;
|
||||||
|
else if ((insn & (0x1f << 1)) == 23 << 1
|
||||||
|
&& ((insn & (0x1f << 6)) < 14 << 6
|
||||||
|
|| ((insn & (0x1f << 6)) >= 16 << 6
|
||||||
|
&& (insn & (0x1f << 6)) < 24 << 6)))
|
||||||
|
/* load and store indexed -> dform. */
|
||||||
|
insn = (32 | ((insn >> 6) & 0x1f)) << 26;
|
||||||
|
else if ((insn & (((0x1a << 5) | 0x1f) << 1)) == 21 << 1)
|
||||||
|
/* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
|
||||||
|
insn = ((58 | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1);
|
||||||
|
else if ((insn & (((0x1f << 5) | 0x1f) << 1)) == 341 << 1)
|
||||||
|
/* lwax -> lwa. */
|
||||||
|
insn = (58 << 26) | 2;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
insn |= rtra;
|
||||||
|
return insn;
|
||||||
|
}
|
||||||
|
|
||||||
/* The RELOCATE_SECTION function is called by the ELF backend linker
|
/* The RELOCATE_SECTION function is called by the ELF backend linker
|
||||||
to handle the relocations for a section.
|
to handle the relocations for a section.
|
||||||
|
|
||||||
|
@ -6813,37 +6853,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||||
if ((tls_mask & TLS_TLS) != 0
|
if ((tls_mask & TLS_TLS) != 0
|
||||||
&& (tls_mask & TLS_TPREL) == 0)
|
&& (tls_mask & TLS_TPREL) == 0)
|
||||||
{
|
{
|
||||||
bfd_vma insn, rtra;
|
bfd_vma insn;
|
||||||
|
|
||||||
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
|
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
|
||||||
if ((insn & ((31 << 26) | (31 << 11)))
|
insn = _bfd_elf_ppc_at_tls_transform (insn, 2);
|
||||||
== ((31 << 26) | (2 << 11)))
|
if (insn == 0)
|
||||||
rtra = insn & ((1 << 26) - (1 << 16));
|
|
||||||
else if ((insn & ((31 << 26) | (31 << 16)))
|
|
||||||
== ((31 << 26) | (2 << 16)))
|
|
||||||
rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5);
|
|
||||||
else
|
|
||||||
abort ();
|
abort ();
|
||||||
if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1)
|
|
||||||
/* add -> addi. */
|
|
||||||
insn = 14 << 26;
|
|
||||||
else if ((insn & (31 << 1)) == 23 << 1
|
|
||||||
&& ((insn & (31 << 6)) < 14 << 6
|
|
||||||
|| ((insn & (31 << 6)) >= 16 << 6
|
|
||||||
&& (insn & (31 << 6)) < 24 << 6)))
|
|
||||||
/* load and store indexed -> dform. */
|
|
||||||
insn = (32 | ((insn >> 6) & 31)) << 26;
|
|
||||||
else if ((insn & (31 << 1)) == 21 << 1
|
|
||||||
&& (insn & (0x1a << 6)) == 0)
|
|
||||||
/* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
|
|
||||||
insn = (((58 | ((insn >> 6) & 4)) << 26)
|
|
||||||
| ((insn >> 6) & 1));
|
|
||||||
else if ((insn & (31 << 1)) == 21 << 1
|
|
||||||
&& (insn & ((1 << 11) - (1 << 1))) == 341 << 1)
|
|
||||||
/* lwax -> lwa. */
|
|
||||||
insn = (58 << 26) | 2;
|
|
||||||
else
|
|
||||||
abort ();
|
|
||||||
insn |= rtra;
|
|
||||||
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
|
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
|
||||||
r_type = R_PPC_TPREL16_LO;
|
r_type = R_PPC_TPREL16_LO;
|
||||||
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
||||||
|
|
|
@ -11018,37 +11018,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||||
if (tls_mask != 0
|
if (tls_mask != 0
|
||||||
&& (tls_mask & TLS_TPREL) == 0)
|
&& (tls_mask & TLS_TPREL) == 0)
|
||||||
{
|
{
|
||||||
bfd_vma rtra;
|
|
||||||
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
|
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
|
||||||
if ((insn & ((0x3f << 26) | (31 << 11)))
|
insn = _bfd_elf_ppc_at_tls_transform (insn, 13);
|
||||||
== ((31 << 26) | (13 << 11)))
|
if (insn == 0)
|
||||||
rtra = insn & ((1 << 26) - (1 << 16));
|
|
||||||
else if ((insn & ((0x3f << 26) | (31 << 16)))
|
|
||||||
== ((31 << 26) | (13 << 16)))
|
|
||||||
rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5);
|
|
||||||
else
|
|
||||||
abort ();
|
abort ();
|
||||||
if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1)
|
|
||||||
/* add -> addi. */
|
|
||||||
insn = 14 << 26;
|
|
||||||
else if ((insn & (31 << 1)) == 23 << 1
|
|
||||||
&& ((insn & (31 << 6)) < 14 << 6
|
|
||||||
|| ((insn & (31 << 6)) >= 16 << 6
|
|
||||||
&& (insn & (31 << 6)) < 24 << 6)))
|
|
||||||
/* load and store indexed -> dform. */
|
|
||||||
insn = (32 | ((insn >> 6) & 31)) << 26;
|
|
||||||
else if ((insn & (31 << 1)) == 21 << 1
|
|
||||||
&& (insn & (0x1a << 6)) == 0)
|
|
||||||
/* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
|
|
||||||
insn = (((58 | ((insn >> 6) & 4)) << 26)
|
|
||||||
| ((insn >> 6) & 1));
|
|
||||||
else if ((insn & (31 << 1)) == 21 << 1
|
|
||||||
&& (insn & ((1 << 11) - (1 << 1))) == 341 << 1)
|
|
||||||
/* lwax -> lwa. */
|
|
||||||
insn = (58 << 26) | 2;
|
|
||||||
else
|
|
||||||
abort ();
|
|
||||||
insn |= rtra;
|
|
||||||
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
|
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
|
||||||
/* Was PPC64_TLS which sits on insn boundary, now
|
/* Was PPC64_TLS which sits on insn boundary, now
|
||||||
PPC64_TPREL16_LO which is at low-order half-word. */
|
PPC64_TPREL16_LO which is at low-order half-word. */
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2009-11-18 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* config/tc-ppc.c (md_assemble): Report error on invalid @tls operands
|
||||||
|
and opcode.
|
||||||
|
|
||||||
2009-11-17 Sebastian Pop <sebastian.pop@amd.com>
|
2009-11-17 Sebastian Pop <sebastian.pop@amd.com>
|
||||||
Quentin Neill <quentin.neill@amd.com>
|
Quentin Neill <quentin.neill@amd.com>
|
||||||
|
|
||||||
|
|
|
@ -2732,8 +2732,15 @@ md_assemble (char *str)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BFD_RELOC_PPC_TLS:
|
case BFD_RELOC_PPC_TLS:
|
||||||
insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
|
if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0))
|
||||||
ppc_cpu, (char *) NULL, 0);
|
as_bad (_("@tls may not be used with \"%s\" operands"),
|
||||||
|
opcode->name);
|
||||||
|
else if (operand->shift != 11)
|
||||||
|
as_bad (_("@tls may only be used in last operand"));
|
||||||
|
else
|
||||||
|
insn = ppc_insert_operand (insn, operand,
|
||||||
|
ppc_obj64 ? 13 : 2,
|
||||||
|
ppc_cpu, (char *) NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* We'll only use the 32 (or 64) bit form of these relocations
|
/* We'll only use the 32 (or 64) bit form of these relocations
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue