aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2009-11-18 12:42:52 +0000
committerAlan Modra <amodra@gmail.com>2009-11-18 12:42:52 +0000
commit2d0f3896005097776f6bd807c7df97bbb6c99dd9 (patch)
tree4e9d68141118e584e1ae02cb080a8ed3d2773091
parent8cddccd3f191a62607325235ffd55cb37c1120bf (diff)
downloadgdb-2d0f3896005097776f6bd807c7df97bbb6c99dd9.zip
gdb-2d0f3896005097776f6bd807c7df97bbb6c99dd9.tar.gz
gdb-2d0f3896005097776f6bd807c7df97bbb6c99dd9.tar.bz2
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.
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/bfd-in.h4
-rw-r--r--bfd/bfd-in2.h4
-rw-r--r--bfd/elf32-ppc.c73
-rw-r--r--bfd/elf64-ppc.c31
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-ppc.c11
7 files changed, 77 insertions, 60 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 9bc8a85..d7d77bf 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,14 @@
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>
+
* targets.c: Don't include alloca-conf.h.
(bfd_get_target_info): Don't use alloca.
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index c3d2d97..82bf043 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -908,6 +908,10 @@ extern bfd_boolean elf32_arm_build_stubs
extern bfd_boolean elf32_arm_fix_exidx_coverage
(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. */
extern void bfd_ticoff_set_section_load_page
(struct bfd_section *, int);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 2cf3ba1..455ec56 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -915,6 +915,10 @@ extern bfd_boolean elf32_arm_build_stubs
extern bfd_boolean elf32_arm_fix_exidx_coverage
(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. */
extern void bfd_ticoff_set_section_load_page
(struct bfd_section *, int);
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 95058a2..e4fdc1e 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -6613,6 +6613,46 @@ is_static_defined (struct elf_link_hash_entry *h)
&& 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
to handle the relocations for a section.
@@ -6813,37 +6853,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
if ((tls_mask & TLS_TLS) != 0
&& (tls_mask & TLS_TPREL) == 0)
{
- bfd_vma insn, rtra;
+ bfd_vma insn;
+
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
- if ((insn & ((31 << 26) | (31 << 11)))
- == ((31 << 26) | (2 << 11)))
- 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 ();
- 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
+ insn = _bfd_elf_ppc_at_tls_transform (insn, 2);
+ if (insn == 0)
abort ();
- insn |= rtra;
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
r_type = R_PPC_TPREL16_LO;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 35757b8..e748a41 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -11018,37 +11018,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
if (tls_mask != 0
&& (tls_mask & TLS_TPREL) == 0)
{
- bfd_vma rtra;
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
- if ((insn & ((0x3f << 26) | (31 << 11)))
- == ((31 << 26) | (13 << 11)))
- 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 ();
- 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
+ insn = _bfd_elf_ppc_at_tls_transform (insn, 13);
+ if (insn == 0)
abort ();
- insn |= rtra;
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
/* Was PPC64_TLS which sits on insn boundary, now
PPC64_TPREL16_LO which is at low-order half-word. */
diff --git a/gas/ChangeLog b/gas/ChangeLog
index deb12a4..15092c4 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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>
Quentin Neill <quentin.neill@amd.com>
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 493bfe5..1d615e9 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -2732,8 +2732,15 @@ md_assemble (char *str)
break;
case BFD_RELOC_PPC_TLS:
- insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
- ppc_cpu, (char *) NULL, 0);
+ if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 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;
/* We'll only use the 32 (or 64) bit form of these relocations