aboutsummaryrefslogtreecommitdiff
path: root/gdb/ppc64-tdep.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-06-03 10:55:29 +0930
committerAlan Modra <amodra@gmail.com>2014-06-03 10:55:29 +0930
commit397998fc32a34d3c8993ef46da45c3957a4dd402 (patch)
tree2dba3305c8567097b13505879d970299d2b9ad08 /gdb/ppc64-tdep.c
parent61f5c66f62502f33e1f2441a043bd29bb3ad6ea5 (diff)
downloadgdb-397998fc32a34d3c8993ef46da45c3957a4dd402.zip
gdb-397998fc32a34d3c8993ef46da45c3957a4dd402.tar.gz
gdb-397998fc32a34d3c8993ef46da45c3957a4dd402.tar.bz2
Support fusion for ELFv2 stubs
Power8 fuses addis,addi and addis,ld sequences when the target of the addis is the same as the addi/ld. Thus addis r12,r2,xxx@ha addi r12,r12,xxx@l / ld r12,xxx@l(r12) is faster than addis r11,r2,xxx@ha addi r12,r11,xxx@l / ld r12,xxx@l(r11) So use the form that allows fusion in plt call and branch stubs. bfd/ * elf64-ppc.c (ADDIS_R12_R2): Define. (build_plt_stub): Support fusion on ELFv2 stub. (ppc_build_one_stub): Likewise for plt branch stubs. gold/ * powerpc.cc (addis_12_2): Define. (Stub_table::do_write): Support fusion on ELFv2 stubs. ld/testsuite/ * ld-powerpc/elfv2exe.d: Update for changed plt call stubs. gdb/ * ppc64-tdep.c (ppc64_standard_linkage8): New. (ppc64_skip_trampoline_code): Recognise ELFv2 stub supporting fusion.
Diffstat (limited to 'gdb/ppc64-tdep.c')
-rw-r--r--gdb/ppc64-tdep.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/gdb/ppc64-tdep.c b/gdb/ppc64-tdep.c
index cbbbedc..8acd754 100644
--- a/gdb/ppc64-tdep.c
+++ b/gdb/ppc64-tdep.c
@@ -303,6 +303,29 @@ static struct ppc_insn_pattern ppc64_standard_linkage7[] =
{ 0, 0, 0 }
};
+/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2,
+ supporting fusion. */
+
+static struct ppc_insn_pattern ppc64_standard_linkage8[] =
+ {
+ /* std r2, 24(r1) <optional> */
+ { -1, insn_ds (62, 2, 1, 24, 0), 1 },
+
+ /* addis r12, r2, <any> */
+ { insn_d (-1, -1, -1, 0), insn_d (15, 12, 2, 0), 0 },
+
+ /* ld r12, <any>(r12) */
+ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 12, 0, 0), 0 },
+
+ /* mtctr r12 */
+ { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
+
+ /* bctr */
+ { -1, 0x4e800420, 0 },
+
+ { 0, 0, 0 }
+ };
+
/* When the dynamic linker is doing lazy symbol resolution, the first
call to a function in another object will go like this:
@@ -437,10 +460,14 @@ ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
ARRAY_SIZE (ppc64_standard_linkage4))),
MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage5),
ARRAY_SIZE (ppc64_standard_linkage6)),
- ARRAY_SIZE (ppc64_standard_linkage7))) - 1];
+ MAX (ARRAY_SIZE (ppc64_standard_linkage7),
+ ARRAY_SIZE (ppc64_standard_linkage8))))
+ - 1];
CORE_ADDR target;
- if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
+ if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
+ pc = ppc64_standard_linkage4_target (frame, pc, insns);
+ else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
pc = ppc64_standard_linkage3_target (frame, pc, insns);
else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6, insns))
pc = ppc64_standard_linkage4_target (frame, pc, insns);