[1/3,v2] Fast tracepoint for powerpc64le

Message ID 54EDE81E.4020109@gmail.com
State New, archived
Headers

Commit Message

Wei-cheng, Wang Feb. 25, 2015, 3:19 p.m. UTC
  Hi Ulrich,

I just found my mail client the it to the wrong address.
Here are some detailed explanation in my previous mail,
in cases you've not read yet.
https://sourceware.org/ml/gdb-patches/2015-02/msg00604.html
https://sourceware.org/ml/gdb-patches/2015-02/msg00605.html

In this path,
1. Changes for "unavailable-stack frames" are removed.
    I will send a separate patch for this.
2. Add testcases for bytecode compilation in ftrace.exp
    It is used to testing various emit_OP functions.
3. Some minor bug fixes.

Thanks,
Wei-cheng

--

gdb/ChangeLog

2015-02-25  Wei-cheng Wang  <cole945@gmail.com>

	* rs6000-tdep.c (ppc_fast_tracepoint_valid_at,
	ppc_relocate_instruction, ppc_gen_return_address): New functions.
	(rs6000_gdbarch_init): Hook ppc_fast_tracepoint_valid_at,
	ppc_relocate_instruction, and ppc_gen_return_address.

gdb/gdbserver/ChangeLog

2015-02-25  Wei-cheng Wang  <cole945@gmail.com>

	* Makefile.in (linux-ppc-ipa.o, powerpc-64l-ipa.o,
	powerpc-32l-ipa.o): New rules.
	* configure.srv (powerpc*-*-linux*): Add powerpc-64l-ipa.o,
	powerpc-32l-ipa.o, and linux-ppc-ipa.o in ipa_obj
	* linux-ppc-ipa.c: New file.
	* linux-ppc-low.c (ppc_supports_z_point_type, ppc_insert_point,
	ppc_remove_point, put_i32, get_i32, gen_ds_form, gen_d_form,
	gen_xfx_form, gen_x_form, gen_md_form, gen_i_form, gen_b_form,
	gen_limm, gen_atomic_xchg, gen_call, ppc_supports_tracepoints,
	ppc_install_fast_tracepoint_jump_pad,
	ppc_get_min_fast_tracepoint_insn_len, emit_insns, ppc64_emit_prologue,
	ppc64_emit_epilogue, ppc64_emit_add, ppc64_emit_sub, ppc64_emit_mul,
	ppc64_emit_lsh, ppc64_emit_rsh_signed, ppc64_emit_rsh_unsigned,
	ppc64_emit_ext, ppc64_emit_zero_ext, ppc64_emit_log_not,
	ppc64_emit_bit_and, ppc64_emit_bit_or, ppc64_emit_bit_xor,
	ppc64_emit_bit_not, ppc64_emit_equal, ppc64_emit_less_signed,
	ppc64_emit_less_unsigned, ppc64_emit_ref, ppc64_emit_const,
	ppc64_emit_reg, ppc64_emit_pop, ppc64_emit_stack_flush,
	ppc64_emit_swap, ppc64_emit_stack_adjust, ppc64_emit_call,
	ppc64_emit_int_call_1, ppc64_emit_void_call_2, ppc64_emit_if_goto,
	ppc64_emit_goto, ppc64_emit_eq_goto, ppc64_emit_ne_goto,
	ppc64_emit_lt_goto, ppc64_emit_le_goto, ppc64_emit_gt_goto,
	ppc64_emit_ge_goto, ppc_write_goto_address, ppc_emit_ops,
	ppc_supports_range_stepping, ppc_fast_tracepoint_valid_at,
	ppc_relocate_instruction): New functions.
	(ppc64_emit_ops_vector): New struct for bytecode compilation.
	(the_low_target): Add target ops - ppc_supports_z_point_type,
	ppc_insert_point, ppc_remove_point, ppc_supports_tracepoints,
	ppc_install_fast_tracepoint_jump_pad, ppc_emit_ops,
	ppc_get_min_fast_tracepoint_insn_len, ppc_supports_range_stepping.

gdb/testsuite/ChangeLog

	* gdb.trace/backtrace.exp: Set registers for powerpc*-*-*.
	* gdb.trace/collection.exp: Ditto.
	* gdb.trace/entry-values.exp: Ditto.
	* gdb.trace/mi-trace-frame-collected.exp: Ditto.
	* gdb.trace/mi-trace-unavailable.exp: Ditto.
	* gdb.trace/pending.exp: Ditto.
	* gdb.trace/report.exp: Ditto.
	* gdb.trace/trace-break.exp: Ditto.
	* gdb.trace/while-dyn.exp: Ditto.
	* gdb.trace/change-loc.h: set_point for powerpc.
	* gdb.trace/ftrace.c: Ditto
	* gdb.trace/pendshr1.c: Ditto.
	* gdb.trace/pendshr2.c: Ditto.
	* gdb.trace/range-stepping.c: Ditto.
	* gdb.trace/trace-break.c: Ditto.
	* gdb.trace/trace-mt.c: Ditto.
	* gdb.trace/ftrace.exp: Enable testing for powerpc*-*-*.
	(test_ftrace_condition) New function for testing bytecode compilation.
---
  gdb/gdbserver/Makefile.in                          |    9 +
  gdb/gdbserver/configure.srv                        |    1 +
  gdb/gdbserver/linux-ppc-ipa.c                      |  120 ++
  gdb/gdbserver/linux-ppc-low.c                      | 1268 +++++++++++++++++++-
  gdb/rs6000-tdep.c                                  |  164 +++
  gdb/testsuite/gdb.trace/backtrace.exp              |    3 +
  gdb/testsuite/gdb.trace/change-loc.h               |    2 +
  gdb/testsuite/gdb.trace/collection.exp             |    4 +
  gdb/testsuite/gdb.trace/entry-values.exp           |    2 +
  gdb/testsuite/gdb.trace/ftrace.c                   |    4 +
  gdb/testsuite/gdb.trace/ftrace.exp                 |   61 +-
  .../gdb.trace/mi-trace-frame-collected.exp         |    2 +
  gdb/testsuite/gdb.trace/mi-trace-unavailable.exp   |    2 +
  gdb/testsuite/gdb.trace/pending.exp                |    2 +
  gdb/testsuite/gdb.trace/pendshr1.c                 |    2 +
  gdb/testsuite/gdb.trace/pendshr2.c                 |    2 +
  gdb/testsuite/gdb.trace/range-stepping.c           |    2 +
  gdb/testsuite/gdb.trace/report.exp                 |    4 +
  gdb/testsuite/gdb.trace/trace-break.c              |    4 +
  gdb/testsuite/gdb.trace/trace-break.exp            |    4 +
  gdb/testsuite/gdb.trace/trace-mt.c                 |    2 +
  gdb/testsuite/gdb.trace/while-dyn.exp              |    2 +
  22 files changed, 1658 insertions(+), 8 deletions(-)
  create mode 100644 gdb/gdbserver/linux-ppc-ipa.c
  

Patch

diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index e479c7c..6bdac3e 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -491,6 +491,15 @@  linux-amd64-ipa.o: linux-amd64-ipa.c
  amd64-linux-ipa.o: amd64-linux.c
  	$(IPAGENT_COMPILE) $<
  	$(POSTCOMPILE)
+linux-ppc-ipa.o: linux-ppc-ipa.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+powerpc-64l-ipa.o: powerpc-64l.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+powerpc-32l-ipa.o: powerpc-32l.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
  tdesc-ipa.o: tdesc.c
  	$(IPAGENT_COMPILE) $<
  	$(POSTCOMPILE)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 127786e..e13daf1 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -245,6 +245,7 @@  case "${target}" in
  			srv_linux_usrregs=yes
  			srv_linux_regsets=yes
  			srv_linux_thread_db=yes
+			ipa_obj="powerpc-64l-ipa.o powerpc-32l-ipa.o linux-ppc-ipa.o"
  			;;
    powerpc-*-lynxos*)	srv_regobj="powerpc-32.o"
  			srv_tgtobj="lynx-low.o lynx-ppc-low.o"
diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c
new file mode 100644
index 0000000..34b26d0
--- /dev/null
+++ b/gdb/gdbserver/linux-ppc-ipa.c
@@ -0,0 +1,120 @@ 
+/* GNU/Linux/PowerPC specific low level interface, for the in-process
+   agent library for GDB.
+
+   Copyright (C) 2010-2015 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "server.h"
+#include "tracepoint.h"
+
+#if defined __PPC64__
+void init_registers_powerpc_64l (void);
+extern const struct target_desc *tdesc_powerpc_64l;
+#define REGSZ		8
+#else
+void init_registers_powerpc_32l (void);
+extern const struct target_desc *tdesc_powerpc_32l;
+#define REGSZ		4
+#endif
+
+/* These macros define the position of registers in the buffer collected
+   by the fast tracepoint jump pad.  */
+#define FT_CR_PC	0
+#define FT_CR_R0	1
+#define FT_CR_CR	33
+#define FT_CR_XER	34
+#define FT_CR_LR	35
+#define FT_CR_CTR	36
+#define FT_CR_GPR(n)	(FT_CR_R0 + (n))
+
+static const int ppc_ft_collect_regmap[] = {
+  /* GPRs */
+  FT_CR_GPR (0), FT_CR_GPR (1), FT_CR_GPR (2),
+  FT_CR_GPR (3), FT_CR_GPR (4), FT_CR_GPR (5),
+  FT_CR_GPR (6), FT_CR_GPR (7), FT_CR_GPR (8),
+  FT_CR_GPR (9), FT_CR_GPR (10), FT_CR_GPR (11),
+  FT_CR_GPR (12), FT_CR_GPR (13), FT_CR_GPR (14),
+  FT_CR_GPR (15), FT_CR_GPR (16), FT_CR_GPR (17),
+  FT_CR_GPR (18), FT_CR_GPR (19), FT_CR_GPR (20),
+  FT_CR_GPR (21), FT_CR_GPR (22), FT_CR_GPR (23),
+  FT_CR_GPR (24), FT_CR_GPR (25), FT_CR_GPR (26),
+  FT_CR_GPR (27), FT_CR_GPR (28), FT_CR_GPR (29),
+  FT_CR_GPR (30), FT_CR_GPR (31),
+  /* FPRs - not collected.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  FT_CR_PC, /* PC */
+  -1, /* MSR */
+  FT_CR_CR, /* CR */
+  FT_CR_LR, /* LR */
+  FT_CR_CTR, /* CTR */
+  FT_CR_XER, /* XER */
+  -1, /* FPSCR */
+};
+
+#define PPC_NUM_FT_COLLECT_GREGS \
+  (sizeof (ppc_ft_collect_regmap) / sizeof(ppc_ft_collect_regmap[0]))
+
+/* Supply registers collected by the fast tracepoint jump pad.
+   BUF is the second argument we pass to gdb_collect in jump pad.  */
+
+void
+supply_fast_tracepoint_registers (struct regcache *regcache,
+				  const unsigned char *buf)
+{
+  int i;
+
+  for (i = 0; i < PPC_NUM_FT_COLLECT_GREGS; i++)
+    {
+      if (ppc_ft_collect_regmap[i] == -1)
+	continue;
+      supply_register (regcache, i,
+		       ((char *) buf)
+			+ ppc_ft_collect_regmap[i] * REGSZ);
+    }
+}
+
+/* Return the value of register REGNUM.  RAW_REGS is collected buffer
+   by jump pad.  This function is called by emit_reg.  */
+
+ULONGEST __attribute__ ((visibility("default"), used))
+gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
+{
+  if (regnum >= PPC_NUM_FT_COLLECT_GREGS)
+    return 0;
+  if (ppc_ft_collect_regmap[regnum] == -1)
+    return 0;
+
+  return *(ULONGEST *) (raw_regs
+			+ ppc_ft_collect_regmap[regnum] * REGSZ);
+}
+
+/* Initialize ipa_tdesc and others.  */
+
+void
+initialize_low_tracepoint (void)
+{
+#if defined __PPC64__
+  init_registers_powerpc_64l ();
+  ipa_tdesc = tdesc_powerpc_64l;
+#else
+  init_registers_powerpc_32l ();
+  ipa_tdesc = tdesc_powerpc_32l;
+#endif
+}
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 188fac0..0b47543 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -24,6 +24,8 @@ 
  #include <asm/ptrace.h>

  #include "nat/ppc-linux.h"
+#include "ax.h"
+#include "tracepoint.h"

  static unsigned long ppc_hwcap;

@@ -512,6 +514,1243 @@  ppc_breakpoint_at (CORE_ADDR where)
    return 0;
  }

+/* Implement supports_z_point_type target-ops.
+   Returns true if type Z_TYPE breakpoint is supported.
+
+   Handling software breakpoint at server side, so tracepoints
+   and breakpoints can be inserted at the same location.  */
+
+static int
+ppc_supports_z_point_type (char z_type)
+{
+  switch (z_type)
+    {
+    case Z_PACKET_SW_BP:
+      return 1;
+    case Z_PACKET_HW_BP:
+    case Z_PACKET_WRITE_WP:
+    case Z_PACKET_ACCESS_WP:
+    default:
+      return 0;
+    }
+}
+
+/* Implement insert_point target-ops.
+   Returns 0 on success, -1 on failure and 1 on unsupported.  */
+
+static int
+ppc_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+		  int size, struct raw_breakpoint *bp)
+{
+  switch (type)
+    {
+    case raw_bkpt_type_sw:
+      return insert_memory_breakpoint (bp);
+
+    case raw_bkpt_type_hw:
+    case raw_bkpt_type_write_wp:
+    case raw_bkpt_type_access_wp:
+    default:
+      /* Unsupported.  */
+      return 1;
+    }
+}
+
+/* Implement remove_point target-ops.
+   Returns 0 on success, -1 on failure and 1 on unsupported.  */
+
+static int
+ppc_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+		  int size, struct raw_breakpoint *bp)
+{
+  switch (type)
+    {
+    case raw_bkpt_type_sw:
+      return remove_memory_breakpoint (bp);
+
+    case raw_bkpt_type_hw:
+    case raw_bkpt_type_write_wp:
+    case raw_bkpt_type_access_wp:
+    default:
+      /* Unsupported.  */
+      return 1;
+    }
+}
+
+/* Put a 32-bit INSN instruction in BUF in target endian.  */
+
+static int
+put_i32 (unsigned char *buf, uint32_t insn)
+{
+  if (__BYTE_ORDER == __LITTLE_ENDIAN)
+    {
+      buf[3] = (insn >> 24) & 0xff;
+      buf[2] = (insn >> 16) & 0xff;
+      buf[1] = (insn >> 8) & 0xff;
+      buf[0] = insn & 0xff;
+    }
+  else
+    {
+      buf[0] = (insn >> 24) & 0xff;
+      buf[1] = (insn >> 16) & 0xff;
+      buf[2] = (insn >> 8) & 0xff;
+      buf[3] = insn & 0xff;
+    }
+
+  return 4;
+}
+
+/* return a 32-bit value in target endian in BUF.  */
+
+__attribute__((unused)) /* Maybe unused due to conditional compilation.  */
+static uint32_t
+get_i32 (unsigned char *buf)
+{
+  uint32_t r;
+
+  if (__BYTE_ORDER == __LITTLE_ENDIAN)
+    r = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+  else
+    r = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+
+  return r;
+}
+
+/* Generate a ds-form instruction in BUF and return the number of bytes written
+
+   0      6     11   16          30 32
+   | OPCD | RST | RA |     DS    |XO|  */
+
+__attribute__((unused)) /* Maybe unused due to conditional compilation.  */
+static int
+gen_ds_form (unsigned char *buf, int opcd, int rst, int ra, int ds, int xo)
+{
+  uint32_t insn = opcd << 26;
+
+  insn |= (rst << 21) | (ra << 16) | (ds & 0xfffc) | (xo & 0x3);
+  return put_i32 (buf, insn);
+}
+
+/* Followings are frequently used ds-form instructions.  */
+
+#define GEN_STD(buf, rs, ra, offset)	gen_ds_form (buf, 62, rs, ra, offset, 0)
+#define GEN_STDU(buf, rs, ra, offset)	gen_ds_form (buf, 62, rs, ra, offset, 1)
+#define GEN_LD(buf, rt, ra, offset)	gen_ds_form (buf, 58, rt, ra, offset, 0)
+#define GEN_LDU(buf, rt, ra, offset)	gen_ds_form (buf, 58, rt, ra, offset, 1)
+
+/* Generate a d-form instruction in BUF.
+
+   0      6     11   16             32
+   | OPCD | RST | RA |       D      |  */
+
+static int
+gen_d_form (unsigned char *buf, int opcd, int rst, int ra, int si)
+{
+  uint32_t insn = opcd << 26;
+
+  insn |= (rst << 21) | (ra << 16) | (si & 0xffff);
+  return put_i32 (buf, insn);
+}
+
+/* Followings are frequently used d-form instructions.  */
+
+#define GEN_ADDI(buf, rt, ra, si)	gen_d_form (buf, 14, rt, ra, si)
+#define GEN_ADDIS(buf, rt, ra, si)	gen_d_form (buf, 15, rt, ra, si)
+#define GEN_LI(buf, rt, si)		GEN_ADDI (buf, rt, 0, si)
+#define GEN_LIS(buf, rt, si)		GEN_ADDIS (buf, rt, 0, si)
+#define GEN_ORI(buf, rt, ra, si)	gen_d_form (buf, 24, rt, ra, si)
+#define GEN_ORIS(buf, rt, ra, si)	gen_d_form (buf, 25, rt, ra, si)
+#define GEN_LWZ(buf, rt, ra, si)	gen_d_form (buf, 32, rt, ra, si)
+#define GEN_STW(buf, rt, ra, si)	gen_d_form (buf, 36, rt, ra, si)
+
+/* Generate a xfx-form instruction in BUF and return the number of bytes
+   written.
+
+   0      6     11         21        31 32
+   | OPCD | RST |    RI    |    XO   |/|  */
+
+static int
+gen_xfx_form (unsigned char *buf, int opcd, int rst, int ri, int xo)
+{
+  uint32_t insn = opcd << 26;
+  unsigned int n = ((ri & 0x1f) << 5) | ((ri >> 5) & 0x1f);
+
+  insn |= (rst << 21) | (n << 11) | (xo << 1);
+  return put_i32 (buf, insn);
+}
+
+/* Followings are frequently used xfx-form instructions.  */
+
+#define GEN_MFSPR(buf, rt, spr)		gen_xfx_form (buf, 31, rt, spr, 339)
+#define GEN_MTSPR(buf, rt, spr)		gen_xfx_form (buf, 31, rt, spr, 467)
+
+/* Generate a x-form instruction in BUF and return the number of bytes written.
+
+   0      6     11   16   21       31 32
+   | OPCD | RST | RA | RB |   XO   |RC|  */
+
+static int
+gen_x_form (unsigned char *buf, int opcd, int rst, int ra, int rb,
+	    int xo, int rc)
+{
+  uint32_t insn = opcd << 26;
+
+  insn |= (rst << 21) | (ra << 16) | (rb << 11) | (xo << 1) | rc;
+  return put_i32 (buf, insn);
+}
+
+/* Followings are frequently used x-form instructions.  */
+
+#define GEN_OR(buf, ra, rs, rb)		gen_x_form (buf, 31, rs, ra, rb, 444, 0)
+#define GEN_MR(buf, ra, rs)		GEN_OR (buf, ra, rs, rs)
+#define GEN_LWARX(buf, rt, ra, rb)	gen_x_form (buf, 31, rt, ra, rb, 20, 0)
+#define GEN_STWCX(buf, rs, ra, rb)	gen_x_form (buf, 31, rs, ra, rb, 150, 1)
+/* Assume bf = cr7.  */
+#define GEN_CMPW(buf, ra, rb)    gen_x_form (buf, 31, 28, ra, rb, 0, 0)
+
+/* Generate a md-form instruction in BUF and return the number of bytes written.
+
+   0      6    11   16   21   27   30 31 32
+   | OPCD | RS | RA | sh | mb | XO |sh|Rc|  */
+
+static int
+gen_md_form (unsigned char *buf, int opcd, int rs, int ra, int sh, int mb,
+	     int xo, int rc)
+{
+  uint32_t insn = opcd << 26;
+  unsigned int n = ((mb & 0x1f) << 1) | ((mb >> 5) & 0x1);
+  unsigned int sh0_4 = sh & 0x1f;
+  unsigned int sh5 = (sh >> 5) & 1;
+
+  insn |= (rs << 21) | (ra << 16) | (sh0_4 << 11) | (n << 5) | (sh5 << 1)
+	  | (xo << 2);
+  return put_i32 (buf, insn);
+}
+
+/* The following are frequently used md-form instructions.  */
+
+#define GEN_RLDICL(buf, ra, rs ,sh, mb) \
+				gen_md_form (buf, 30, rs, ra, sh, mb, 0, 0)
+#define GEN_RLDICR(buf, ra, rs ,sh, mb) \
+				gen_md_form (buf, 30, rs, ra, sh, mb, 1, 0)
+
+/* Generate a i-form instruction in BUF and return the number of bytes written.
+
+   0      6                          30 31 32
+   | OPCD |            LI            |AA|LK|  */
+
+static int
+gen_i_form (unsigned char *buf, int opcd, int li, int aa, int lk)
+{
+  uint32_t insn = opcd << 26;
+
+  insn |= (li & 0x3fffffc) | (aa & 1) | (lk & 1);
+  return put_i32 (buf, insn);
+}
+
+/* The following are frequently used i-form instructions.  */
+
+#define GEN_B(buf, li)		gen_i_form (buf, 18, li, 0, 0)
+#define GEN_BL(buf, li)		gen_i_form (buf, 18, li, 0, 1)
+
+/* Generate a b-form instruction in BUF and return the number of bytes written.
+
+   0      6    11   16               30 31 32
+   | OPCD | BO | BI |      BD        |AA|LK|  */
+
+static int
+gen_b_form (unsigned char *buf, int opcd, int bo, int bi, int bd,
+	    int aa, int lk)
+{
+  uint32_t insn = opcd << 26;
+
+  insn |= (bo << 21) | (bi << 16) | (bd & 0xfffc) | (aa & 1) | (lk & 1);
+  return put_i32 (buf, insn);
+}
+
+/* The following are frequently used b-form instructions.  */
+/* Assume bi = cr7.  */
+#define GEN_BNE(buf, bd)  gen_b_form (buf, 16, 0x4, (7 << 2) | 2, bd, 0 ,0)
+
+/* GEN_LOAD and GEN_STORE generate 64- or 32-bit load/store for ppc64 or ppc32
+   respectively.  They are primary used for save/restore GPRs in jump-pad,
+   not used for bytecode compiling.  */
+
+#if defined __PPC64__
+#define GEN_LOAD(buf, rt, ra, si)	GEN_LD (buf, rt, ra, si)
+#define GEN_STORE(buf, rt, ra, si)	GEN_STD (buf, rt, ra, si)
+#else
+#define GEN_LOAD(buf, rt, ra, si)	GEN_LWZ (buf, rt, ra, si)
+#define GEN_STORE(buf, rt, ra, si)	GEN_STW (buf, rt, ra, si)
+#endif
+
+/* Generate a sequence of instructions to load IMM in the register REG.
+   Write the instructions in BUF and return the number of bytes written.  */
+
+static int
+gen_limm (unsigned char *buf, int reg, uint64_t imm)
+{
+  unsigned char *p = buf;
+
+  if ((imm >> 8) == 0)
+    {
+      /* li	reg, imm[7:0] */
+      p += GEN_LI (p, reg, imm);
+    }
+  else if ((imm >> 16) == 0)
+    {
+      /* li	reg, 0
+	 ori	reg, reg, imm[15:0] */
+      p += GEN_LI (p, reg, 0);
+      p += GEN_ORI (p, reg, reg, imm);
+    }
+  else if ((imm >> 32) == 0)
+    {
+      /* lis	reg, imm[31:16]
+	 ori	reg, reg, imm[15:0]
+	 rldicl	reg, reg, 0, 32 */
+      p += GEN_LIS (p, reg, (imm >> 16) & 0xffff);
+      p += GEN_ORI (p, reg, reg, imm & 0xffff);
+      p += GEN_RLDICL (p, reg, reg, 0, 32);
+    }
+  else
+    {
+      /* lis    reg, <imm[63:48]>
+	 ori    reg, reg, <imm[48:32]>
+	 rldicr reg, reg, 32, 31
+	 oris   reg, reg, <imm[31:16]>
+	 ori    reg, reg, <imm[15:0]> */
+      p += GEN_LIS (p, reg, ((imm >> 48) & 0xffff));
+      p += GEN_ORI (p, reg, reg, ((imm >> 32) & 0xffff));
+      p += GEN_RLDICR (p, reg, reg, 32, 31);
+      p += GEN_ORIS (p, reg, reg, ((imm >> 16) & 0xffff));
+      p += GEN_ORI (p, reg, reg, (imm & 0xffff));
+    }
+
+  return p - buf;
+}
+
+/* Generate a sequence for atomically exchange at location LOCK.
+   This code sequence clobbers r6, r7, r8, r9.  */
+
+static int
+gen_atomic_xchg (unsigned char *buf, CORE_ADDR lock, int old_value, int new_value)
+{
+  const int r_lock = 6;
+  const int r_old = 7;
+  const int r_new = 8;
+  const int r_tmp = 9;
+  unsigned char *p = buf;
+
+  /*
+  1: lwsync
+  2: lwarx   TMP, 0, LOCK
+     cmpwi   TMP, OLD
+     bne     1b
+     stwcx.  NEW, 0, LOCK
+     bne     2b */
+
+  p += gen_limm (p, r_lock, lock);
+  p += gen_limm (p, r_new, new_value);
+  p += gen_limm (p, r_old, old_value);
+
+  p += put_i32 (p, 0x7c2004ac);	/* lwsync */
+  p += GEN_LWARX (p, r_tmp, 0, r_lock);
+  p += GEN_CMPW (p, r_tmp, r_old);
+  p += GEN_BNE (p, -12);
+  p += GEN_STWCX (p, r_new, 0, r_lock);
+  p += GEN_BNE (p, -16);
+
+  return p - buf;
+}
+
+/* Generate a sequence of instructions for calling a function
+   at address of FN.  Return the number of bytes are written in BUF.
+
+   FIXME: For ppc64be, FN should be the address to the function
+   descriptor, so we should load 8(FN) to R2, 16(FN) to R11
+   and then call the function-entry at 0(FN).  However, current GDB
+   implicitly convert the address from function descriptor to the actual
+   function address. See qSymbol handling in remote.c.  Although it
+   seems we can successfully call however, things go wrong when callee
+   trying to access global variable.  */
+
+static int
+gen_call (unsigned char *buf, CORE_ADDR fn)
+{
+  unsigned char *p = buf;
+
+  /* Must be called by r12 for caller to calculate TOC address. */
+  p += gen_limm (p, 12, fn);
+  p += GEN_MTSPR (p, 12, 9);		/* mtctr  r12 */
+  p += put_i32 (p, 0x4e800421);		/* bctrl */
+
+  return p - buf;
+}
+
+/* Implement supports_tracepoints hook of target_ops.
+   Always return true.  */
+
+static int
+ppc_supports_tracepoints (void)
+{
+#if defined (__PPC64__) && _CALL_ELF == 2
+  return 1;
+#else
+  return 0;
+#endif
+}
+
+/* Implement install_fast_tracepoint_jump_pad of target_ops.
+   See target.h for details.  */
+
+static int
+ppc_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
+				      CORE_ADDR collector,
+				      CORE_ADDR lockaddr,
+				      ULONGEST orig_size,
+				      CORE_ADDR *jump_entry,
+				      CORE_ADDR *trampoline,
+				      ULONGEST *trampoline_size,
+				      unsigned char *jjump_pad_insn,
+				      ULONGEST *jjump_pad_insn_size,
+				      CORE_ADDR *adjusted_insn_addr,
+				      CORE_ADDR *adjusted_insn_addr_end,
+				      char *err)
+{
+  unsigned char buf[1024];
+  unsigned char *p = buf;
+  int j, offset;
+  CORE_ADDR buildaddr = *jump_entry;
+  const CORE_ADDR entryaddr = *jump_entry;
+#if __PPC64__
+  const int rsz = 8;
+#else
+  const int rsz = 4;
+#endif
+  const int frame_size = (((37 * rsz) + 112) + 0xf) & ~0xf;
+
+  /* Stack frame layout for this jump pad,
+
+     High	CTR   -8(sp)
+		LR   -16(sp)
+		XER
+		CR
+		R31
+		R29
+		...
+		R1
+		R0
+     Low	PC/<tpaddr>
+
+     The code flow of this jump pad,
+
+     1. Save GPR and SPR
+     3. Adjust SP
+     4. Prepare argument
+     5. Call gdb_collector
+     6. Restore SP
+     7. Restore GPR and SPR
+     8. Build a jump for back to the program
+     9. Copy/relocate original instruction
+    10. Build a jump for replacing orignal instruction.  */
+
+  for (j = 0; j < 32; j++)
+    p += GEN_STORE (p, j, 1, (-rsz * 36 + j * rsz));
+
+  /* Save PC<tpaddr>  */
+  p += gen_limm (p, 3, tpaddr);
+  p += GEN_STORE (p, 3, 1, (-rsz * 37));
+
+  /* Save CR, XER, LR, and CTR.  */
+  p += put_i32 (p, 0x7c600026);			/* mfcr   r3 */
+  p += GEN_MFSPR (p, 4, 1);			/* mfxer  r4 */
+  p += GEN_MFSPR (p, 5, 8);			/* mflr   r5 */
+  p += GEN_MFSPR (p, 6, 9);			/* mfctr  r6 */
+  p += GEN_STORE (p, 3, 1, -4 * rsz);		/* std    r3, -32(r1) */
+  p += GEN_STORE (p, 4, 1, -3 * rsz);		/* std    r4, -24(r1) */
+  p += GEN_STORE (p, 5, 1, -2 * rsz);		/* std    r5, -16(r1) */
+  p += GEN_STORE (p, 6, 1, -1 * rsz);		/* std    r6, -8(r1) */
+
+  /* Adjust stack pointer.  */
+  p += GEN_ADDI (p, 1, 1, -frame_size);		/* subi   r1,r1,FRAME_SIZE */
+
+  /* Setup arguments to collector.  */
+
+  /* Set r4 to collected registers.  */
+  p += GEN_ADDI (p, 4, 1, frame_size - rsz * 37);
+  /* Set r3 to TPOINT.  */
+  p += gen_limm (p, 3, tpoint);
+
+  p += gen_atomic_xchg (p, lockaddr, 0, 1);
+  /* Call to collector.  */
+  p += gen_call (p, collector);
+  p += gen_atomic_xchg (p, lockaddr, 1, 0);
+
+  /* Restore stack and registers.  */
+  p += GEN_ADDI (p, 1, 1, frame_size);	/* addi	r1,r1,FRAME_SIZE */
+  p += GEN_LOAD (p, 3, 1, -4 * rsz);	/* ld	r3, -32(r1) */
+  p += GEN_LOAD (p, 4, 1, -3 * rsz);	/* ld	r4, -24(r1) */
+  p += GEN_LOAD (p, 5, 1, -2 * rsz);	/* ld	r5, -16(r1) */
+  p += GEN_LOAD (p, 6, 1, -1 * rsz);	/* ld	r6, -8(r1) */
+  p += put_i32 (p, 0x7c6ff120);		/* mtcr	r3 */
+  p += GEN_MTSPR (p, 4, 1);		/* mtxer  r4 */
+  p += GEN_MTSPR (p, 5, 8);		/* mtlr   r5 */
+  p += GEN_MTSPR (p, 6, 9);		/* mtctr  r6 */
+  for (j = 0; j < 32; j++)
+    p += GEN_LOAD (p, j, 1, (-rsz * 36 + j * rsz));
+
+  /* Flush instructions to inferior memory.  */
+  write_inferior_memory (buildaddr, buf, (p - buf));
+
+  /* Now, insert the original instruction to execute in the jump pad.  */
+  *adjusted_insn_addr = buildaddr + (p - buf);
+  *adjusted_insn_addr_end = *adjusted_insn_addr;
+  relocate_instruction (adjusted_insn_addr_end, tpaddr);
+
+  /* Verify the relocation size.  If should be 4 for normal copy, or 8
+     for some conditional branch.  */
+  if ((*adjusted_insn_addr_end - *adjusted_insn_addr == 0)
+      || (*adjusted_insn_addr_end - *adjusted_insn_addr > 8))
+    {
+      sprintf (err, "E.Unexpected instruction length = %d"
+		    "when relocate instruction.",
+		    (int) (*adjusted_insn_addr_end - *adjusted_insn_addr));
+      return 1;
+    }
+
+  buildaddr = *adjusted_insn_addr_end;
+  p = buf;
+  /* Finally, write a jump back to the program.  */
+  offset = (tpaddr + 4) - buildaddr;
+  if (offset >= (1 << 26) || offset < -(1 << 26))
+    {
+      sprintf (err, "E.Jump back from jump pad too far from tracepoint "
+		    "(offset 0x%x > 26-bit).", offset);
+      return 1;
+    }
+  /* b <tpaddr+4> */
+  p += GEN_B (p, offset);
+  write_inferior_memory (buildaddr, buf, (p - buf));
+  *jump_entry = buildaddr + (p - buf);
+
+  /* The jump pad is now built.  Wire in a jump to our jump pad.  This
+     is always done last (by our caller actually), so that we can
+     install fast tracepoints with threads running.  This relies on
+     the agent's atomic write support.  */
+  offset = entryaddr - tpaddr;
+  if (offset >= (1 << 25) || offset < -(1 << 25))
+    {
+      sprintf (err, "E.Jump back from jump pad too far from tracepoint "
+		    "(offset 0x%x > 26-bit).", offset);
+      return 1;
+    }
+  /* b <jentry> */
+  GEN_B (jjump_pad_insn, offset);
+  *jjump_pad_insn_size = 4;
+
+  return 0;
+}
+
+/* Returns the minimum instruction length for installing a tracepoint.  */
+
+static int
+ppc_get_min_fast_tracepoint_insn_len ()
+{
+  return 4;
+}
+
+#if __PPC64__
+
+static void
+emit_insns (unsigned char *buf, int n)
+{
+  write_inferior_memory (current_insn_ptr, buf, n);
+  current_insn_ptr += n;
+}
+
+#define __EMIT_ASM(NAME, INSNS)					\
+  do								\
+    {								\
+      extern unsigned char start_bcax_ ## NAME [];		\
+      extern unsigned char end_bcax_ ## NAME [];		\
+      emit_insns (start_bcax_ ## NAME,				\
+		  end_bcax_ ## NAME - start_bcax_ ## NAME);	\
+      __asm__ (".section .text.__ppcbcax\n\t"			\
+	       "start_bcax_" #NAME ":\n\t"			\
+	       INSNS "\n\t"					\
+	       "end_bcax_" #NAME ":\n\t"			\
+	       ".previous\n\t");				\
+    } while (0)
+
+#define _EMIT_ASM(NAME, INSNS)		__EMIT_ASM (NAME, INSNS)
+#define EMIT_ASM(INSNS)			_EMIT_ASM (__LINE__, INSNS)
+
+/*
+
+  Bytecode execution stack frame
+
+	|  Parameter save area    (SP + 48) [8 doublewords]
+	|  TOC save area          (SP + 40)
+	|  link editor doubleword (SP + 32)
+	|  compiler doubleword    (SP + 24)  save TOP here during call
+	|  LR save area           (SP + 16)
+	|  CR save area           (SP + 8)
+ SP' -> +- Back chain             (SP + 0)
+	|  Save r31
+	|  Save r30
+	|  Save r4    for *value
+	|  Save r3    for CTX
+ r30 -> +- Bytecode execution stack
+	|
+	|  64-byte (8 doublewords) at initial.  Expand stack as needed.
+	|
+ r31 -> +-
+
+  initial frame size
+  = (48 + 8 * 8) + (4 * 8) + 64
+  = 112 + 96
+  = 208
+
+   r31 is the frame-base for restoring stack-pointer.
+   r30 is the stack-pointer for bytecode machine.
+       It should point to next-empty, so we can use LDU for pop.
+   r3  is used for cache of TOP value.
+       It is the first argument, pointer to CTX.
+   r4  is the second argument, pointer to the result.
+   SP+24 is used for saving TOP during call.
+
+ Note:
+ * To restore stack at epilogue
+   => sp = r31 + 208
+ * To check stack is big enough for bytecode execution.
+   => r30 - 8 > SP + 112
+ * To return execution result.
+   => 0(r4) = TOP
+
+ */
+
+enum { bc_framesz = 208 };
+
+/* Emit prologue in inferior memory.  See above comments.  */
+
+static void
+ppc64_emit_prologue (void)
+{
+  EMIT_ASM ("mflr  0		\n"
+	    "std   0, 16(1)	\n"
+	    "std   31, -8(1)	\n"
+	    "std   30, -16(1)	\n"
+	    "std   4, -24(1)	\n"
+	    "std   3, -32(1)	\n"
+	    "addi  30, 1, -40	\n"
+	    "li	   3, 0		\n"
+	    "stdu  1, -208(1)	\n"
+	    "mr	   31, 1	\n");
+}
+
+/* Emit epilogue in inferior memory.  See above comments.  */
+
+static void
+ppc64_emit_epilogue (void)
+{
+  EMIT_ASM (/* Restore SP.  */
+	    "addi  1, 31, 208	\n"
+	    /* *result = TOP */
+	    "ld    4, -24(1)	\n"
+	    "std   3, 0(4)	\n"
+	    /* Return 0 for no-erro.  */
+	    "li    3, 0		\n"
+	    "ld    0, 16(1)	\n"
+	    "ld    31, -8(1)	\n"
+	    "ld    30, -16(1)	\n"
+	    "mtlr  0		\n"
+	    "blr		\n");
+}
+
+/* TOP = stack[--sp] + TOP  */
+
+static void
+ppc64_emit_add (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "add  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] - TOP  */
+
+static void
+ppc64_emit_sub (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "sub  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] * TOP  */
+
+static void
+ppc64_emit_mul (void)
+{
+  EMIT_ASM ("ldu    4, 8(30)	\n"
+	    "mulld  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] << TOP  */
+
+static void
+ppc64_emit_lsh (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "sld  3, 4, 3	\n");
+}
+
+/* Top = stack[--sp] >> TOP
+   (Arithmetic shift right)  */
+
+static void
+ppc64_emit_rsh_signed (void)
+{
+  EMIT_ASM ("ldu   4, 8(30)	\n"
+	    "srad  3, 4, 3	\n");
+}
+
+/* Top = stack[--sp] >> TOP
+   (Logical shift right)  */
+
+static void
+ppc64_emit_rsh_unsigned (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "srd  3, 4, 3	\n");
+}
+
+/* Emit code for signed-extension specified by ARG.  */
+
+static void
+ppc64_emit_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM ("extsb  3, 3");
+      break;
+    case 16:
+      EMIT_ASM ("extsh  3, 3");
+      break;
+    case 32:
+      EMIT_ASM ("extsw  3, 3");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* Emit code for zero-extension specified by ARG.  */
+
+static void
+ppc64_emit_zero_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM ("rldicl 3,3,0,56");
+      break;
+    case 16:
+      EMIT_ASM ("rldicl 3,3,0,48");
+      break;
+    case 32:
+      EMIT_ASM ("rldicl 3,3,0,32");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* TOP = !TOP
+   i.e., TOP = (TOP == 0) ? 1 : 0;  */
+
+static void
+ppc64_emit_log_not (void)
+{
+  EMIT_ASM ("cntlzd  3, 3	\n"
+	    "srdi    3, 3, 6	\n");
+}
+
+/* TOP = stack[--sp] & TOP  */
+
+static void
+ppc64_emit_bit_and (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "and  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] | TOP  */
+
+static void
+ppc64_emit_bit_or (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "or   3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] ^ TOP  */
+
+static void
+ppc64_emit_bit_xor (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "xor  3, 4, 3	\n");
+}
+
+/* TOP = ~TOP
+   i.e., TOP = ~(TOP | TOP)  */
+
+static void
+ppc64_emit_bit_not (void)
+{
+  EMIT_ASM ("nor  3, 3, 3	\n");
+}
+
+/* TOP = stack[--sp] == TOP  */
+
+static void
+ppc64_emit_equal (void)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "xor     3, 3, 4	\n"
+	    "cntlzd  3, 3	\n"
+	    "srdi    3, 3, 6	\n");
+}
+
+/* TOP = stack[--sp] < TOP
+   (Signed comparison)  */
+
+static void
+ppc64_emit_less_signed (void)
+{
+  EMIT_ASM ("ldu     4, 8(30)		\n"
+	    "cmpd    7, 4, 3		\n"
+	    "mfocrf  3, 1		\n"
+	    "rlwinm  3, 3, 29, 31, 31	\n");
+}
+
+/* TOP = stack[--sp] < TOP
+   (Unsigned comparison)  */
+
+static void
+ppc64_emit_less_unsigned (void)
+{
+  EMIT_ASM ("ldu     4, 8(30)		\n"
+	    "cmpld   7, 4, 3		\n"
+	    "mfocrf  3, 1		\n"
+	    "rlwinm  3, 3, 29, 31, 31	\n");
+}
+
+/* Access the memory address in TOP in size of SIZE.
+   Zero-extend the read value.  */
+
+static void
+ppc64_emit_ref (int size)
+{
+  switch (size)
+    {
+    case 1:
+      EMIT_ASM ("lbz   3, 0(3)");
+      break;
+    case 2:
+      EMIT_ASM ("lhz   3, 0(3)");
+      break;
+    case 4:
+      EMIT_ASM ("lwz   3, 0(3)");
+      break;
+    case 8:
+      EMIT_ASM ("ld    3, 0(3)");
+      break;
+    }
+}
+
+/* TOP = NUM  */
+
+static void
+ppc64_emit_const (LONGEST num)
+{
+  unsigned char buf[5 * 4];
+  unsigned char *p = buf;
+
+  p += gen_limm (p, 3, num);
+
+  write_inferior_memory (current_insn_ptr, buf, (p - buf));
+  current_insn_ptr += (p - buf);
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* Set TOP to the value of register REG by calling get_raw_reg function
+   with two argument, collected buffer and register number.  */
+
+static void
+ppc64_emit_reg (int reg)
+{
+  unsigned char buf[10 * 4];
+  unsigned char *p = buf;
+
+  p += GEN_LD (p, 3, 31, bc_framesz - 32);
+  p += GEN_LD (p, 3, 3, 48);	/* offsetof (fast_tracepoint_ctx, regs) */
+  p += GEN_LI (p, 4, reg);	/* mr	r4, reg */
+  p += gen_call (p, get_raw_reg_func_addr ());
+
+  write_inferior_memory (current_insn_ptr, buf, (p - buf));
+  current_insn_ptr += p - buf;
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* TOP = stack[--sp] */
+
+static void
+ppc64_emit_pop (void)
+{
+  EMIT_ASM ("ldu  3, 8(30)");
+}
+
+/* stack[sp++] = TOP
+
+   Because we may use up bytecode stack, expand 8 doublewords more
+   if needed.  */
+
+static void
+ppc64_emit_stack_flush (void)
+{
+  /* Make sure bytecode stack is big enough before push.
+     Otherwise, expand 64-byte more.  */
+
+  EMIT_ASM ("  std   3, 0(30)		\n"
+	    "  addi  4, 30, -(112 + 8)	\n"
+	    "  cmpd  7, 4, 1		\n"
+	    "  bgt   1f			\n"
+	    "  ld    4, 0(1)		\n"
+	    "  addi  1, 1, -64		\n"
+	    "  std   4, 0(1)		\n"
+	    "1:addi  30, 30, -8		\n");
+}
+
+/* Swap TOP and stack[sp-1]  */
+
+static void
+ppc64_emit_swap (void)
+{
+  EMIT_ASM ("ld   4, 8(30)	\n"
+	    "std  3, 8(30)	\n"
+	    "mr   3, 4		\n");
+}
+
+/* Discard N elements in the stack.  */
+
+static void
+ppc64_emit_stack_adjust (int n)
+{
+  unsigned char buf[4];
+  unsigned char *p = buf;
+
+  p += GEN_ADDI (p, 30, 30, n << 3);	/* addi	r30, r30, (n << 3) */
+
+  write_inferior_memory (current_insn_ptr, buf, (p - buf));
+  current_insn_ptr += p - buf;
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* Call function FN.  */
+
+static void
+ppc64_emit_call (CORE_ADDR fn)
+{
+  unsigned char buf[8 * 4];
+  unsigned char *p = buf;
+
+  p += gen_call (p, fn);
+
+  write_inferior_memory (current_insn_ptr, buf, (p - buf));
+  current_insn_ptr += p - buf;
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* FN's prototype is `LONGEST(*fn)(int)'.
+   TOP = fn (arg1)
+  */
+
+static void
+ppc64_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  unsigned char buf[8 * 4];
+  unsigned char *p = buf;
+
+  /* Setup argument.  arg1 is a 16-bit value.  */
+  p += GEN_LI (p, 3, arg1);		/* li	r3, arg1 */
+  p += gen_call (p, fn);
+
+  write_inferior_memory (current_insn_ptr, buf, (p - buf));
+  current_insn_ptr += p - buf;
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* FN's prototype is `void(*fn)(int,LONGEST)'.
+   fn (arg1, TOP)
+
+   TOP should be preserved/restored before/after the call.  */
+
+static void
+ppc64_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  unsigned char buf[12 * 4];
+  unsigned char *p = buf;
+
+  /* Save TOP */
+  p += GEN_STD (p, 3, 31, bc_framesz + 24);
+
+  /* Setup argument.  arg1 is a 16-bit value.  */
+  p += GEN_MR (p, 4, 3);		/* mr	r4, r3 */
+  p += GEN_LI (p, 3, arg1);	/* li	r3, arg1 */
+  p += gen_call (p, fn);
+
+  /* Restore TOP */
+  p += GEN_LD (p, 3, 31, bc_framesz + 24);
+
+  write_inferior_memory (current_insn_ptr, buf, (p - buf));
+  current_insn_ptr += p - buf;
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* Note in the following goto ops:
+
+   When emitting goto, the target address is later relocated by
+   write_goto_address.  OFFSET_P is the offset of the branch instruction
+   in the code sequence, and SIZE_P is how to relocate the instruction,
+   recognized by ppc_write_goto_address.  In current implementation,
+   SIZE can be either 24 or 14 for branch of conditional-branch instruction.
+ */
+
+/* If TOP is true, goto somewhere.  Otherwise, just fall-through.  */
+
+static void
+ppc64_emit_if_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("mr     4, 3	\n"
+	    "ldu    3, 8(30)	\n"
+	    "cmpdi  7, 4, 0	\n"
+	    "1:bne  7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Unconditional goto.  */
+
+static void
+ppc64_emit_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("1:b	1b");
+
+  if (offset_p)
+    *offset_p = 0;
+  if (size_p)
+    *size_p = 24;
+}
+
+/* Goto if stack[--sp] == TOP  */
+
+static void
+ppc64_emit_eq_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:beq   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] != TOP  */
+
+static void
+ppc64_emit_ne_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:bne   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] < TOP  */
+
+static void
+ppc64_emit_lt_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:blt   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] <= TOP  */
+
+static void
+ppc64_emit_le_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:ble   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] > TOP  */
+
+static void
+ppc64_emit_gt_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:bgt   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] >= TOP  */
+
+static void
+ppc64_emit_ge_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:bge   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Relocate previous emitted branch instruction.  FROM is the address
+   of the branch instruction, TO is the goto target address, and SIZE
+   if the value we set by *SIZE_P before.  Currently, it is either
+   24 or 14 of branch and conditional-branch instruction.  */
+
+static void
+ppc_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  int rel = to - from;
+  uint32_t insn;
+  int opcd;
+  unsigned char buf[4];
+
+  read_inferior_memory (from, buf, 4);
+  insn = get_i32 (buf);
+  opcd = (insn >> 26) & 0x3f;
+
+  switch (size)
+    {
+    case 14:
+      if (opcd != 16)
+	emit_error = 1;
+      insn = (insn & ~0xfffc) | (rel & 0xfffc);
+      break;
+    case 24:
+      if (opcd != 18)
+	emit_error = 1;
+      insn = (insn & ~0x3fffffc) | (rel & 0x3fffffc);
+      break;
+    default:
+      emit_error = 1;
+    }
+
+  put_i32 (buf, insn);
+  write_inferior_memory (from, buf, 4);
+}
+
+/* Vector of emit ops for PowerPC64.  */
+
+static struct emit_ops ppc64_emit_ops_vector =
+{
+  ppc64_emit_prologue,
+  ppc64_emit_epilogue,
+  ppc64_emit_add,
+  ppc64_emit_sub,
+  ppc64_emit_mul,
+  ppc64_emit_lsh,
+  ppc64_emit_rsh_signed,
+  ppc64_emit_rsh_unsigned,
+  ppc64_emit_ext,
+  ppc64_emit_log_not,
+  ppc64_emit_bit_and,
+  ppc64_emit_bit_or,
+  ppc64_emit_bit_xor,
+  ppc64_emit_bit_not,
+  ppc64_emit_equal,
+  ppc64_emit_less_signed,
+  ppc64_emit_less_unsigned,
+  ppc64_emit_ref,
+  ppc64_emit_if_goto,
+  ppc64_emit_goto,
+  ppc_write_goto_address,
+  ppc64_emit_const,
+  ppc64_emit_call,
+  ppc64_emit_reg,
+  ppc64_emit_pop,
+  ppc64_emit_stack_flush,
+  ppc64_emit_zero_ext,
+  ppc64_emit_swap,
+  ppc64_emit_stack_adjust,
+  ppc64_emit_int_call_1,
+  ppc64_emit_void_call_2,
+  ppc64_emit_eq_goto,
+  ppc64_emit_ne_goto,
+  ppc64_emit_lt_goto,
+  ppc64_emit_le_goto,
+  ppc64_emit_gt_goto,
+  ppc64_emit_ge_goto
+};
+
+/*  Implementation of emit_ops target ops.   */
+
+__attribute__ ((unused))
+static struct emit_ops *
+ppc_emit_ops (void)
+{
+  return &ppc64_emit_ops_vector;
+}
+#endif
+
+/* Returns true for supporting range-stepping.  */
+
+static int
+ppc_supports_range_stepping (void)
+{
+  return 1;
+}
+
  /* Provide only a fill function for the general register set.  ps_lgetregs
     will use this for NPTL support.  */

@@ -687,16 +1926,31 @@  struct linux_target_ops the_low_target = {
    ppc_set_pc,
    (const unsigned char *) &ppc_breakpoint,
    ppc_breakpoint_len,
-  NULL,
-  0,
+  NULL, /* breakpoint_reinsert_addr */
+  0, /* decr_pc_after_break */
    ppc_breakpoint_at,
-  NULL, /* supports_z_point_type */
-  NULL,
-  NULL,
-  NULL,
-  NULL,
+  ppc_supports_z_point_type, /* supports_z_point_type */
+  ppc_insert_point,
+  ppc_remove_point,
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
    ppc_collect_ptrace_register,
    ppc_supply_ptrace_register,
+  NULL, /* siginfo_fixup */
+  NULL, /* linux_new_process */
+  NULL, /* linux_new_thread */
+  NULL, /* linux_prepare_to_resume */
+  NULL, /* linux_process_qsupported */
+  ppc_supports_tracepoints,
+  NULL, /* get_thread_area */
+  ppc_install_fast_tracepoint_jump_pad,
+#if __PPC64__
+  ppc_emit_ops,
+#else
+  NULL, /* Use interpreter for ppc32.  */
+#endif
+  ppc_get_min_fast_tracepoint_insn_len,
+  ppc_supports_range_stepping,
  };

  void
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index ef94bba..dc27cfb 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -83,6 +83,9 @@ 
  #include "features/rs6000/powerpc-e500.c"
  #include "features/rs6000/rs6000.c"

+#include "ax.h"
+#include "ax-gdb.h"
+
  /* Determine if regnum is an SPE pseudo-register.  */
  #define IS_SPE_PSEUDOREG(tdep, regnum) ((tdep)->ppc_ev0_regnum >= 0 \
      && (regnum) >= (tdep)->ppc_ev0_regnum \
@@ -966,6 +969,21 @@  rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
      return little_breakpoint;
  }

+/* Return true if ADDR is a valid address for tracepoint.  Set *ISZIE
+   to the number of bytes the target should copy elsewhere for the
+   tracepoint.  */
+
+static int
+ppc_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
+			      CORE_ADDR addr, int *isize, char **msg)
+{
+  if (isize)
+    *isize = gdbarch_max_insn_length (gdbarch);
+  if (msg)
+    *msg = NULL;
+  return 1;
+}
+
  /* Instruction masks for displaced stepping.  */
  #define BRANCH_MASK 0xfc000000
  #define BP_MASK 0xFC0007FE
@@ -3679,6 +3697,8 @@  bfd_uses_spe_extensions (bfd *abfd)
  #define PPC_LK(insn)	PPC_BIT (insn, 31)
  #define PPC_TX(insn)	PPC_BIT (insn, 31)
  #define PPC_LEV(insn)	PPC_FIELD (insn, 20, 7)
+#define PPC_LI(insn)	(PPC_SEXT (PPC_FIELD (insn, 6, 24), 24) << 2)
+#define PPC_BD(insn)	(PPC_SEXT (PPC_FIELD (insn, 16, 14), 14) << 2)

  #define PPC_XT(insn)	((PPC_TX (insn) << 5) | PPC_T (insn))
  #define PPC_XER_NB(xer)	(xer & 0x7f)
@@ -5332,6 +5352,146 @@  UNKNOWN_OP:
    return 0;
  }

+/* Copy the instruction from OLDLOC to *TO, and update *TO to *TO + size
+   of instruction.  This function is used to adjust pc-relative instructions
+   when copying.  */
+
+static void
+ppc_relocate_instruction (struct gdbarch *gdbarch,
+			  CORE_ADDR *to, CORE_ADDR oldloc)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  uint32_t insn;
+  int op6, rel, newrel;
+
+  insn = read_memory_unsigned_integer (oldloc, 4, byte_order);
+  op6 = PPC_OP6 (insn);
+
+  if (op6 == 18 && (insn & 2) == 0)
+    {
+      /* branch && AA = 0 */
+      rel = PPC_LI (insn);
+      newrel = (oldloc - *to) + rel;
+
+      /* Out of range. Cannot relocate instruction.  */
+      if (newrel >= (1 << 25) || newrel < -(1 << 25))
+	return;
+
+      insn = (insn & ~0x3fffffc) | (newrel & 0x3fffffc);
+    }
+  else if (op6 == 16 && (insn & 2) == 0)
+    {
+      /* conditional branch && AA = 0 */
+
+      rel = PPC_BD (insn);
+      newrel = (oldloc - *to) + rel;
+
+      if (newrel >= (1 << 25) || newrel < -(1 << 25))
+	return;
+
+      newrel -= 4;
+      if (newrel >= (1 << 15) || newrel < -(1 << 15))
+	{
+	   /* The offset of to big for conditional-branch (16-bit).
+	      Try to invert the condition and jump with 26-bit branch.
+	      For example,
+
+		beq  .Lgoto
+		INSN1
+
+	      =>
+
+		bne  1f
+		b    .Lgoto
+	      1:INSN1
+
+	    */
+
+	   /* Check whether BO is 001at or 011 at.  */
+	   if ((PPC_BO (insn) & 0x14) != 0x4)
+	     return;
+
+	   /* Invert condition.  */
+	   insn ^= (1 << 24);
+	   /* Jump over the unconditional branch.  */
+	   insn = (insn & ~0xfffc) | 0x8;
+	   write_memory_unsigned_integer (*to, 4, byte_order, insn);
+	   *to += 4;
+
+	   /* Copy LK bit.  */
+	   insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
+	   write_memory_unsigned_integer (*to, 4, byte_order, insn);
+	   *to += 4;
+
+	   return;
+	}
+      else
+	insn = (insn & ~0xfffc) | (newrel & 0xfffc);
+    }
+
+  write_memory_unsigned_integer (*to, 4, byte_order, insn);
+  *to += 4;
+}
+
+/* Implement gdbarch_gen_return_address.  Generate a bytecode expression
+   to get the value of the saved PC.  SCOPE is the address we want to
+   get return address for.  SCOPE maybe in the middle of a function.  */
+
+static void
+ppc_gen_return_address (struct gdbarch *gdbarch,
+			struct agent_expr *ax, struct axs_value *value,
+			CORE_ADDR scope)
+{
+  struct rs6000_framedata frame;
+  CORE_ADDR func_addr;
+
+  /* Try to find the start of the function and analyze the prologue.  */
+  if (find_pc_partial_function (scope, NULL, &func_addr, NULL))
+    {
+      skip_prologue (gdbarch, func_addr, scope, &frame);
+
+      if (frame.lr_offset == 0)
+	{
+	  value->type = register_type (gdbarch, PPC_LR_REGNUM);
+	  value->kind = axs_lvalue_register;
+	  value->u.reg = PPC_LR_REGNUM;
+	  return;
+	}
+    }
+  else
+    {
+      /* If we don't where the function starts, we cannot analyze it.
+	 Assuming it's not a leaf function, not frameless, and LR is
+	 saved at back-chain + 16.  */
+
+      frame.frameless = 0;
+      frame.lr_offset = 16;
+    }
+
+  /* if (frameless)
+       load 16(SP)
+     else
+       BC = 0(SP)
+       load 16(BC) */
+
+  ax_reg (ax, gdbarch_sp_regnum (gdbarch));
+
+  /* Load back-chain.  */
+  if (!frame.frameless)
+    {
+      if (register_size (gdbarch, PPC_LR_REGNUM) == 8)
+	ax_simple (ax, aop_ref64);
+      else
+	ax_simple (ax, aop_ref32);
+    }
+
+  ax_const_l (ax, frame.lr_offset);
+  ax_simple (ax, aop_add);
+  value->type = register_type (gdbarch, PPC_LR_REGNUM);
+  value->kind = axs_lvalue_memory;
+}
+
  /* Initialize the current architecture based on INFO.  If possible, re-use an
     architecture from ARCHES, which is a list of architectures already created
     during this debugging session.
@@ -5892,6 +6052,7 @@  rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)

    set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
    set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
+  set_gdbarch_fast_tracepoint_valid_at (gdbarch, ppc_fast_tracepoint_valid_at);

    /* The value of symbols of type N_SO and N_FUN maybe null when
       it shouldn't be.  */
@@ -5929,6 +6090,9 @@  rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
    set_gdbarch_displaced_step_location (gdbarch,
  				       displaced_step_at_entry_point);

+  set_gdbarch_relocate_instruction (gdbarch, ppc_relocate_instruction);
+  set_gdbarch_gen_return_address (gdbarch, ppc_gen_return_address);
+
    set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);

    /* Hook in ABI-specific overrides, if they have been registered.  */
diff --git a/gdb/testsuite/gdb.trace/backtrace.exp b/gdb/testsuite/gdb.trace/backtrace.exp
index 045778e..3094074 100644
--- a/gdb/testsuite/gdb.trace/backtrace.exp
+++ b/gdb/testsuite/gdb.trace/backtrace.exp
@@ -146,6 +146,9 @@  if [is_amd64_regs_target] {
  } elseif [is_x86_like_target] {
      set fpreg "\$ebp"
      set spreg "\$esp"
+} elseif [istarget "powerpc*-*-*"] {
+    set fpreg "\$r31"
+    set spreg "\$r1"
  } else {
      set fpreg "\$fp"
      set spreg "\$sp"
diff --git a/gdb/testsuite/gdb.trace/change-loc.h b/gdb/testsuite/gdb.trace/change-loc.h
index e8e2e86..8efe12d 100644
--- a/gdb/testsuite/gdb.trace/change-loc.h
+++ b/gdb/testsuite/gdb.trace/change-loc.h
@@ -36,6 +36,8 @@  func4 (void)
         SYMBOL(set_tracepoint) ":\n"
  #if (defined __x86_64__ || defined __i386__)
         "    call " SYMBOL(func5) "\n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );

diff --git a/gdb/testsuite/gdb.trace/collection.exp b/gdb/testsuite/gdb.trace/collection.exp
index bd42cfa..ed562c9 100644
--- a/gdb/testsuite/gdb.trace/collection.exp
+++ b/gdb/testsuite/gdb.trace/collection.exp
@@ -44,6 +44,10 @@  if [is_amd64_regs_target] {
      set fpreg "ebp"
      set spreg "esp"
      set pcreg "eip"
+} elseif [istarget "powerpc*-*-*"] {
+    set fpreg "r31"
+    set spreg "r1"
+    set pcreg "pc"
  } else {
      set fpreg "fp"
      set spreg "sp"
diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp
index 0cf5615..f9928f1 100644
--- a/gdb/testsuite/gdb.trace/entry-values.exp
+++ b/gdb/testsuite/gdb.trace/entry-values.exp
@@ -218,6 +218,8 @@  if [is_amd64_regs_target] {
      set spreg "\$rsp"
  } elseif [is_x86_like_target] {
      set spreg "\$esp"
+} elseif [istarget "powerpc*-*-*"] {
+    set spreg "\$r1"
  } else {
      set spreg "\$sp"
  }
diff --git a/gdb/testsuite/gdb.trace/ftrace.c b/gdb/testsuite/gdb.trace/ftrace.c
index f522e6f..e509c7b 100644
--- a/gdb/testsuite/gdb.trace/ftrace.c
+++ b/gdb/testsuite/gdb.trace/ftrace.c
@@ -42,6 +42,8 @@  marker (int anarg)
         SYMBOL(set_point) ":\n"
  #if (defined __x86_64__ || defined __i386__)
         "    call " SYMBOL(func) "\n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );

@@ -53,6 +55,8 @@  marker (int anarg)
         SYMBOL(four_byter) ":\n"
  #if (defined __i386__)
         "    cmpl $0x1,0x8(%ebp) \n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );
  }
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index f2d8002..2cc7464 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -84,7 +84,8 @@  proc test_fast_tracepoints {} {

      gdb_test "print gdb_agent_gdb_trampoline_buffer_error" ".*" ""

-    if { [istarget "x86_64-*-*"] || [istarget "i\[34567\]86-*-*"] } {
+    if { [istarget "x86_64-*-*"] || [istarget "i\[34567\]86-*-*"] \
+	 || [istarget "powerpc*-*-*"] } {

  	gdb_test "ftrace set_point" "Fast tracepoint .*" \
  	    "fast tracepoint at a long insn"
@@ -178,6 +179,36 @@  proc test_fast_tracepoints {} {
      }
  }

+proc test_ftrace_condition { condexp list } \
+{ with_test_prefix "ond $condexp" \
+{
+    global executable
+    global hex
+
+    clean_restart ${executable}
+    if ![runto_main] {
+	fail "Can't run to main to check for trace support"
+	return -1
+    }
+
+    gdb_test "break end" ".*" ""
+    gdb_test "ftrace set_point if $condexp" "Fast tracepoint .*"
+    gdb_trace_setactions "set action for tracepoint .*" "" \
+	"collect globvar" "^$"
+
+    gdb_test_no_output "tstart" ""
+    gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" ""
+    gdb_test_no_output "tstop" ""
+
+    set i 0
+    foreach expval $list {
+	gdb_test "tfind" "Found trace frame $i, tracepoint .*" "tfind frame $i"
+	gdb_test "print globvar" "\\$\[0-9\]+ = $expval\[\r\n\]" "expect $expval"
+	set i [expr $i + 1]
+    }
+    gdb_test "tfind" "Target failed to find requested trace frame\."
+}}
+
  gdb_reinitialize_dir $srcdir/$subdir

  if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
@@ -186,3 +217,31 @@  if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
  }

  test_fast_tracepoints
+
+test_ftrace_condition "globvar > 7" { 8 9 10 }
+test_ftrace_condition "globvar < 4" { 1 2 3 }
+test_ftrace_condition "globvar >= 7" { 7 8 9 10 }
+test_ftrace_condition "globvar <= 4" { 1 2 3 4 }
+test_ftrace_condition "globvar == 5" { 5 }
+test_ftrace_condition "globvar != 5" { 1 2 3 4 6 7 8 9 10 }
+test_ftrace_condition "globvar > 3 && globvar < 7" { 4 5 6 }
+test_ftrace_condition "globvar < 3 || globvar > 7" { 1 2 8 9 10 }
+test_ftrace_condition "(globvar << 2) + 1 == 29" { 7 }
+test_ftrace_condition "(globvar >> 2) == 2" { 8 9 10 }
+
+# This expression is used for testing emit_reg.
+if [is_amd64_regs_target] {
+    set arg0exp "\$rdi"
+} elseif [is_x86_like_target] {
+    set arg0exp "*(int *) (\$ebp + 8)"
+} elseif [istarget "powerpc*-*-*"] {
+    set arg0exp "\$r3"
+} elseif [istarget "aarch64*"] {
+    set arg0exp "\$x0"
+} else {
+    set arg0exp ""
+}
+
+if { "$arg0exp" != "" } {
+    test_ftrace_condition "($arg0exp > 500)" { 6 7 8 9 10 }
+}
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index 51ed479..1df4d65 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -56,6 +56,8 @@  if [is_amd64_regs_target] {
      set pcreg "rip"
  } elseif [is_x86_like_target] {
      set pcreg "eip"
+} elseif [istarget "powerpc*-*-*"] {
+    set pcreg "pc"
  } else {
      # Other ports that support tracepoints should set the name of pc
      # register here.
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index 6b97d9d..1e6e541 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -135,6 +135,8 @@  proc test_trace_unavailable { data_source } {
  	    set pcnum 16
  	} elseif [is_x86_like_target] {
  	    set pcnum 8
+	} elseif [istarget "powerpc*-*-*"] {
+	    set pcnum 64
  	} else {
  	    # Other ports support tracepoint should define the number
  	    # of its own pc register.
diff --git a/gdb/testsuite/gdb.trace/pending.exp b/gdb/testsuite/gdb.trace/pending.exp
index 0399807..ed36cac 100644
--- a/gdb/testsuite/gdb.trace/pending.exp
+++ b/gdb/testsuite/gdb.trace/pending.exp
@@ -441,6 +441,8 @@  proc pending_tracepoint_with_action_resolved { trace_type } \
  	set pcreg "rip"
      } elseif [is_x86_like_target] {
  	set pcreg "eip"
+    } elseif [istarget "powerpc*-*-*"] {
+	set pcreg "pc"
      }

      gdb_trace_setactions "set action for pending tracepoint" "" \
diff --git a/gdb/testsuite/gdb.trace/pendshr1.c b/gdb/testsuite/gdb.trace/pendshr1.c
index d3b5463..2fd0fba 100644
--- a/gdb/testsuite/gdb.trace/pendshr1.c
+++ b/gdb/testsuite/gdb.trace/pendshr1.c
@@ -38,6 +38,8 @@  pendfunc (int x)
         SYMBOL(set_point1) ":\n"
  #if (defined __x86_64__ || defined __i386__)
         "    call " SYMBOL(pendfunc1) "\n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );
  }
diff --git a/gdb/testsuite/gdb.trace/pendshr2.c b/gdb/testsuite/gdb.trace/pendshr2.c
index b8a51a5..3f40c76 100644
--- a/gdb/testsuite/gdb.trace/pendshr2.c
+++ b/gdb/testsuite/gdb.trace/pendshr2.c
@@ -35,6 +35,8 @@  pendfunc2 (int x)
         SYMBOL(set_point2) ":\n"
  #if (defined __x86_64__ || defined __i386__)
         "    call " SYMBOL(foo) "\n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );
  }
diff --git a/gdb/testsuite/gdb.trace/range-stepping.c b/gdb/testsuite/gdb.trace/range-stepping.c
index 113f0e2..606db25 100644
--- a/gdb/testsuite/gdb.trace/range-stepping.c
+++ b/gdb/testsuite/gdb.trace/range-stepping.c
@@ -26,6 +26,8 @@ 
     tracepoint jump.  */
  #if (defined __x86_64__ || defined __i386__)
  #  define NOP "   .byte 0xe9,0x00,0x00,0x00,0x00\n" /* jmp $+5 (5-byte nop) */
+#elif (defined __PPC64__ || defined __PPC__)
+#  define NOP "    nop\n"
  #else
  #  define NOP "" /* port me */
  #endif
diff --git a/gdb/testsuite/gdb.trace/report.exp b/gdb/testsuite/gdb.trace/report.exp
index 2fa676b..e0160f7 100644
--- a/gdb/testsuite/gdb.trace/report.exp
+++ b/gdb/testsuite/gdb.trace/report.exp
@@ -158,6 +158,10 @@  if [is_amd64_regs_target] {
      set fpreg "ebp"
      set spreg "esp"
      set pcreg "eip"
+} elseif [istarget "powerpc*-*-*"] {
+    set fpreg "r31"
+    set spreg "r1"
+    set pcreg "pc"
  } else {
      set fpreg "fp"
      set spreg "sp"
diff --git a/gdb/testsuite/gdb.trace/trace-break.c b/gdb/testsuite/gdb.trace/trace-break.c
index f381ec6..ced0e92 100644
--- a/gdb/testsuite/gdb.trace/trace-break.c
+++ b/gdb/testsuite/gdb.trace/trace-break.c
@@ -41,6 +41,8 @@  marker (void)
         SYMBOL(set_point) ":\n"
  #if (defined __x86_64__ || defined __i386__)
         "    call " SYMBOL(func) "\n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );

@@ -48,6 +50,8 @@  marker (void)
         SYMBOL(after_set_point) ":\n"
  #if (defined __x86_64__ || defined __i386__)
         "    call " SYMBOL(func) "\n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );
  }
diff --git a/gdb/testsuite/gdb.trace/trace-break.exp b/gdb/testsuite/gdb.trace/trace-break.exp
index 4283ca6..9d6551a 100644
--- a/gdb/testsuite/gdb.trace/trace-break.exp
+++ b/gdb/testsuite/gdb.trace/trace-break.exp
@@ -49,6 +49,10 @@  if [is_amd64_regs_target] {
      set fpreg "ebp"
      set spreg "esp"
      set pcreg "eip"
+} elseif [istarget "powerpc*-*-*"] {
+    set fpreg "r31"
+    set spreg "r1"
+    set pcreg "pc"
  }

  # Set breakpoint and tracepoint at the same address.
diff --git a/gdb/testsuite/gdb.trace/trace-mt.c b/gdb/testsuite/gdb.trace/trace-mt.c
index 38aeff5..855de54 100644
--- a/gdb/testsuite/gdb.trace/trace-mt.c
+++ b/gdb/testsuite/gdb.trace/trace-mt.c
@@ -37,6 +37,8 @@  thread_function(void *arg)
         SYMBOL(set_point1) ":\n"
  #if (defined __x86_64__ || defined __i386__)
         "    call " SYMBOL(func) "\n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
  #endif
         );
  }
diff --git a/gdb/testsuite/gdb.trace/while-dyn.exp b/gdb/testsuite/gdb.trace/while-dyn.exp
index 198421e..ef92b2d 100644
--- a/gdb/testsuite/gdb.trace/while-dyn.exp
+++ b/gdb/testsuite/gdb.trace/while-dyn.exp
@@ -47,6 +47,8 @@  if [is_amd64_regs_target] {
      set fpreg "\$rbp"
  } elseif [is_x86_like_target] {
      set fpreg "\$ebp"
+} elseif [istarget "powerpc*-*-*"] {
+    set fpreg "\$r31"
  } else {
      set fpreg "\$fp"
  }