Add framework for ppc64 support.  Apologies in advance for the
inevitable breakage to other platforms.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5250 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/Makefile.am b/Makefile.am
index 6a0e9cd..d39d0ea 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,6 +47,10 @@
 BUILT_SOURCES += valt_load_address_ppc32_linux.lds
 CLEANFILES += valt_load_address_ppc32_linux.lds
 endif
+if VG_PPC64_LINUX
+BUILT_SOURCES += valt_load_address_ppc64_linux.lds
+CLEANFILES += valt_load_address_ppc64_linux.lds
+endif
 
 default.supp: $(SUPP_FILES)
 
@@ -82,6 +86,7 @@
 	@VEX_DIR@/pub/libvex_guest_amd64.h \
 	@VEX_DIR@/pub/libvex_ir.h \
 	@VEX_DIR@/pub/libvex_guest_ppc32.h \
+	@VEX_DIR@/pub/libvex_guest_ppc64.h \
 	@VEX_DIR@/pub/libvex_basictypes.h \
 	@VEX_DIR@/pub/libvex_guest_offsets.h \
 	@VEX_DIR@/pub/libvex_emwarn.h \
@@ -101,6 +106,7 @@
 	VEX/pub/libvex_guest_amd64.h \
 	VEX/pub/libvex_ir.h \
 	VEX/pub/libvex_guest_ppc32.h \
+	VEX/pub/libvex_guest_ppc64.h \
 	VEX/pub/libvex_basictypes.h \
 	VEX/pub/libvex_guest_offsets.h \
 	VEX/pub/libvex_emwarn.h \
@@ -189,7 +195,14 @@
 	|| rm -f $@
 
 valt_load_address_ppc32_linux.lds: Makefile
-	$(CC) -Wl,--verbose -nostdlib 2>&1 | sed \
+	$(CC) @FLAG_M32@ -Wl,--verbose -nostdlib 2>&1 | sed \
+		-e '1,/^=====\+$$/d' \
+		-e '/^=====\+$$/d' \
+		-e '/\. = 0x[0-9A-Fa-f]\+ + SIZEOF_HEADERS/s/0x[0-9A-Fa-f]\+/valt_load_address/g' > $@ \
+	|| rm -f $@
+
+valt_load_address_ppc64_linux.lds: Makefile
+	$(CC) -m64 -Wl,--verbose -nostdlib 2>&1 | sed \
 		-e '1,/^=====\+$$/d' \
 		-e '/^=====\+$$/d' \
 		-e '/\. = 0x[0-9A-Fa-f]\+ + SIZEOF_HEADERS/s/0x[0-9A-Fa-f]\+/valt_load_address/g' > $@ \
diff --git a/Makefile.core.am b/Makefile.core.am
index c9729fe..6cf336c 100644
--- a/Makefile.core.am
+++ b/Makefile.core.am
@@ -34,9 +34,22 @@
 		-DVGO_linux=1 \
 		-DVGP_ppc32_linux=1
 
+add_includes_ppc64_linux = -I$(top_srcdir)/coregrind \
+		-I$(top_srcdir) \
+		-I$(top_srcdir)/coregrind/ppc64 \
+		-I$(top_srcdir)/coregrind/linux \
+		-I$(top_srcdir)/coregrind/ppc64-linux \
+		-I$(top_srcdir)/include \
+		-I@VEX_DIR@/pub \
+		-DVG_PLATFORM="\"ppc64-linux\"" \
+		-DVGA_ppc64=1 \
+		-DVGO_linux=1 \
+		-DVGP_ppc64_linux=1
+
 include $(top_srcdir)/Makefile.flags.am
 
 PRELOAD_LDFLAGS_COMMON = -nostdlib -shared -Wl,-z,interpose,-z,initfirst
 PRELOAD_LDFLAGS_X86_LINUX = $(PRELOAD_LDFLAGS_COMMON) @FLAG_M32@
 PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD_LDFLAGS_COMMON) -m64
-PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON)
+PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON) @FLAG_M32@
+PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON) -m64
diff --git a/Makefile.flags.am b/Makefile.flags.am
index 3f12c7e..1d4555e 100644
--- a/Makefile.flags.am
+++ b/Makefile.flags.am
@@ -12,8 +12,12 @@
 AM_CCASFLAGS_AMD64_LINUX = $(add_includes_amd64_linux) -m64 -g
 
 AM_CPPFLAGS_PPC32_LINUX = $(add_includes_ppc32_linux)
-AM_CFLAGS_PPC32_LINUX = $(WERROR) $(AM_CFLAGS_BASE)
-AM_CCASFLAGS_PPC32_LINUX = $(add_includes_ppc32_linux) -Wa,-maltivec -g
+AM_CFLAGS_PPC32_LINUX = $(WERROR) @FLAG_M32@ $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC32_LINUX = $(add_includes_ppc32_linux) -Wa,-maltivec @FLAG_M32@ -g
+
+AM_CPPFLAGS_PPC64_LINUX = $(add_includes_ppc64_linux)
+AM_CFLAGS_PPC64_LINUX = $(WERROR) -m64 $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC64_LINUX = $(add_includes_ppc64_linux) -Wa,-maltivec -m64 -g
 
 AM_CPPFLAGS = $(AM_CPPFLAGS_@VG_MAKE_PLATFORM@)
 AM_CFLAGS = $(AM_CFLAGS_@VG_MAKE_PLATFORM@)
diff --git a/Makefile.tool-flags.am b/Makefile.tool-flags.am
index 25100b9..26d08e6 100644
--- a/Makefile.tool-flags.am
+++ b/Makefile.tool-flags.am
@@ -16,4 +16,10 @@
 		-DVGO_linux=1 \
 		-DVGP_ppc32_linux=1
 
+add_includes_ppc64_linux = -I$(top_srcdir)/include \
+		-I@VEX_DIR@/pub \
+		-DVGA_ppc64=1 \
+		-DVGO_linux=1 \
+		-DVGP_ppc64_linux=1
+
 include $(top_srcdir)/Makefile.flags.am
diff --git a/Makefile.tool.am b/Makefile.tool.am
index bab28fa..e985aec 100644
--- a/Makefile.tool.am
+++ b/Makefile.tool.am
@@ -15,6 +15,9 @@
 LIBREPLACEMALLOC_PPC32_LINUX = \
 	$(top_builddir)/coregrind/libreplacemalloc_toolpreload_ppc32_linux.a
 
+LIBREPLACEMALLOC_PPC64_LINUX = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload_ppc64_linux.a
+
 COREGRIND_LIBS_X86_LINUX = \
 	$(top_builddir)/coregrind/libcoregrind_x86_linux.a \
 	@VEX_DIR@/libvex_x86_linux.a
@@ -27,6 +30,10 @@
 	$(top_builddir)/coregrind/libcoregrind_ppc32_linux.a \
 	@VEX_DIR@/libvex_ppc32_linux.a
 
+COREGRIND_LIBS_PPC64_LINUX = \
+	$(top_builddir)/coregrind/libcoregrind_ppc64_linux.a \
+	@VEX_DIR@/libvex_ppc64_linux.a
+
 ##.PHONY:  @VEX_DIR@/libvex.a
 
 @VEX_DIR@/libvex_x86_linux.a: @VEX_DIR@/priv/main/vex_svnversion.h
@@ -38,6 +45,9 @@
 @VEX_DIR@/libvex_ppc32_linux.a: @VEX_DIR@/priv/main/vex_svnversion.h
 	$(MAKE) -C @VEX_DIR@ CC="$(CC)" libvex_ppc32_linux.a EXTRA_CFLAGS="$(AM_CFLAGS_PPC32_LINUX)"
 
+@VEX_DIR@/libvex_ppc64_linux.a: @VEX_DIR@/priv/main/vex_svnversion.h
+	$(MAKE) -C @VEX_DIR@ CC="$(CC)" libvex_ppc64_linux.a EXTRA_CFLAGS="$(AM_CFLAGS_PPC64_LINUX)"
+
 @VEX_DIR@/priv/main/vex_svnversion.h:
 	$(MAKE) -C @VEX_DIR@ CC="$(CC)" version
 
@@ -58,13 +68,19 @@
 
 TOOL_LDADD_PPC32_LINUX = $(COREGRIND_LIBS_PPC32_LINUX) $(TOOL_LDADD_COMMON)
 TOOL_LDFLAGS_PPC32_LINUX = \
-	$(TOOL_LDFLAGS_COMMON) \
+	$(TOOL_LDFLAGS_COMMON) @FLAG_M32@ \
 	-Wl,-T,$(top_builddir)/valt_load_address_ppc32_linux.lds
 
+TOOL_LDADD_PPC64_LINUX = $(COREGRIND_LIBS_PPC64_LINUX) $(TOOL_LDADD_COMMON)
+TOOL_LDFLAGS_PPC64_LINUX = \
+	$(TOOL_LDFLAGS_COMMON) -m64 \
+	-Wl,-T,$(top_builddir)/valt_load_address_ppc64_linux.lds
+
 PRELOAD_LDFLAGS_COMMON = -nostdlib -shared -Wl,-z,interpose,-z,initfirst
 PRELOAD_LDFLAGS_X86_LINUX = $(PRELOAD_LDFLAGS_COMMON) @FLAG_M32@
 PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD_LDFLAGS_COMMON) -m64
-PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON)
+PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON) @FLAG_M32@
+PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON) -m64
 
 LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \
 	-Wl,--whole-archive \
@@ -78,3 +94,7 @@
 	-Wl,--whole-archive \
 	$(LIBREPLACEMALLOC_PPC32_LINUX) \
 	-Wl,--no-whole-archive
+LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX = \
+	-Wl,--whole-archive \
+	$(LIBREPLACEMALLOC_PPC64_LINUX) \
+	-Wl,--no-whole-archive
diff --git a/cachegrind/Makefile.am b/cachegrind/Makefile.am
index 863c12b..51bd5bd 100644
--- a/cachegrind/Makefile.am
+++ b/cachegrind/Makefile.am
@@ -14,11 +14,15 @@
 if VG_PPC32_LINUX
 noinst_PROGRAMS += cachegrind-ppc32-linux
 endif
+if VG_PPC64_LINUX
+noinst_PROGRAMS += cachegrind-ppc64-linux
+endif
 
 CACHEGRIND_SOURCES_COMMON = cg_main.c
 CACHEGRIND_SOURCES_X86 = cg-x86.c
 CACHEGRIND_SOURCES_AMD64 = cg-amd64.c
 CACHEGRIND_SOURCES_PPC32 = cg-ppc32.c
+CACHEGRIND_SOURCES_PPC64 = cg-ppc64.c
 
 cachegrind_x86_linux_SOURCES      = $(CACHEGRIND_SOURCES_COMMON) $(CACHEGRIND_SOURCES_X86)
 cachegrind_x86_linux_CPPFLAGS     = $(AM_CPPFLAGS_X86_LINUX)
@@ -40,3 +44,10 @@
 cachegrind_ppc32_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC32_LINUX)
 cachegrind_ppc32_linux_LDADD        = $(TOOL_LDADD_PPC32_LINUX)
 cachegrind_ppc32_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC32_LINUX)
+
+cachegrind_ppc64_linux_SOURCES      = $(CACHEGRIND_SOURCES_COMMON) $(CACHEGRIND_SOURCES_PPC64)
+cachegrind_ppc64_linux_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+cachegrind_ppc64_linux_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX)
+cachegrind_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_LINUX)
+cachegrind_ppc64_linux_LDADD        = $(TOOL_LDADD_PPC64_LINUX)
+cachegrind_ppc64_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC64_LINUX)
diff --git a/cachegrind/cg-ppc64.c b/cachegrind/cg-ppc64.c
new file mode 100644
index 0000000..18a0e07
--- /dev/null
+++ b/cachegrind/cg-ppc64.c
@@ -0,0 +1,61 @@
+
+/*--------------------------------------------------------------------*/
+/*--- PPC64-specific definitions.                 ppc64/cg-ppc64.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Cachegrind, a Valgrind tool for cache
+   profiling programs.
+
+   Copyright (C) 2005 Nicholas Nethercote
+      njn@valgrind.org
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_tool_basics.h"
+#include "pub_tool_libcbase.h"
+#include "pub_tool_libcassert.h"
+#include "pub_tool_libcprint.h"
+
+#include "cg_arch.h"
+
+void VG_(configure_caches)(cache_t* I1c, cache_t* D1c, cache_t* L2c,
+                           Bool all_caches_clo_defined)
+{
+   // Set caches to default.
+   *I1c = (cache_t) {  65536, 2, 64 };
+   *D1c = (cache_t) {  65536, 2, 64 };
+   *L2c = (cache_t) { 262144, 8, 64 };
+
+   // Warn if config not completely specified from cmd line.  Note that
+   // this message is slightly different from the one we give on x86/AMD64
+   // when auto-detection fails;  this lets us filter out this one (which is
+   // not important) in the regression test suite without filtering the
+   // x86/AMD64 one (which we want to see if it ever occurs in the
+   // regression test suite).
+   if (!all_caches_clo_defined) {
+      VG_(message)(Vg_DebugMsg, 
+                   "Warning: Cannot auto-detect cache config on PPC64, using one "
+                   "or more defaults ");
+   }
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/cachegrind/tests/Makefile.am b/cachegrind/tests/Makefile.am
index 9ebfe90..aee2531 100644
--- a/cachegrind/tests/Makefile.am
+++ b/cachegrind/tests/Makefile.am
@@ -8,6 +8,9 @@
 if VG_PPC32_LINUX
 SUBDIRS += ppc32
 endif
+if VG_PPC64_LINUX
+SUBDIRS += ppc64
+endif
 
 DIST_SUBDIRS = ${VG_ARCH_ALL} .
 
diff --git a/configure.in b/configure.in
index 099b990..5681fd7 100644
--- a/configure.in
+++ b/configure.in
@@ -110,7 +110,7 @@
 AC_MSG_CHECKING([for a supported CPU])
 AC_SUBST(VG_ARCH)
 AC_SUBST(VG_ARCH_ALL)
-VG_ARCH_ALL="amd64 ppc32 x86"
+VG_ARCH_ALL="amd64 ppc32 ppc64 x86"
 AC_SUBST(VALT_LOAD_ADDRESS)
 
 case "${host_cpu}" in
@@ -131,7 +131,14 @@
         valt_load_address_inner="0x60000000"
         ;;
 
-     powerpc*)
+     powerpc64)
+        AC_MSG_RESULT([ok (${host_cpu})])
+        VG_ARCH="ppc64"
+        valt_load_address_normal="0x70000000"
+        valt_load_address_inner="0x60000000"
+        ;;
+
+     powerpc)
         AC_MSG_RESULT([ok (${host_cpu})])
         VG_ARCH="ppc32"
         valt_load_address_normal="0x70000000"
@@ -205,12 +212,12 @@
 AC_MSG_CHECKING([for a supported CPU/OS combination])
 AC_SUBST(VG_PLATFORM)
 AC_SUBST(VG_PLATFORM_ALL)
-VG_PLATFORM_ALL="amd64-linux ppc32-linux x86-linux"
+VG_PLATFORM_ALL="amd64-linux ppc32-linux ppc64-linux x86-linux"
 
 VG_PLATFORM="$VG_ARCH-$VG_OS"
 
 case $VG_PLATFORM in
-    x86-linux|amd64-linux|ppc32-linux)
+    x86-linux|amd64-linux|ppc32-linux|ppc64-linux)
         AC_MSG_RESULT([ok (${host_cpu}-${host_os})])
         ;;
 
@@ -220,12 +227,27 @@
         ;;
 esac
 
-AM_CONDITIONAL(VG_X86_LINUX, test x$VG_PLATFORM = xx86-linux -o x$VG_PLATFORM = xamd64-linux)
+AM_CONDITIONAL(VG_X86_LINUX,   test x$VG_PLATFORM = xx86-linux -o x$VG_PLATFORM = xamd64-linux)
 AM_CONDITIONAL(VG_AMD64_LINUX, test x$VG_PLATFORM = xamd64-linux)
-AM_CONDITIONAL(VG_PPC32_LINUX, test x$VG_PLATFORM = xppc32-linux)
+AM_CONDITIONAL(VG_PPC32_LINUX, test x$VG_PLATFORM = xppc32-linux -o x$VG_PLATFORM = xppc64-linux)
+AM_CONDITIONAL(VG_PPC64_LINUX, test x$VG_PLATFORM = xppc64-linux)
 
 AC_SUBST(VG_MAKE_PLATFORM)
-VG_MAKE_PLATFORM=`echo $VG_PLATFORM | tr [a-z-] [A-Z_]`
+case $VG_PLATFORM in
+     x86-linux)
+	VG_MAKE_PLATFORM=X86_LINUX
+	;;
+     amd64-linux)
+	VG_MAKE_PLATFORM=AMD64_LINUX
+	;;
+     ppc32-linux|ppc64-linux)
+	VG_MAKE_PLATFORM=PPC32_LINUX
+	;;
+     *)
+	AC_MSG_ERROR([VG_PLATFORM is not known -- configure script bug])
+	;;
+esac
+##VG_MAKE_PLATFORM=`echo $VG_PLATFORM | tr [a-z-] [A-Z_]`
 
 AC_SUBST(DEFAULT_SUPP)
 
@@ -484,12 +506,14 @@
    memcheck/tests/Makefile
    memcheck/tests/amd64/Makefile
    memcheck/tests/ppc32/Makefile
+   memcheck/tests/ppc64/Makefile
    memcheck/tests/x86/Makefile
    memcheck/docs/Makefile
    cachegrind/Makefile
    cachegrind/tests/Makefile
    cachegrind/tests/amd64/Makefile
    cachegrind/tests/ppc32/Makefile
+   cachegrind/tests/ppc64/Makefile
    cachegrind/tests/x86/Makefile
    cachegrind/docs/Makefile
    cachegrind/cg_annotate
@@ -507,6 +531,7 @@
    none/tests/Makefile
    none/tests/amd64/Makefile
    none/tests/ppc32/Makefile
+   none/tests/ppc64/Makefile
    none/tests/x86/Makefile
    none/docs/Makefile
 ) 
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 45972c9..b61ab26 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -11,6 +11,7 @@
 AM_CPPFLAGS_X86_LINUX   += -DVG_LIBDIR="\"$(valdir)"\"
 AM_CPPFLAGS_AMD64_LINUX += -DVG_LIBDIR="\"$(valdir)"\"
 AM_CPPFLAGS_PPC32_LINUX += -DVG_LIBDIR="\"$(valdir)"\"
+AM_CPPFLAGS_PPC64_LINUX += -DVG_LIBDIR="\"$(valdir)"\"
 
 
 default.supp: $(SUPP_FILES)
@@ -25,6 +26,9 @@
 if VG_PPC32_LINUX
 noinst_LIBRARIES += libcoregrind_ppc32_linux.a libreplacemalloc_toolpreload_ppc32_linux.a
 endif
+if VG_PPC64_LINUX
+noinst_LIBRARIES += libcoregrind_ppc64_linux.a libreplacemalloc_toolpreload_ppc64_linux.a
+endif
 
 bin_PROGRAMS = \
 	valgrind
@@ -39,6 +43,9 @@
 if VG_PPC32_LINUX
 noinst_PROGRAMS += vgpreload_core-ppc32-linux.so
 endif
+if VG_PPC64_LINUX
+noinst_PROGRAMS += vgpreload_core-ppc64-linux.so
+endif
 
 noinst_HEADERS = \
 	coregrind.h		\
@@ -207,6 +214,19 @@
 libcoregrind_ppc32_linux_a_CFLAGS = $(AM_CFLAGS_PPC32_LINUX)
 libcoregrind_ppc32_linux_a_CCASFLAGS = $(AM_CCASFLAGS_PPC32_LINUX)
 
+libcoregrind_ppc64_linux_a_SOURCES = \
+	$(COREGRIND_SOURCES_COMMON) \
+	$(COREGRIND_LINUX_SOURCE) \
+	m_coredump/coredump-ppc64-linux.c \
+	m_dispatch/dispatch-ppc64-linux.S \
+	m_sigframe/sigframe-ppc64-linux.c \
+	m_syswrap/syscall-ppc64-linux.S \
+	m_syswrap/syswrap-ppc64-linux.c
+
+libcoregrind_ppc64_linux_a_CPPFLAGS = $(AM_CPPFLAGS_PPC64_LINUX)
+libcoregrind_ppc64_linux_a_CFLAGS = $(AM_CFLAGS_PPC64_LINUX)
+libcoregrind_ppc64_linux_a_CCASFLAGS = $(AM_CCASFLAGS_PPC64_LINUX)
+
 libreplacemalloc_toolpreload_x86_linux_a_SOURCES = m_replacemalloc/vg_replace_malloc.c
 libreplacemalloc_toolpreload_x86_linux_a_CPPFLAGS = $(AM_CPPFLAGS_X86_LINUX)
 libreplacemalloc_toolpreload_x86_linux_a_CFLAGS = $(AM_CFLAGS_X86_LINUX) -fpic -fno-omit-frame-pointer
@@ -219,12 +239,18 @@
 libreplacemalloc_toolpreload_ppc32_linux_a_CPPFLAGS = $(AM_CPPFLAGS_PPC32_LINUX)
 libreplacemalloc_toolpreload_ppc32_linux_a_CFLAGS = $(AM_CFLAGS_PPC32_LINUX) -fpic -fno-omit-frame-pointer
 
+libreplacemalloc_toolpreload_ppc64_linux_a_SOURCES = m_replacemalloc/vg_replace_malloc.c
+libreplacemalloc_toolpreload_ppc64_linux_a_CPPFLAGS = $(AM_CPPFLAGS_PPC64_LINUX)
+libreplacemalloc_toolpreload_ppc64_linux_a_CFLAGS = $(AM_CFLAGS_PPC64_LINUX) -fpic -fno-omit-frame-pointer
+
 m_dispatch/dispatch-x86-linux.S:	 libvex_guest_offsets.h
 m_dispatch/dispatch-amd64-linux.S:	 libvex_guest_offsets.h
 m_dispatch/dispatch-ppc32-linux.S:	 libvex_guest_offsets.h
+m_dispatch/dispatch-ppc64-linux.S:	 libvex_guest_offsets.h
 m_syswrap/syscall-x86-linux.S:		 libvex_guest_offsets.h
 m_syswrap/syscall-amd64-linux.S:	 libvex_guest_offsets.h
 m_syswrap/syscall-ppc32-linux.S:	 libvex_guest_offsets.h
+m_syswrap/syscall-ppc64-linux.S:	 libvex_guest_offsets.h
 m_syswrap/syswrap-main.c: 		 libvex_guest_offsets.h
 
 libvex_guest_offsets.h:
@@ -247,6 +273,11 @@
 vgpreload_core_ppc32_linux_so_CFLAGS = $(AM_CFLAGS_PPC32_LINUX) $(AM_CFLAGS_PIC)
 vgpreload_core_ppc32_linux_so_LDFLAGS = $(PRELOAD_LDFLAGS_PPC32_LINUX)
 
+vgpreload_core_ppc64_linux_so_SOURCES = $(VGPRELOAD_CORE_SOURCES_COMMON)
+vgpreload_core_ppc64_linux_so_CPPFLAGS = $(AM_CPPFLAGS_PPC64_LINUX)
+vgpreload_core_ppc64_linux_so_CFLAGS = $(AM_CFLAGS_PPC64_LINUX) $(AM_CFLAGS_PIC)
+vgpreload_core_ppc64_linux_so_LDFLAGS = $(PRELOAD_LDFLAGS_PPC64_LINUX)
+
 clean-local:
 	$(MAKE) -C @VEX_DIR@ CC="$(CC)" clean
 
diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c
index 693a784..d64b062 100644
--- a/coregrind/m_aspacemgr/aspacemgr.c
+++ b/coregrind/m_aspacemgr/aspacemgr.c
@@ -445,7 +445,7 @@
 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
    res = VG_(do_syscall6)(__NR_mmap2, (UWord)start, length,
                           prot, flags, fd, offset / VKI_PAGE_SIZE);
-#  elif defined(VGP_amd64_linux)
+#  elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
    res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, 
                          prot, flags, fd, offset);
 #  else
diff --git a/coregrind/m_coredump/coredump-ppc64-linux.c b/coregrind/m_coredump/coredump-ppc64-linux.c
new file mode 100644
index 0000000..71cddca
--- /dev/null
+++ b/coregrind/m_coredump/coredump-ppc64-linux.c
@@ -0,0 +1,76 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Dumping core.                         coredump-ppc32-linux.c ---*/
+/*--------------------------------------------------------------------*/
+ 
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Julian Seward 
+      jseward@acm.org
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_coredump.h"
+#include "pub_core_threadstate.h"
+
+#include "priv_elf.h"
+
+void ML_(fill_elfregs_from_tst)(struct vki_user_regs_struct* regs, 
+                                const ThreadArchState* arch)
+{
+#  define DO(n)  regs->gpr[n] = arch->vex.guest_GPR##n
+   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
+   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+#  undef DO
+
+   regs->nip = arch->vex.guest_CIA;
+   regs->msr = 0xf032;   /* pretty arbitrary */
+   regs->orig_gpr3 = arch->vex.guest_GPR3;
+   regs->ctr = arch->vex.guest_CTR;
+   regs->link = arch->vex.guest_LR;
+   regs->xer = LibVEX_GuestPPC64_get_XER( &((ThreadArchState*)arch)->vex );
+   regs->ccr = LibVEX_GuestPPC64_get_CR( &((ThreadArchState*)arch)->vex );
+   /* regs->mq = 0; */
+   regs->trap = 0;
+   regs->dar = 0; /* should be fault address? */
+   regs->dsisr = 0;
+   regs->result = 0;
+}
+
+void ML_(fill_elffpregs_from_tst)(vki_elf_fpregset_t* fpu,
+                                  const ThreadArchState* arch)
+{
+   /* The guest state has the FPR fields declared as ULongs, so need
+      to fish out the values without converting them. */
+#  define DO(n)  (*fpu)[n] = *(double*)(&arch->vex.guest_FPR##n)
+   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
+   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+#  undef DO
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_coredump/priv_elf.h b/coregrind/m_coredump/priv_elf.h
index a1340a4..692cef6 100644
--- a/coregrind/m_coredump/priv_elf.h
+++ b/coregrind/m_coredump/priv_elf.h
@@ -28,8 +28,8 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#ifndef __PRIV_SYMTAB_H
-#define __PRIV_SYMTAB_H
+#ifndef __PRIV_ELF_H
+#define __PRIV_ELF_H
 
 void ML_(fill_elfregs_from_tst)(struct vki_user_regs_struct* regs, 
                                 const ThreadArchState* arch);
@@ -42,7 +42,7 @@
                                    const ThreadArchState* arch);
 #endif
 
-#endif   // __PRIV_SYMTAB_H
+#endif   // __PRIV_ELF_H
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
diff --git a/coregrind/m_debugger.c b/coregrind/m_debugger.c
index 8c0bc27..9a5cc0d 100644
--- a/coregrind/m_debugger.c
+++ b/coregrind/m_debugger.c
@@ -36,6 +36,7 @@
 #include "pub_core_libcprint.h"
 #include "pub_core_libcproc.h"
 #include "pub_core_libcsignal.h"
+#include "pub_core_libcassert.h"
 #include "pub_core_options.h"
 
 
@@ -130,6 +131,9 @@
                      (void*)LibVEX_GuestPPC32_get_XER(vex));
    return rc;
 
+#elif defined(VGA_ppc64)
+   I_die_here;
+
 #else
 #  error Unknown arch
 #endif
diff --git a/coregrind/m_debuginfo/dwarf.c b/coregrind/m_debuginfo/dwarf.c
index 457c862..560ded2 100644
--- a/coregrind/m_debuginfo/dwarf.c
+++ b/coregrind/m_debuginfo/dwarf.c
@@ -1321,6 +1321,10 @@
 #  define FP_REG         1
 #  define SP_REG         1
 #  define RA_REG_DEFAULT 8     // CAB: What's a good default ?
+#elif defined(VGP_ppc64_linux)
+#  define FP_REG         1
+#  define SP_REG         1
+#  define RA_REG_DEFAULT 8     // CAB: What's a good default ?
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_debuginfo/symtab.c b/coregrind/m_debuginfo/symtab.c
index a92685f..0afe0d8 100644
--- a/coregrind/m_debuginfo/symtab.c
+++ b/coregrind/m_debuginfo/symtab.c
@@ -2267,8 +2267,8 @@
    case 15:          return (Addr) & arch->vex.guest_R15;
    default:          return 0;
    }
-#elif defined(VGA_ppc32)
-   /* This is the Intel register encoding -- integer regs. */
+#elif defined(VGA_ppc32) || defined(VGA_ppc64)
+   /* This is the PPC register encoding -- integer regs. */
 #  define R_STACK_PTR   1
 #  define R_FRAME_PTR   1
    switch (regno) {
diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c
index 48d5caf..39473c8 100644
--- a/coregrind/m_debuglog.c
+++ b/coregrind/m_debuglog.c
@@ -54,7 +54,7 @@
 /*--- Stuff to make us completely independent.             ---*/
 /*------------------------------------------------------------*/
 
-/* ----- x86-linux specifics ----- */
+/* ----- Platform-specifics ----- */
 
 #if defined(VGP_x86_linux)
 
@@ -158,6 +158,39 @@
    return __res;
 }
 
+#elif defined(VGP_ppc64_linux)
+
+static UInt local_sys_write_stderr ( HChar* buf, Int n )
+{
+   UInt __res;
+   __asm__ volatile (
+      "li %%r0,4\n\t"      /* set %r0 = __NR_write */
+      "li %%r3,2\n\t"      /* set %r3 = stderr */
+      "mr %%r4,%1\n\t"     /* set %r4 = buf */
+      "mr %%r5,%2\n\t"     /* set %r5 = n */
+      "sc\n\t"             /* write(stderr, buf, n) */
+      "mr %0,%%r3\n"       /* set __res = r3 */
+      : "=mr" (__res)
+      : "g" (buf), "g" (n)
+      : "r0", "r3", "r4", "r5" );
+   if (__res < 0)
+      __res = -1;
+   return __res;
+}
+
+static UInt local_sys_getpid ( void )
+{
+   UInt __res;
+   __asm__ volatile (
+      "li %%r0,20\n"       /* set %r0 = __NR_getpid */
+      "\tsc\n"             /* getpid() */
+      "\tmr %0,%%r3\n"     /* set __res = r3 */
+      : "=mr" (__res)
+      :
+      : "r0" );
+   return __res;
+}
+
 #else
 # error Unknown platform
 #endif
diff --git a/coregrind/m_dispatch/dispatch-ppc64-linux.S b/coregrind/m_dispatch/dispatch-ppc64-linux.S
new file mode 100644
index 0000000..1eea790
--- /dev/null
+++ b/coregrind/m_dispatch/dispatch-ppc64-linux.S
@@ -0,0 +1,474 @@
+
+##--------------------------------------------------------------------##
+##--- The core dispatch loop, for jumping to a code address.       ---##
+##---                                             dispatch-ppc64.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, a dynamic binary instrumentation
+  framework.
+
+  Copyright (C) 2005 Cerion Armour-Brown <cerion@open-works.co.uk>
+
+  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 2 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, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics_asm.h"
+#include "pub_core_dispatch_asm.h"
+#include "pub_core_transtab_asm.h"
+#include "libvex_guest_offsets.h"	/* for OFFSET_ppc64_CIA */
+
+
+/* References to globals via the TOC */
+
+	.section        ".toc","aw"
+tocent__vgPlain_tt_fast:
+	.tc vgPlain_tt_fast[TC],vgPlain_tt_fast
+
+/*------------------------------------------------------------*/
+/*--- The dispatch loop.                                   ---*/
+/*------------------------------------------------------------*/
+
+	.section	".text"
+	.align 2
+
+/* signature: UWord VG_(run_innerloop) ( void* guest_state ) */
+
+        .globl  .VG_(run_innerloop)
+.VG_(run_innerloop):
+        /* ----- entry point to VG_(run_innerloop) ----- */
+
+        /* For Linux/ppc32 we need the SysV ABI, which uses
+           LR->4(parent_sp), CR->anywhere.
+           (The AIX ABI, used on Darwin, and maybe Linux/ppc64?,
+           uses LR->8(prt_sp), CR->4(prt_sp))
+        */
+
+        /* Save lr */
+        mflr    0
+        stw     0,4(1)
+
+        /* New stack frame */
+        stwu    1,-624(1)  /* sp should maintain 16-byte alignment */
+
+        /* Save callee-saved registers... */
+
+        /* Floating-point reg save area : 144 bytes */
+        stfd    31,616(1)
+        stfd    30,608(1)
+        stfd    29,600(1)
+        stfd    28,592(1)
+        stfd    27,584(1)
+        stfd    26,576(1)
+        stfd    25,568(1)
+        stfd    24,560(1)
+        stfd    23,552(1)
+        stfd    22,544(1)
+        stfd    21,536(1)
+        stfd    20,528(1)
+        stfd    19,520(1)
+        stfd    18,512(1)
+        stfd    17,504(1)
+        stfd    16,496(1)
+        stfd    15,488(1)
+        stfd    14,480(1)
+
+        /* General reg save area : 144 bytes */
+        stw     31,472(1)
+        stw     30,464(1)
+        stw     29,456(1)
+        stw     28,448(1)
+        stw     27,440(1)
+        stw     26,432(1)
+        stw     25,424(1)
+        stw     24,416(1)
+        stw     23,408(1)
+        stw     22,400(1)
+        stw     21,392(1)
+        stw     20,384(1)
+        stw     19,376(1)
+        stw     18,368(1)
+        stw     17,360(1)
+        stw     16,352(1)
+        stw     15,344(1)
+        stw     14,336(1)
+        /* Probably not necessary to save r13 (thread-specific ptr),
+           as VEX stays clear of it... but what the hey. */
+        stw     13,328(1)
+
+        /* It's necessary to save/restore VRSAVE in the AIX / Darwin ABI.
+           The Linux kernel might not actually use VRSAVE for its intended
+           purpose, but it should be harmless to preserve anyway. */
+	/* r3 is live here (guest state ptr), so use r4 */
+        lis     4,VG_(machine_ppc64_has_VMX)@ha
+        lwz     4,VG_(machine_ppc64_has_VMX)@l(4)
+        cmplwi  4,0
+        beq     LafterVMX1
+
+        /* VRSAVE save word : 32 bytes */
+        mfspr   4,256         /* vrsave reg is spr number 256 */
+        stw     4,324(1)
+
+        /* Alignment padding : 4 bytes */
+
+        /* Vector reg save area (quadword aligned) : 192 bytes */
+        li      4,304
+        stvx    31,4,1
+        li      4,288
+        stvx    30,4,1
+        li      4,272
+        stvx    29,4,1
+        li      4,256
+        stvx    28,4,1
+        li      4,240
+        stvx    27,4,1
+        li      4,224
+        stvx    26,4,1
+        li      4,208
+        stvx    25,4,1
+        li      4,192
+        stvx    24,4,1
+        li      4,176
+        stvx    23,4,1
+        li      4,160
+        stvx    22,4,1
+        li      4,144
+        stvx    21,4,1
+        li      4,128
+        stvx    20,4,1
+LafterVMX1:
+
+        /* Save cr */
+        mfcr    0
+        stw     0,112(1)
+
+
+        /* Local variable space... */
+
+        /* r3 holds guest_state */
+        mr      31,3
+        stw     3,104(1)       /* spill orig guest_state ptr */
+
+        /* 96(sp) used later to check FPSCR[RM] */
+
+        /* 88(sp) used later to stop ctr reg being clobbered */
+
+	/* 48:87(sp) free */
+	
+        /* Linkage Area (reserved)
+           40(sp) : TOC
+           32(sp) : link editor doubleword
+           24(sp) : compiler doubleword
+           16(sp) : LR
+           8(sp)  : CR
+           0(sp)  : back-chain
+        */
+
+// CAB TODO: Use a caller-saved reg for orig guest_state ptr
+// - rem to set non-allocateable in isel.c
+
+        /* hold dispatch_ctr in ctr reg */
+        lis     17,VG_(dispatch_ctr)@ha
+        lwz     17,VG_(dispatch_ctr)@l(17)
+        mtctr   17
+
+        /* fetch %CIA into r30 */
+        lwz     30,OFFSET_ppc64_CIA(31)
+
+        /* set host FPU control word to the default mode expected 
+           by VEX-generated code.  See comments in libvex.h for
+           more info. */
+        fsub    3,3,3   /* generate zero */
+        mtfsf   0xFF,3
+
+        /* set host AltiVec control word to the default mode expected 
+           by VEX-generated code. */
+        lis     3,VG_(machine_ppc64_has_VMX)@ha
+        lwz     3,VG_(machine_ppc64_has_VMX)@l(3)
+        cmplwi  3,0
+        beq     LafterVMX2
+
+        vspltisw 3,0x0  /* generate zero */
+        mtvscr  3
+LafterVMX2:
+
+        /* make a stack frame for the code we are calling */
+        stwu    1,-48(1)
+
+        /* fall into main loop */
+
+/* Live regs:
+	r1 (=sp)
+	r2 (toc pointer)
+	r30 (=guest CIA = jump address)
+	r31 (=guest_state)
+	ctr (=dispatch_ctr)
+   Stack state:
+	104 (r1) (=guest_state ptr)
+	96 (r1) (=var space for FPSCR[RM])
+	88 (r1) (=var space for CTR)
+	44:87 (r1) (=free)
+        0:43 (r1) (=stack frame header)
+*/
+
+dispatch_boring:
+        /* save the jump address in the guest state */
+        std     30,OFFSET_ppc64_CIA(31)
+
+        /* Are we out of timeslice?  If yes, defer to scheduler. */
+        bdz     counter_is_zero  /* decrements ctr reg */
+
+        /* try a fast lookup in the translation cache */
+        /* r4=((r30<<3) & (VG_TT_FAST_MASK<<3)) */
+	rldic	4,30, 3,64-3-VG_TT_FAST_BITS
+// CAB:	use a caller-saved reg for this ?
+	/* r5 = & VG_(tt_fast) */
+	ld	5, tocent__vgPlain_tt_fast@toc(2)
+	/* r5 = VG_(tt_fast)[r30 & VG_TT_FAST_MASK] */
+	ldx	5, 5,4
+	/* r6 = VG_(tt_fast)[r30 & VG_TT_FAST_MASK]->orig_addr */
+	ld	6, 0(5)
+        cmpw    30,6
+        bne     fast_lookup_failed
+
+        /* increment bb profile counter */
+// CAB:	use a caller-saved reg for this ?
+	/* r7 = & VG_(tt_fastN) */
+	ld	7, tocent__vgPlain_tt_fast@toc(2)
+	/* r7 = VG_(tt_fastN)[r30 & VG_TT_FAST_MASK] */
+	srdi	4, 4,1
+	lwzx	6, 7,4
+	addi	6, 6,1
+	stwx	6, 7,4
+
+        /* Found a match.  Call tce[1], which is 8 bytes along, since
+           each tce element is a 64-bit int. */
+        addi    8,5,8
+        mtlr    8
+
+        /* stop ctr being clobbered */
+// CAB:	use a caller-saved reg for this ?
+//      but then (bdz) => (decr, cmp, bc)... still better than a stw?
+        mfctr   9
+        std     9,136(1)         /* => 88(parent_sp) */
+
+        blrl
+
+
+        /* On return from guest code:
+	   r3 holds destination (original) address.
+
+           r31 may be unchanged (guest_state), or may indicate further
+           details of the control transfer requested to *r3.
+
+           If r31 is unchanged, just jump next to r3.
+
+           Otherwise fall out, back to the scheduler, and let it
+           figure out what to do next.
+        */
+
+	/* reinstate clobbered ctr */
+        ld      9,136(1)          /* => 88(parent_sp) */
+        mtctr   9
+
+        mr      30,3             /* put CIA (=r3) in r30 */
+        ld      16,152(1)        /* gst_state ptr => 104(prnt_sp) */
+        cmpd    16,31
+        beq     dispatch_boring  /* r31 unchanged... */
+
+        mr      3,31             /* put return val (=r31) in r3 */
+        b       dispatch_exceptional
+
+/* All exits from the dispatcher go through here.
+   r3 holds the return value. 
+*/
+run_innerloop_exit: 
+        /* We're leaving.  Check that nobody messed with
+           VSCR or FPSCR. */
+
+/* This check avoidance may be removable if stfiwx is implemented. */
+#if !defined(ENABLE_INNER)
+        /* Check FPSCR & 0xFF == 0 (lowest 8bits are controls)  */
+        mffs      4                       /* fpscr -> fpr */
+        li        5,144                   /* => 96(parent_sp) */
+        stfiwx    4,5,1                   /* fpr to stack */
+        lwzx      6,5,1                   /* load to gpr */
+        andi.     6,6,0xFF                /* mask wanted bits */
+        cmplwi    6,0x0                   /* cmp with zero */
+        bne       invariant_violation     /* branch if not zero */
+#endif
+
+	/* Using r11 - value used again further on, so don't trash! */
+        lis     11,VG_(machine_ppc64_has_VMX)@ha
+        lwz     11,VG_(machine_ppc64_has_VMX)@l(11)
+        cmplwi  11,0
+        beq     LafterVMX8
+
+        /* Check VSCR[NJ] == 1 */
+        /* first generate 4x 0x00010000 */
+        vspltisw  4,0x1                   /* 4x 0x00000001 */
+        vspltisw  5,0x0                   /* zero */
+        vsldoi    6,4,5,0x2               /* <<2*8 => 4x 0x00010000 */
+        /* retrieve VSCR and mask wanted bits */
+        mfvscr    7
+        vand      7,7,6                   /* gives NJ flag */
+        vspltw    7,7,0x3                 /* flags-word to all lanes */
+        vcmpequw. 8,6,7                   /* CR[24] = 1 if v6 == v7 */
+        bt        24,invariant_violation  /* branch if all_equal */
+LafterVMX8:
+
+	/* otherwise we're OK */
+        b       run_innerloop_exit_REALLY
+
+
+invariant_violation:
+        li      3,VG_TRC_INVARIANT_FAILED
+        b       run_innerloop_exit_REALLY
+
+run_innerloop_exit_REALLY:
+        /* r3 holds VG_TRC_* value to return */
+
+        /* Return to parent stack */
+        addi    1,1,48
+
+        /* Write ctr to VG(dispatch_ctr) */
+        mfctr   17
+        lis     18,VG_(dispatch_ctr)@ha
+        stw     17,VG_(dispatch_ctr)@l(18)
+
+        /* Restore cr */
+        lwz     0,112(1)
+        mtcr    0
+
+        /* Restore callee-saved registers... */
+
+        /* Floating-point regs */
+        lfd    31,616(1)
+        lfd    30,608(1)
+        lfd    29,600(1)
+        lfd    28,592(1)
+        lfd    27,584(1)
+        lfd    26,576(1)
+        lfd    25,568(1)
+        lfd    24,560(1)
+        lfd    23,552(1)
+        lfd    22,544(1)
+        lfd    21,536(1)
+        lfd    20,528(1)
+        lfd    19,520(1)
+        lfd    18,512(1)
+        lfd    17,504(1)
+        lfd    16,496(1)
+        lfd    15,488(1)
+        lfd    14,480(1)
+
+        /* General regs */
+        lwz     31,472(1)
+        lwz     30,464(1)
+        lwz     29,456(1)
+        lwz     28,448(1)
+        lwz     27,440(1)
+        lwz     26,432(1)
+        lwz     25,424(1)
+        lwz     24,416(1)
+        lwz     23,408(1)
+        lwz     22,400(1)
+        lwz     21,392(1)
+        lwz     20,384(1)
+        lwz     19,376(1)
+        lwz     18,368(1)
+        lwz     17,360(1)
+        lwz     16,352(1)
+        lwz     15,344(1)
+        lwz     14,336(1)
+        lwz     13,328(1)
+
+        /* r11 already holds VG_(machine_ppc64_has_VMX) value */
+        cmplwi  11,0
+        beq     LafterVMX9
+
+        /* VRSAVE */
+        lwz     4,324(1)
+        mfspr   4,256         /* VRSAVE reg is spr number 256 */
+
+        /* Vector regs */
+        li      4,304
+        lvx     31,4,1
+        li      4,288
+        lvx     30,4,1
+        li      4,272
+        lvx     29,4,1
+        li      4,256
+        lvx     28,4,1
+        li      4,240
+        lvx     27,4,1
+        li      4,224
+        lvx     26,4,1
+        li      4,208
+        lvx     25,4,1
+        li      4,192
+        lvx     24,4,1
+        li      4,176
+        lvx     23,4,1
+        li      4,160
+        lvx     22,4,1
+        li      4,144
+        lvx     21,4,1
+        li      4,128
+        lvx     20,4,1
+LafterVMX9:
+
+        /* reset lr & sp */
+        lwz     0,628(1)  /* stack_size + 4 */
+        mtlr    0
+        addi    1,1,624   /* stack_size */
+        blr
+
+
+/* Other ways of getting out of the inner loop.  Placed out-of-line to
+   make it look cleaner. 
+*/
+dispatch_exceptional:
+	/* this is jumped to only, not fallen-through from above */
+	/* save r30 in %CIA and defer to sched */
+        lwz     16,152(1)
+        stw     30,OFFSET_ppc64_CIA(16)
+        b       run_innerloop_exit
+
+fast_lookup_failed:
+	/* %CIA is up to date here since dispatch_boring dominates */
+        mfctr   17
+        addi    17,17,1
+	mtctr   17
+        li      3,VG_TRC_INNER_FASTMISS
+	b       run_innerloop_exit
+
+counter_is_zero:
+	/* %CIA is up to date here since dispatch_boring dominates */
+        mfctr   17
+        addi    17,17,1
+	mtctr   17
+        li      3,VG_TRC_INNER_COUNTERZERO
+        b       run_innerloop_exit
+
+/* Let the linker know we don't need an executable stack */
+.section .note.GNU-stack,"",@progbits
+
+##--------------------------------------------------------------------##
+##--- end                                                          ---##
+##--------------------------------------------------------------------##
diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
index 8cd810b..773b601 100644
--- a/coregrind/m_libcassert.c
+++ b/coregrind/m_libcassert.c
@@ -75,6 +75,20 @@
             "=r" (fp)               \
           : /* reads none */        \
           : "r0" /* trashed */ );
+#elif defined(VGP_ppc64_linux)
+#  define GET_REAL_PC_SP_AND_FP(pc, sp, fp)                   \
+      asm("mflr 0;"                   /* r0 = lr */           \
+          "bl m_libcassert_get_ip;"   /* lr = pc */           \
+          "m_libcassert_get_ip:\n"                            \
+          "mflr %0;"                \
+          "mtlr 0;"                   /* restore lr */        \
+          "mr %1,1;"                \
+          "mr %2,1;"                \
+          : "=r" (pc),              \
+            "=r" (sp),              \
+            "=r" (fp)               \
+          : /* reads none */        \
+          : "r0" /* trashed */ );
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
index 8a78d6d..c3ed7d3 100644
--- a/coregrind/m_libcfile.c
+++ b/coregrind/m_libcfile.c
@@ -478,7 +478,7 @@
 static
 Int my_socket ( Int domain, Int type, Int protocol )
 {
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    SysRes res;
    UWord  args[3];
    args[0] = domain;
@@ -501,7 +501,7 @@
 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, 
                  Int addrlen )
 {
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    SysRes res;
    UWord  args[3];
    args[0] = sockfd;
@@ -528,7 +528,7 @@
       error is still returned. */
    Int flags = VKI_MSG_NOSIGNAL;
 
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    SysRes res;
    UWord  args[4];
    args[0] = sd;
@@ -552,7 +552,7 @@
 {
    SysRes res;
 
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    UWord  args[3];
    args[0] = sd;
    args[1] = (UWord)name;
@@ -574,7 +574,7 @@
 {
    SysRes res;
 
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    UWord  args[3];
    args[0] = sd;
    args[1] = (UWord)name;
@@ -597,7 +597,7 @@
 {
    SysRes res;
 
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    UWord  args[5];
    args[0] = sd;
    args[1] = level;
diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c
index c851fc2..1db9d45 100644
--- a/coregrind/m_libcproc.c
+++ b/coregrind/m_libcproc.c
@@ -412,7 +412,7 @@
       list[i] = (UInt)list16[i];
    return size;
 
-#  elif defined(VGP_amd64_linux)
+#  elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
    SysRes sres;
    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
    if (sres.isError)
diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
index 8c3d096..403b8fd 100644
--- a/coregrind/m_machine.c
+++ b/coregrind/m_machine.c
@@ -58,7 +58,7 @@
 
 Addr VG_(get_LR) ( ThreadId tid )
 {
-#  if defined(VGA_ppc32)
+#  if defined(VGA_ppc32) || defined(VGA_ppc64)
    return VG_(threads)[tid].arch.vex.guest_LR;
 #  elif defined(VGA_x86) || defined(VGA_amd64)
    return 0;
@@ -137,7 +137,7 @@
    (*f)(vex->guest_R13);
    (*f)(vex->guest_R14);
    (*f)(vex->guest_R15);
-#elif defined(VGA_ppc32)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64)
    /* XXX ask tool about validity? */
    (*f)(vex->guest_GPR0);
    (*f)(vex->guest_GPR1);
@@ -258,13 +258,16 @@
 UInt VG_(machine_ppc32_has_FP)  = 0;
 UInt VG_(machine_ppc32_has_VMX) = 0;
 #endif
+#if defined(VGA_ppc64)
+ULong VG_(machine_ppc64_has_VMX) = 0;
+#endif
 
 
 /* Determine what insn set and insn set variant the host has, and
    record it.  To be called once at system startup.  Returns False if
    this a CPU incapable of running Valgrind. */
 
-#if defined(VGA_ppc32)
+#if defined(VGA_ppc32) || defined(VGA_ppc64)
 #include <setjmp.h> // For jmp_buf
 static jmp_buf env_sigill;
 static void handler_sigill ( Int x ) { __builtin_longjmp(env_sigill,1); }
@@ -397,12 +400,54 @@
      return True;
    }
 
+#elif defined(VGA_ppc64)
+   { vki_sigset_t         saved_set, tmp_set;
+     struct vki_sigaction saved_act, tmp_act;
+
+     volatile Bool have_vmx;
+
+     VG_(sigemptyset)(&tmp_set);
+     VG_(sigaddset)(&tmp_set, VKI_SIGILL);
+
+     VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
+
+     VG_(sigaction)(VKI_SIGILL, NULL, &saved_act);
+     tmp_act = saved_act;
+
+     tmp_act.sa_flags &= ~VKI_SA_RESETHAND;
+     tmp_act.sa_flags &= ~VKI_SA_SIGINFO;
+
+     tmp_act.ksa_handler = handler_sigill;
+     VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
+
+     have_vmx = True;
+     if (__builtin_setjmp(env_sigill)) {
+        have_vmx = False;
+     } else {
+        __asm__ __volatile__("vor 0,0,0");
+     }
+
+     VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
+     VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
+
+     /* VG_(printf)("VMX %d\n", (Int)have_vmx); */
+
+     VG_(machine_ppc64_has_VMX) = have_vmx ? 1 : 0;
+
+     va = VexArchPPC64;
+     vai.subarch = have_vmx ? VexSubArchPPC64_VFI : VexSubArchPPC64_FI;
+
+     /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
+        called before we're ready to go. */
+     return True;
+   }
+
 #else
 #  error "Unknown arch"
 #endif
 }
 
-/* Notify host cpu cache line size, as per above comment. */
+/* Notify host cpu cache line size. */
 #if defined(VGA_ppc32)
 void VG_(machine_ppc32_set_clszB)( Int szB )
 {
@@ -420,6 +465,24 @@
 #endif
 
 
+/* Notify host cpu cache line size. */
+#if defined(VGA_ppc64)
+void VG_(machine_ppc64_set_clszB)( Int szB )
+{
+   vg_assert(hwcaps_done);
+
+   /* Either the value must not have been set yet (zero) or we can
+      tolerate it being set to the same value multiple times, as the
+      stack scanning logic in m_main is a bit stupid. */
+   vg_assert(vai.ppc32_cache_line_szB == 0
+             || vai.ppc32_cache_line_szB == szB);
+
+   vg_assert(szB == 32 || szB == 128);
+   vai.ppc32_cache_line_szB = szB;
+}
+#endif
+
+
 /* Fetch host cpu info, once established. */
 void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
                                    /*OUT*/VexArchInfo* pVai )
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index 8f4b4b7..c4da14f 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -1741,6 +1741,20 @@
    arch->vex.guest_GPR1 = client_sp;
    arch->vex.guest_CIA  = client_ip;
 
+#elif defined(VGA_ppc64)
+   vg_assert(0 == sizeof(VexGuestPPC64State) % 8);
+
+   /* Zero out the initial state, and set up the simulated FPU in a
+      sane way. */
+   LibVEX_GuestPPC64_initialise(&arch->vex);
+
+   /* Zero out the shadow area. */
+   VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
+
+   /* Put essential stuff into the new state. */
+   arch->vex.guest_GPR1 = client_sp;
+   arch->vex.guest_CIA  = client_ip;
+
 #else
 #  error Unknown arch
 #endif
@@ -2320,7 +2334,7 @@
 
 #     if defined(VGP_x86_linux)
       iters = 5;
-#     elif defined(VGP_amd64_linux)
+#     elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
       iters = 10;
 #     elif defined(VGP_ppc32_linux)
       iters = 5;
@@ -2847,6 +2861,37 @@
     "\ttrap\n"
     ".previous\n"
 );
+#elif defined(VGP_ppc64_linux)
+asm("\n"
+    ".text\n"
+    "\t.globl _start\n"
+    "\t.type _start,@function\n"
+    "_start:\n"
+    /* set up the new stack in r16 */
+    "\tlis  16,   vgPlain_interim_stack@highest\n"
+    "\tori  16,16,vgPlain_interim_stack@higher\n"
+    "\tsldi 16,16,32\n"
+    "\toris 16,16,vgPlain_interim_stack@h\n"
+    "\tori  16,16,vgPlain_interim_stack@l\n"
+    "\txor  17,17,17\n"
+    "\tlis    17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
+    "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
+    "\txor 18,18,18\n"
+    "\tlis    18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
+    "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
+    "\tadd 16,17,16\n"
+    "\tadd 16,18,16\n"
+    "\trldicr 16,16,0,59\n"
+    /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
+       VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
+       boundary.  And r1 is the original SP.  Set the SP to r16 and
+       call _start_in_C, passing it the initial SP. */
+    "\tmr 3,1\n"
+    "\tmr 1,16\n"
+    "\tbl _start_in_C\n"
+    "\ttrap\n"
+    ".previous\n"
+);
 #else
 #error "_start: needs implementation on this platform"
 #endif
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 56a89e4..1539980 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -404,6 +404,10 @@
 
    }
 
+#elif defined(VGP_ppc64_linux)
+
+   // we'll have to stick some godawful hacks in here, no doubt
+
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
index 9bfc6ca..fd5a5ed 100644
--- a/coregrind/m_scheduler/scheduler.c
+++ b/coregrind/m_scheduler/scheduler.c
@@ -901,7 +901,7 @@
 #elif defined(VGA_amd64)
 #  define VG_CLREQ_ARGS       guest_RAX
 #  define VG_CLREQ_RET        guest_RDX
-#elif defined(VGA_ppc32)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #  define VG_CLREQ_ARGS       guest_GPR4
 #  define VG_CLREQ_RET        guest_GPR3
 #else
diff --git a/coregrind/m_sigframe/sigframe-ppc64-linux.c b/coregrind/m_sigframe/sigframe-ppc64-linux.c
new file mode 100644
index 0000000..723bf03
--- /dev/null
+++ b/coregrind/m_sigframe/sigframe-ppc64-linux.c
@@ -0,0 +1,421 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Create/destroy signal delivery frames.                       ---*/
+/*---                                       sigframe-ppc64-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Nicholas Nethercote
+      njn@valgrind.org
+   Copyright (C) 2004-2005 Paul Mackerras
+      paulus@samba.org
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_machine.h"
+#include "pub_core_options.h"
+#include "pub_core_sigframe.h"
+#include "pub_core_signals.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_trampoline.h"
+#include "pub_core_transtab.h"      // VG_(discard_translations)
+#include "vki_unistd-ppc64-linux.h" // __NR_rt_sigreturn
+
+
+/* This module creates and removes signal frames for signal deliveries
+   on ppc64-linux.
+
+   Note, this file contains kernel-specific knowledge in the form of
+   'struct sigframe' and 'struct rt_sigframe'.  How does that relate
+   to the vki kernel interface stuff?
+
+   Either a 'struct sigframe' or a 'struct rtsigframe' is pushed 
+   onto the client's stack.  This contains a subsidiary
+   vki_ucontext.  That holds the vcpu's state across the signal, 
+   so that the sighandler can mess with the vcpu state if it
+   really wants.
+
+   FIXME: sigcontexting is basically broken for the moment.  When
+   delivering a signal, the integer registers and %eflags are
+   correctly written into the sigcontext, however the FP and SSE state
+   is not.  When returning from a signal, only the integer registers
+   are restored from the sigcontext; the rest of the CPU state is
+   restored to what it was before the signal.
+
+   This will be fixed.
+*/
+
+
+/*------------------------------------------------------------*/
+/*--- Signal frame layouts                                 ---*/
+/*------------------------------------------------------------*/
+
+// A structure in which to save the application's registers
+// during the execution of signal handlers.
+
+// Linux has 2 signal frame structures: one for normal signal
+// deliveries, and one for SA_SIGINFO deliveries (also known as RT
+// signals).
+//
+// In theory, so long as we get the arguments to the handler function
+// right, it doesn't matter what the exact layout of the rest of the
+// frame is.  Unfortunately, things like gcc's exception unwinding
+// make assumptions about the locations of various parts of the frame,
+// so we need to duplicate it exactly.
+
+/* Structure containing bits of information that we want to save
+   on signal delivery. */
+//zz struct vg_sig_private {
+//zz    UInt magicPI;
+//zz    UInt sigNo_private;
+//zz    VexGuestPPC32State shadow;
+//zz };
+//zz 
+//zz /* Structure put on stack for signal handlers with SA_SIGINFO clear. */
+//zz struct nonrt_sigframe {
+//zz    UInt gap1[16];
+//zz    struct vki_sigcontext sigcontext;
+//zz    struct vki_mcontext mcontext;
+//zz    struct vg_sig_private priv;
+//zz    unsigned char abigap[224];
+//zz };
+//zz 
+//zz /* Structure put on stack for signal handlers with SA_SIGINFO set. */
+//zz struct rt_sigframe {
+//zz    UInt gap1[20];
+//zz    vki_siginfo_t siginfo;
+//zz    struct vki_ucontext ucontext;
+//zz    struct vg_sig_private priv;
+//zz    unsigned char abigap[224];
+//zz };
+
+#define SET_SIGNAL_LR(zztst, zzval)                          \
+   do { tst->arch.vex.guest_LR = (zzval);                    \
+      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
+                offsetof(VexGuestPPC32State,guest_LR),       \
+                sizeof(UWord) );                             \
+   } while (0)
+
+#define SET_SIGNAL_GPR(zztst, zzn, zzval)                    \
+   do { tst->arch.vex.guest_GPR##zzn = (zzval);              \
+      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
+                offsetof(VexGuestPPC32State,guest_GPR##zzn), \
+                sizeof(UWord) );                             \
+   } while (0)
+
+
+static 
+void stack_mcontext ( struct vki_mcontext *mc, 
+                      ThreadState* tst, 
+                      Int ret,
+                      UInt fault_addr )
+{
+//   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
+//             (Addr)mc, sizeof(struct vki_pt_regs) );
+//
+//#  define DO(gpr)  mc->mc_gregs[VKI_PT_R0+gpr] = tst->arch.vex.guest_GPR##gpr
+//   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
+//   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+//   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+//   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+//#  undef DO
+//
+//   mc->mc_gregs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
+//   mc->mc_gregs[VKI_PT_MSR]     = 0xf032;   /* pretty arbitrary */
+//   mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
+//   mc->mc_gregs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
+//   mc->mc_gregs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
+//   mc->mc_gregs[VKI_PT_XER]     = LibVEX_GuestPPC32_get_XER(&tst->arch.vex);
+//   mc->mc_gregs[VKI_PT_CCR]     = LibVEX_GuestPPC32_get_CR(&tst->arch.vex);
+//   mc->mc_gregs[VKI_PT_MQ]      = 0;
+//   mc->mc_gregs[VKI_PT_TRAP]    = 0;
+//   mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
+//   mc->mc_gregs[VKI_PT_DSISR]   = 0;
+//   mc->mc_gregs[VKI_PT_RESULT]  = 0;
+//   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, 
+//             (Addr)mc, sizeof(struct vki_pt_regs) );
+//
+//   /* XXX should do FP and vector regs */
+//
+//   /* set up signal return trampoline */
+//   VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
+//            (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
+//   mc->mc_pad[0] = 0x38000000U + ret;   /* li 0,ret */
+//   mc->mc_pad[1] = 0x44000002U;         /* sc */
+//   VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid, 
+//             (Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
+//   /* invalidate any translation of this area */
+//   VG_(discard_translations)( (Addr64)(Addr)&mc->mc_pad, 
+//                              sizeof(mc->mc_pad), "stack_mcontext" );   
+//
+//   /* set the signal handler to return to the trampoline */
+//   SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]);
+}
+
+
+/* Extend the stack segment downwards if needed so as to ensure the
+   new signal frames are mapped to something.  Return a Bool
+   indicating whether or not the operation was successful.
+*/
+static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
+{
+   I_die_here;
+//   ThreadId tid = tst->tid;
+//   NSegment *stackseg = NULL;
+//
+//   if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
+//      stackseg = VG_(am_find_nsegment)(addr);
+//      if (0 && stackseg)
+//	 VG_(printf)("frame=%p seg=%p-%p\n",
+//		     addr, stackseg->start, stackseg->end);
+//   }
+//
+//   if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
+//      VG_(message)(
+//         Vg_UserMsg,
+//         "Can't extend stack to %p during signal delivery for thread %d:",
+//         addr, tid);
+//      if (stackseg == NULL)
+//         VG_(message)(Vg_UserMsg, "  no stack segment");
+//      else
+//         VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
+//
+//      /* set SIGSEGV to default handler */
+//      VG_(set_default_handler)(VKI_SIGSEGV);
+//      VG_(synth_fault_mapping)(tid, addr);
+//
+//      /* The whole process should be about to die, since the default
+//	 action of SIGSEGV to kill the whole process. */
+//      return False;
+//   }
+//
+//   /* For tracking memory events, indicate the entire frame has been
+//      allocated. */
+//   VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
+//             size + VG_STACK_REDZONE_SZB );
+//
+//   return True;
+}
+
+
+/* EXPORTED */
+void VG_(sigframe_create)( ThreadId tid, 
+                           Addr sp_top_of_frame,
+                           const vki_siginfo_t *siginfo,
+                           void *handler, 
+                           UInt flags,
+                           const vki_sigset_t *mask,
+		           void *restorer )
+{
+   I_die_here;
+//   struct vg_sig_private *priv;
+//   Addr sp;
+//   ThreadState *tst;
+//   Int sigNo = siginfo->si_signo;
+//   Addr faultaddr;
+//
+//   /* Stack must be 16-byte aligned */
+//   sp_top_of_frame &= ~0xf;
+//
+//   if (flags & VKI_SA_SIGINFO) {
+//      sp = sp_top_of_frame - sizeof(struct rt_sigframe);
+//   } else {
+//      sp = sp_top_of_frame - sizeof(struct nonrt_sigframe);
+//   }
+//
+//   tst = VG_(get_ThreadState)(tid);
+//
+//   if (!extend(tst, sp, sp_top_of_frame - sp))
+//      return;
+//
+//   vg_assert(VG_IS_16_ALIGNED(sp));
+//
+//   /* Set up the stack chain pointer */
+//   VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
+//             sp, sizeof(UWord) );
+//   *(Addr *)sp = tst->arch.vex.guest_GPR1;
+//   VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 
+//             sp, sizeof(UWord) );
+//
+//   faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
+//   if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
+//      faultaddr = tst->arch.vex.guest_CIA;
+//
+//   if (flags & VKI_SA_SIGINFO) {
+//      struct rt_sigframe *frame = (struct rt_sigframe *) sp;
+//      struct vki_ucontext *ucp = &frame->ucontext;
+//
+//      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
+//                (Addr)&frame->siginfo, sizeof(frame->siginfo) );
+//      VG_(memcpy)(&frame->siginfo, siginfo, sizeof(*siginfo));
+//      VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 
+//                (Addr)&frame->siginfo, sizeof(frame->siginfo) );
+//
+//      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
+//                (Addr)ucp, offsetof(struct vki_ucontext, uc_pad) );
+//      ucp->uc_flags = 0;
+//      ucp->uc_link = 0;
+//      ucp->uc_stack = tst->altstack;
+//      VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
+//                offsetof(struct vki_ucontext, uc_pad) );
+//
+//      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
+//                (Addr)&ucp->uc_regs,
+//                sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
+//      ucp->uc_regs = &ucp->uc_mcontext;
+//      ucp->uc_sigmask = tst->sig_mask;
+//      VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 
+//                (Addr)&ucp->uc_regs,
+//                sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
+//
+//      stack_mcontext(&ucp->uc_mcontext, tst, __NR_rt_sigreturn, faultaddr);
+//      priv = &frame->priv;
+//
+//      SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo);
+//      SET_SIGNAL_GPR(tid, 5, (Addr) ucp);
+//      /* the kernel sets this, though it doesn't seem to be in the ABI */
+//      SET_SIGNAL_GPR(tid, 6, (Addr) &frame->siginfo);
+//
+//   } else {
+//      /* non-RT signal delivery */
+//      struct nonrt_sigframe *frame = (struct nonrt_sigframe *) sp;
+//      struct vki_sigcontext *scp = &frame->sigcontext;
+//
+//      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame sigcontext",
+//                (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
+//      scp->signal = sigNo;
+//      scp->handler = (Addr) handler;
+//      scp->oldmask = tst->sig_mask.sig[0];
+//      scp->_unused[3] = tst->sig_mask.sig[1];
+//      VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
+//                (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
+//
+//      stack_mcontext(&frame->mcontext, tst, __NR_sigreturn, faultaddr);
+//      priv = &frame->priv;
+//
+//      SET_SIGNAL_GPR(tid, 4, (Addr) scp);
+//   }
+//
+//   priv->magicPI       = 0x31415927;
+//   priv->sigNo_private = sigNo;
+//   priv->shadow        = tst->arch.vex_shadow;
+//
+//   SET_SIGNAL_GPR(tid, 1, sp);
+//   SET_SIGNAL_GPR(tid, 3, sigNo);
+//   tst->arch.vex.guest_CIA = (Addr) handler;
+//
+//   if (0)
+//      VG_(printf)("pushed signal frame; %R1 now = %p, "
+//                  "next %%CIA = %p, status=%d\n", 
+//		  sp, tst->arch.vex.guest_CIA, tst->status);
+}
+
+
+/*------------------------------------------------------------*/
+/*--- Destroying signal frames                             ---*/
+/*------------------------------------------------------------*/
+
+/* EXPORTED */
+void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
+{
+   I_die_here;
+//   ThreadState *tst;
+//   struct vg_sig_private *priv;
+//   Addr sp;
+//   UInt frame_size;
+//   struct vki_mcontext *mc;
+//   Int sigNo;
+//   Bool has_siginfo = isRT;
+//
+//   vg_assert(VG_(is_valid_tid)(tid));
+//   tst = VG_(get_ThreadState)(tid);
+//
+//   /* Check that the stack frame looks valid */
+//   sp = tst->arch.vex.guest_GPR1;
+//   vg_assert(VG_IS_16_ALIGNED(sp));
+//   /* JRS 17 Nov 05: This code used to check that *sp -- which should
+//      have been set by the stwu at the start of the handler -- points
+//      to just above the frame (ie, the previous frame).  However, that
+//      isn't valid when delivering signals on alt stacks.  So I removed
+//      it.  The frame is still sanity-checked using the priv->magicPI
+//      field. */
+//
+//   if (has_siginfo) {
+//      struct rt_sigframe *frame = (struct rt_sigframe *)sp;
+//      frame_size = sizeof(*frame);
+//      mc = &frame->ucontext.uc_mcontext;
+//      priv = &frame->priv;
+//      vg_assert(priv->magicPI == 0x31415927);
+//      tst->sig_mask = frame->ucontext.uc_sigmask;
+//   } else {
+//      struct nonrt_sigframe *frame = (struct nonrt_sigframe *)sp;
+//      frame_size = sizeof(*frame);
+//      mc = &frame->mcontext;
+//      priv = &frame->priv;
+//      vg_assert(priv->magicPI == 0x31415927);
+//      tst->sig_mask.sig[0] = frame->sigcontext.oldmask;
+//      tst->sig_mask.sig[1] = frame->sigcontext._unused[3];
+//   }
+//   tst->tmp_sig_mask = tst->sig_mask;
+//
+//   sigNo = priv->sigNo_private;
+//
+//#  define DO(gpr)  tst->arch.vex.guest_GPR##gpr = mc->mc_gregs[VKI_PT_R0+gpr]
+//   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
+//   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+//   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+//   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+//#  undef DO
+//
+//   tst->arch.vex.guest_CIA = mc->mc_gregs[VKI_PT_NIP];
+//
+//   // Umm ... ? (jrs 2005 July 8)
+//   // tst->arch.m_orig_gpr3 = mc->mc_gregs[VKI_PT_ORIG_R3];
+//
+//   LibVEX_GuestPPC32_put_CR( mc->mc_gregs[VKI_PT_CCR], &tst->arch.vex );
+//
+//   tst->arch.vex.guest_LR  = mc->mc_gregs[VKI_PT_LNK];
+//   tst->arch.vex.guest_CTR = mc->mc_gregs[VKI_PT_CTR];
+//   LibVEX_GuestPPC32_put_XER( mc->mc_gregs[VKI_PT_XER], &tst->arch.vex );
+//
+//   tst->arch.vex_shadow = priv->shadow;
+//
+//   VG_TRACK(die_mem_stack_signal, sp, frame_size);
+//
+//   if (VG_(clo_trace_signals))
+//      VG_(message)(Vg_DebugMsg,
+//                   "vg_pop_signal_frame (thread %d): isRT=%d valid magic; EIP=%p",
+//                   tid, has_siginfo, tst->arch.vex.guest_CIA);
+//
+//   /* tell the tools */
+//   VG_TRACK( post_deliver_signal, tid, sigNo );
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                   sigframe-ppc64-linux.c ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c
index 881c13d..ace8de2 100644
--- a/coregrind/m_signals.c
+++ b/coregrind/m_signals.c
@@ -207,6 +207,19 @@
       )
 #  define VG_UCONTEXT_LINK_REG(uc)        ((uc)->uc_regs->mc_gregs[VKI_PT_LNK]) 
 
+#elif defined(VGP_ppc64_linux)
+#  define VG_UCONTEXT_INSTR_PTR(uc)       ((uc)->uc_mcontext.gp_regs[VKI_PT_NIP])
+#  define VG_UCONTEXT_STACK_PTR(uc)       ((uc)->uc_mcontext.gp_regs[VKI_PT_R1])
+#  define VG_UCONTEXT_FRAME_PTR(uc)       ((uc)->uc_mcontext.gp_regs[VKI_PT_R1])
+#  define VG_UCONTEXT_SYSCALL_NUM(uc)     ((uc)->uc_mcontext.gp_regs[VKI_PT_R0])
+#  define VG_UCONTEXT_SYSCALL_SYSRES(uc)                            \
+      /* Convert the values in uc_mcontext r3,cr into a SysRes. */  \
+      VG_(mk_SysRes_ppc64_linux)(                                   \
+         (uc)->uc_mcontext.gp_regs[VKI_PT_R3],                      \
+         (((uc)->uc_mcontext.gp_regs[VKI_PT_CCR] >> 28) & 1)        \
+      )
+#  define VG_UCONTEXT_LINK_REG(uc)        ((uc)->uc_mcontext.gp_regs[VKI_PT_LNK]) 
+
 #else
 #  error Unknown platform
 #endif
@@ -462,6 +475,13 @@
    "	li	0, " #name "\n" \
    "	sc\n" \
    ".previous\n"
+#elif defined(VGP_ppc64_linux)
+#  define _MYSIG(name) \
+   ".text\n" \
+   "my_sigreturn:\n" \
+   "	li	0, " #name "\n" \
+   "	sc\n" \
+   ".previous\n"
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
index fde3a25..63a3b93 100644
--- a/coregrind/m_stacktrace.c
+++ b/coregrind/m_stacktrace.c
@@ -54,7 +54,7 @@
                             Addr ip, Addr sp, Addr fp, Addr lr,
                             Addr fp_min, Addr fp_max_orig )
 {
-#if defined(VGP_ppc32_linux)
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    Bool  lr_is_first_RA = False; /* ppc only */
 #endif
    Bool  debug = False;
@@ -234,7 +234,7 @@
       break;
    }
 
-#  elif defined(VGP_ppc32_linux)
+#  elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
 
    /*--------------------- ppc32 ---------------------*/
 
diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c
index af90517..28a79c0 100644
--- a/coregrind/m_syscall.c
+++ b/coregrind/m_syscall.c
@@ -54,7 +54,7 @@
    syscall returns a value in -1 .. -4095 as a valid result so we can
    safely test with -4095.
 */
-SysRes VG_(mk_SysRes_x86_linux) ( Word val ) {
+SysRes VG_(mk_SysRes_x86_linux) ( UInt val ) {
    SysRes res;
    res.isError = val >= -4095 && val <= -1;
    res.val     = res.isError ? -val : val;
@@ -62,7 +62,7 @@
 }
 
 /* Similarly .. */
-SysRes VG_(mk_SysRes_amd64_linux) ( Word val ) {
+SysRes VG_(mk_SysRes_amd64_linux) ( ULong val ) {
    SysRes res;
    res.isError = val >= -4095 && val <= -1;
    res.val     = res.isError ? -val : val;
@@ -78,6 +78,13 @@
    return res;
 }
 
+SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong errflag ) {
+   SysRes res;
+   res.isError = errflag != 0;
+   res.val     = val;
+   return res;
+}
+
 
 SysRes VG_(mk_SysRes_Error) ( UWord val ) {
    SysRes r = { val, True };
@@ -133,6 +140,7 @@
 "	ret\n"
 ".previous\n"
 );
+
 #elif defined(VGP_amd64_linux)
 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
    %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
@@ -167,6 +175,7 @@
 "	ret\n"
 ".previous\n"
 );
+
 #elif defined(VGP_ppc32_linux)
 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
 
@@ -200,6 +209,36 @@
 "        blr\n"                 /* and return                             */
 ".previous\n"
 );
+
+#elif defined(VGP_ppc64_linux)
+/* Due to the need to return 65 bits of result, this is completely
+   different from the ppc32 case.  The single arg register points to a
+   7-word block containing the syscall # and the 6 args.  The syscall
+   result proper is put in [0] of the block, and %cr0.so is in the
+   bottom but of [1]. */
+extern void do_syscall_WRK ( ULong* argblock );
+asm(
+".text\n"
+".do_syscall_WRK:\n"
+"        std  3,-16(1)\n"  /* stash arg */
+"        ld   8, 48(3)\n"  /* sc arg 6 */
+"        ld   7, 40(3)\n"  /* sc arg 5 */
+"        ld   6, 32(3)\n"  /* sc arg 4 */
+"        ld   5, 24(3)\n"  /* sc arg 3 */
+"        ld   4, 16(3)\n"  /* sc arg 2 */
+"        ld   0,  0(3)\n"  /* sc number */
+"        ld   3,  8(3)\n"  /* sc arg 1 */
+"        sc\n"             /* result in r3 and cr0.so */
+"        ld   5,-16(1)\n"  /* reacquire argblock ptr (r5 is caller-save) */
+"        std  3,0(5)\n"    /* argblock[0] = r3 */
+"        xor  3,3,3\n"
+"        mfcr 3\n"
+"        srwi 3,3,28\n"
+"        andi. 3,3,1\n"
+"        std  3,8(5)\n"    /* argblock[1] = cr0.s0 & 1 */
+"        blr\n"
+".previous\n"
+);
 #else
 #  error Unknown platform
 #endif
@@ -218,6 +257,17 @@
   UInt  val     = (UInt)(ret>>32);
   UInt  cr0so   = (UInt)(ret);
   return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
+#elif defined(VGP_ppc64_linux)
+  ULong argblock[7];
+  argblock[0] = sysno;
+  argblock[1] = a1;
+  argblock[2] = a2;
+  argblock[3] = a3;
+  argblock[4] = a4;
+  argblock[5] = a5;
+  argblock[6] = a6;
+  do_syscall_WRK( &argblock[0] );
+  return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_syswrap/syscall-ppc64-linux.S b/coregrind/m_syswrap/syscall-ppc64-linux.S
new file mode 100644
index 0000000..3d8134f
--- /dev/null
+++ b/coregrind/m_syswrap/syscall-ppc64-linux.S
@@ -0,0 +1,159 @@
+
+##--------------------------------------------------------------------##
+##--- Support for doing system calls.        syscall-ppc64-linux.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, a dynamic binary instrumentation
+  framework.
+
+  Copyright (C) 2005 Paul Mackerras <paulus@samba.org>
+
+  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 2 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, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics_asm.h"
+#include "vki_unistd.h"
+#include "libvex_guest_offsets.h"
+		
+
+/*----------------------------------------------------------------*/
+/*
+        Perform a syscall for the client.  This will run a syscall
+        with the client's specific per-thread signal mask.
+
+        The structure of this function is such that, if the syscall is
+        interrupted by a signal, we can determine exactly what
+        execution state we were in with respect to the execution of
+        the syscall by examining the value of NIP in the signal
+        handler.  This means that we can always do the appropriate
+        thing to precisely emulate the kernel's signal/syscall
+        interactions.
+
+        The syscall number is taken from the argument, even though it
+        should also be in regs->m_gpr[0].  The syscall result is written
+        back to regs->m_gpr[3]/m_xer/m_result on completion.
+
+        Returns 0 if the syscall was successfully called (even if the
+        syscall itself failed), or a -ve error code if one of the
+        sigprocmasks failed (there's no way to determine which one
+        failed).
+
+        VG_(fixup_guest_state_after_syscall_interrupted) does the
+	thread state fixup in the case where we were interrupted by a
+	signal.
+
+        Prototype:
+
+	Int ML_(do_syscall_for_client_WRK)(
+				  Int syscallno,		// r3
+				  void* guest_state,		// r4
+				  const vki_sigset_t *sysmask,	// r5
+				  const vki_sigset_t *postmask,	// r6
+				  Int nsigwords)		// r7
+*/
+/* from vki_arch.h */
+#define VKI_SIG_SETMASK 2
+
+.globl .ML_(do_syscall_for_client_WRK)
+.ML_(do_syscall_for_client_WRK):
+        /* make a stack frame */
+        stdu    1,-64(1)
+        std     31,56(1)
+        std     30,48(1)
+        std     29,40(1)
+        std     28,32(1)
+        mr      31,3            /* syscall number */
+        mr      30,4            /* guest_state */
+        mr      29,6            /* postmask */
+        mr      28,7            /* nsigwords */
+
+        /* set the signal mask for doing the system call */
+        /* set up for sigprocmask(SIG_SETMASK, sysmask, postmask) */
+1:      li      0,__NR_sigprocmask
+        li      3,VKI_SIG_SETMASK
+        mr      4,5
+        mr      5,6
+        sc                      /* set the mask */
+        bso     7f              /* if the sigprocmask fails */
+
+        /* load up syscall args from the threadstate */
+        ld      3,OFFSET_ppc64_GPR3(30)
+        ld      4,OFFSET_ppc64_GPR4(30)
+        ld      5,OFFSET_ppc64_GPR5(30)
+        ld      6,OFFSET_ppc64_GPR6(30)
+        ld      7,OFFSET_ppc64_GPR7(30)
+        ld      8,OFFSET_ppc64_GPR8(30)
+        mr      0,31            /* syscall number */
+2:      sc                      /* do the syscall */
+
+        /* put the result back in the threadstate  */
+3:	std     3,OFFSET_ppc64_GPR3(30)     /* gst->GPR3 = sc result */
+	/* copy cr0.so back to simulated state */
+	mfcr    5                           /* r5 = CR               */
+	rlwinm	5,5,4,31,31                 /* r5 = (CR >> 28) & 1   */
+        stb     5,OFFSET_ppc64_CR0_0(30)    /* gst->CR0.SO = cr0.so  */
+
+        /* block signals again */
+	/* set up for sigprocmask(SIG_SETMASK, postmask, NULL) */
+4:      li      0,__NR_sigprocmask
+        li      3,VKI_SIG_SETMASK
+        mr      4,29
+        li      5,0
+        mr      6,28
+        sc                      /* set the mask */
+        bso     7f              /* if the sigprocmask fails */
+
+        /* now safe from signals */
+
+        /* pop off stack frame */
+5:      ld      28,32(1)
+        ld      29,40(1)
+        ld      30,48(1)
+        ld      31,56(1)
+        addi    1,1,64
+        blr
+
+	/* failure: return -ve error code */
+7:      neg     3,3
+        b       5b
+
+.section .rodata
+/* export the ranges so that
+   VG_(fixup_guest_state_after_syscall_interrupted) can do the
+   right thing */
+
+.globl ML_(blksys_setup)
+.globl ML_(blksys_restart)
+.globl ML_(blksys_complete)
+.globl ML_(blksys_committed)
+.globl ML_(blksys_finished)
+ML_(blksys_setup):     .long 1b
+ML_(blksys_restart):   .long 2b
+ML_(blksys_complete):  .long 3b
+ML_(blksys_committed): .long 4b
+ML_(blksys_finished):  .long 5b
+
+.previous
+		
+/* Let the linker know we don't need an executable stack */
+.section .note.GNU-stack,"",@progbits
+
+##--------------------------------------------------------------------##
+##--- end                                                          ---##
+##--------------------------------------------------------------------##
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index fbaaba9..acfa922 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -3427,7 +3427,7 @@
    case VKI_SOUND_PCM_READ_RATE:
    case VKI_SOUND_PCM_READ_CHANNELS:
    case VKI_SOUND_PCM_READ_BITS:
-#if !defined(VGA_ppc32)
+#if !defined(VGA_ppc32) && !defined(VGA_ppc64)
    case (VKI_SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
 #endif
    case VKI_SOUND_PCM_READ_FILTER:
@@ -4134,7 +4134,7 @@
    case VKI_SOUND_PCM_READ_RATE:
    case VKI_SOUND_PCM_READ_CHANNELS:
    case VKI_SOUND_PCM_READ_BITS:
-#if !defined(VGA_ppc32)
+#if !defined(VGA_ppc32) && !defined(VGA_ppc64)
    case (VKI_SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
 #endif
    case VKI_SOUND_PCM_READ_FILTER:
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index faa6335..866f0c5 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -177,7 +177,7 @@
          "syscall\n"		/* exit(tst->os_state.exitcode) */
          : "=m" (tst->status)
          : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
-#elif defined(VGP_ppc32_linux)
+#elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
       { UInt vgts_empty = (UInt)VgTs_Empty;
         asm volatile (
           "stw %1,%0\n\t"          /* set tst->status = VgTs_Empty */
@@ -304,7 +304,7 @@
 
    /* Since this is the fork() form of clone, we don't need all that
       VG_(clone) stuff */
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    res = VG_(do_syscall5)( __NR_clone, flags, 
                            (UWord)NULL, (UWord)parent_tidptr, 
                            (UWord)NULL, (UWord)child_tidptr );
diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c
index de85593..8251d03 100644
--- a/coregrind/m_syswrap/syswrap-main.c
+++ b/coregrind/m_syswrap/syswrap-main.c
@@ -56,6 +56,7 @@
    x86    eax  ebx   ecx   edx   esi   edi   ebp   eax       (== NUM)
    amd64  rax  rdi   rsi   rdx   r10   r8    r9    rax       (== NUM)
    ppc32  r0   r3    r4    r5    r6    r7    r8    r3+CR0.SO (== ARG1)
+   ppc64  r0   r3    r4    r5    r6    r7    r8    r3+CR0.SO (== ARG1)
 */
 
 /* This is the top level of the system-call handler module.  All
@@ -329,6 +330,16 @@
    canonical->arg5  = gst->guest_GPR7;
    canonical->arg6  = gst->guest_GPR8;
 
+#elif defined(VGP_ppc64_linux)
+   VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
+   canonical->sysno = gst->guest_GPR0;
+   canonical->arg1  = gst->guest_GPR3;
+   canonical->arg2  = gst->guest_GPR4;
+   canonical->arg3  = gst->guest_GPR5;
+   canonical->arg4  = gst->guest_GPR6;
+   canonical->arg5  = gst->guest_GPR7;
+   canonical->arg6  = gst->guest_GPR8;
+
 #else
 #  error "getSyscallArgsFromGuestState: unknown arch"
 #endif
@@ -368,6 +379,16 @@
    gst->guest_GPR7 = canonical->arg5;
    gst->guest_GPR8 = canonical->arg6;
 
+#elif defined(VGP_ppc64_linux)
+   VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
+   gst->guest_GPR0 = canonical->sysno;
+   gst->guest_GPR3 = canonical->arg1;
+   gst->guest_GPR4 = canonical->arg2;
+   gst->guest_GPR5 = canonical->arg3;
+   gst->guest_GPR6 = canonical->arg4;
+   gst->guest_GPR7 = canonical->arg5;
+   gst->guest_GPR8 = canonical->arg6;
+
 #else
 #  error "putSyscallArgsIntoGuestState: unknown arch"
 #endif
@@ -396,6 +417,13 @@
    canonical->what = (err == 1)  ? SsFailure  : SsSuccess;
    canonical->val  = (UWord)gst->guest_GPR3;
 
+#elif defined(VGP_ppc64_linux)
+   VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
+   UInt                cr  = LibVEX_GuestPPC64_get_CR( gst );
+   UInt                err = (cr >> 28) & 1;  // CR0.SO
+   canonical->what = (err == 1)  ? SsFailure  : SsSuccess;
+   canonical->val  = (UWord)gst->guest_GPR3;
+
 #else
 #  error "getSyscallStatusFromGuestState: unknown arch"
 #endif
@@ -447,6 +475,23 @@
       LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), gst );
    }
 
+#elif defined(VGP_ppc64_linux)
+   VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
+   UInt old_cr = LibVEX_GuestPPC64_get_CR(gst);
+
+   vg_assert(canonical->what == SsSuccess 
+             || canonical->what == SsFailure);
+
+   gst->guest_GPR3 = canonical->val;
+
+   if (canonical->what == SsFailure) {
+      /* set CR0.SO */
+      LibVEX_GuestPPC64_put_CR( old_cr | (1<<28), gst );
+   } else {
+      /* clear CR0.SO */
+      LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), gst );
+   }
+
 #else
 #  error "putSyscallStatusIntoGuestState: unknown arch"
 #endif
@@ -490,6 +535,16 @@
    layout->o_arg6   = OFFSET_ppc32_GPR8;
    layout->o_retval = OFFSET_ppc32_GPR3;
 
+#elif defined(VGP_ppc64_linux)
+   layout->o_sysno  = OFFSET_ppc64_GPR0;
+   layout->o_arg1   = OFFSET_ppc64_GPR3;
+   layout->o_arg2   = OFFSET_ppc64_GPR4;
+   layout->o_arg3   = OFFSET_ppc64_GPR5;
+   layout->o_arg4   = OFFSET_ppc64_GPR6;
+   layout->o_arg5   = OFFSET_ppc64_GPR7;
+   layout->o_arg6   = OFFSET_ppc64_GPR8;
+   layout->o_retval = OFFSET_ppc64_GPR3;
+
 #else
 #  error "getSyscallLayout: unknown arch"
 #endif
@@ -981,7 +1036,7 @@
       vg_assert(p[0] == 0x0F && p[1] == 0x05);
    }
 
-#elif defined(VGP_ppc32_linux)
+#elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
    arch->vex.guest_CIA -= 4;             // sizeof(ppc32 instr)
 
    /* Make sure our caller is actually sane, and we're really backing
diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c
new file mode 100644
index 0000000..017bc27
--- /dev/null
+++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c
@@ -0,0 +1,1495 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Platform-specific syscalls stuff.      syswrap-ppc64-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2005 Nicholas Nethercote <njn@valgrind.org>
+   Copyright (C) 2005 Cerion Armour-Brown <cerion@open-works.co.uk>
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_debuglog.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_libcproc.h"
+#include "pub_core_libcsignal.h"
+#include "pub_core_options.h"
+#include "pub_core_scheduler.h"
+#include "pub_core_sigframe.h"      // For VG_(sigframe_destroy)()
+#include "pub_core_signals.h"
+#include "pub_core_syscall.h"
+#include "pub_core_syswrap.h"
+#include "pub_core_tooliface.h"
+
+#include "priv_types_n_macros.h"
+#include "priv_syswrap-generic.h"   /* for decls of generic wrappers */
+#include "priv_syswrap-linux.h"     /* for decls of linux-ish wrappers */
+#include "priv_syswrap-main.h"
+
+#include "vki_unistd.h"              /* for the __NR_* constants */
+
+
+/* ---------------------------------------------------------------------
+   clone() handling
+   ------------------------------------------------------------------ */
+
+/* Call f(arg1), but first switch stacks, using 'stack' as the new
+   stack, and use 'retaddr' as f's return-to address.  Also, clear all
+   the integer registers before entering f.*/
+__attribute__((noreturn))
+void ML_(call_on_new_stack_0_1) ( Addr stack,
+                                  Addr retaddr,
+                                  void (*f)(Word),
+                                  Word arg1 );
+//    r3 = stack
+//    r4 = retaddr
+//    r5 = f
+//    r6 = arg1
+asm(
+".text\n"
+".globl .vgModuleLocal_call_on_new_stack_0_1\n"
+".vgModuleLocal_call_on_new_stack_0_1:\n"
+"   mr    %r1,%r3\n\t"     // stack to %sp
+"   mtlr  %r4\n\t"         // retaddr to %lr
+"   mtctr %r5\n\t"         // f to count reg
+"   mr %r3,%r6\n\t"        // arg1 to %r3
+"   li 0,0\n\t"            // zero all GP regs
+"   li 4,0\n\t"
+"   li 5,0\n\t"
+"   li 6,0\n\t"
+"   li 7,0\n\t"
+"   li 8,0\n\t"
+"   li 9,0\n\t"
+"   li 10,0\n\t"
+"   li 11,0\n\t"
+"   li 12,0\n\t"
+"   li 13,0\n\t"
+"   li 14,0\n\t"
+"   li 15,0\n\t"
+"   li 16,0\n\t"
+"   li 17,0\n\t"
+"   li 18,0\n\t"
+"   li 19,0\n\t"
+"   li 20,0\n\t"
+"   li 21,0\n\t"
+"   li 22,0\n\t"
+"   li 23,0\n\t"
+"   li 24,0\n\t"
+"   li 25,0\n\t"
+"   li 26,0\n\t"
+"   li 27,0\n\t"
+"   li 28,0\n\t"
+"   li 29,0\n\t"
+"   li 30,0\n\t"
+"   li 31,0\n\t"
+"   mtxer 0\n\t"           // CAB: Need this?
+"   mtcr 0\n\t"            // CAB: Need this?
+"   bctr\n\t"              // jump to dst
+"   trap\n"                // should never get here
+".previous\n"
+);
+
+
+/*
+        Perform a clone system call.  clone is strange because it has
+        fork()-like return-twice semantics, so it needs special
+        handling here.
+
+        Upon entry, we have:
+
+            word (fn)(void*)    in r3
+            void* child_stack   in r4
+            word flags          in r5
+            void* arg           in r6
+            pid_t* child_tid    in r7
+            pid_t* parent_tid   in r8
+            void* ???           in r9
+
+        System call requires:
+
+            int    $__NR_clone  in r0  (sc number)
+            int    flags        in r3  (sc arg1)
+            void*  child_stack  in r4  (sc arg2)
+            pid_t* parent_tid   in r5  (sc arg3)
+            ??     child_tls    in r6  (sc arg4)
+            pid_t* child_tid    in r7  (sc arg5)
+            void*  ???          in r8  (sc arg6)
+
+        Returns a ULong encoded as: top half is %cr following syscall,
+        low half is syscall return value (r3).
+ */
+#define __NR_CLONE        VG_STRINGIFY(__NR_clone)
+#define __NR_EXIT         VG_STRINGIFY(__NR_exit)
+
+extern
+ULong do_syscall_clone_ppc64_linux ( Word (*fn)(void *), 
+                                     void* stack, 
+                                     Int   flags, 
+                                     void* arg,
+                                     Int*  child_tid, 
+                                     Int*  parent_tid, 
+                                     void/*vki_modify_ldt_t*/ * );
+asm(
+".text\n"
+".do_syscall_clone_ppc64_linux:\n"
+"       stdu    1,-64(1)\n"
+"       std     29,40(1)\n"
+"       std     30,48(1)\n"
+"       std     31,56(1)\n"
+"       mr      30,3\n"              // preserve fn
+"       mr      31,6\n"              // preserve arg
+
+        // setup child stack
+"       rlwinm  4,4,0,~0xf\n"        // trim sp to multiple of 16 bytes
+"       li      0,0\n"
+"       stdu    0,-32(4)\n"          // make initial stack frame
+"       mr      29,4\n"              // preserve sp
+
+        // setup syscall
+"       li      0,"__NR_CLONE"\n"    // syscall number
+"       mr      3,5\n"               // syscall arg1: flags
+        // r4 already setup          // syscall arg2: child_stack
+"       mr      5,8\n"               // syscall arg3: parent_tid
+"       mr      6,2\n"               // syscall arg4: REAL THREAD tls
+"       mr      7,7\n"               // syscall arg5: child_tid
+"       mr      8,8\n"               // syscall arg6: ????
+"       mr      9,9\n"               // syscall arg7: ????
+
+"       sc\n"                        // clone()
+
+"       mfcr    4\n"                 // CR now in low half r4
+"       slwi    4,4,16\n"
+"       slwi    4,4,16\n"            // CR now in hi half r4
+
+"       slwi    3,3,16\n"
+"       slwi    3,3,16\n"
+"       srwi    3,3,16\n"
+"       srwi    3,3,16\n"            // zero out hi half r3
+
+"       and     3,3,4\n"             // r3 = CR : syscall-retval
+"       cmpwi   3,0\n"               // child if retval == 0 (note, cmpw)
+"       bne     1f\n"                // jump if !child
+
+        /* CHILD - call thread function */
+        /* Note: 2.4 kernel doesn't set the child stack pointer,
+           so we do it here.
+           That does leave a small window for a signal to be delivered
+           on the wrong stack, unfortunately. */
+"       mr      1,29\n"
+"       mtctr   30\n"                // ctr reg = fn
+"       mr      3,31\n"              // r3 = arg
+"       bctrl\n"                     // call fn()
+
+        // exit with result
+"       li      0,"__NR_EXIT"\n"
+"       sc\n"
+
+        // Exit returned?!
+"       .long   0\n"
+
+        // PARENT or ERROR - return
+"1:     ld      29,40(1)\n"
+"       ld      30,48(1)\n"
+"       ld      31,56(1)\n"
+"       addi    1,1,64\n"
+"       blr\n"
+".previous\n"
+);
+
+#undef __NR_CLONE
+#undef __NR_EXIT
+
+// forward declarations
+static void setup_child ( ThreadArchState*, ThreadArchState* );
+
+/* 
+   When a client clones, we need to keep track of the new thread.  This means:
+   1. allocate a ThreadId+ThreadState+stack for the the thread
+
+   2. initialize the thread's new VCPU state
+
+   3. create the thread using the same args as the client requested,
+   but using the scheduler entrypoint for IP, and a separate stack
+   for SP.
+ */
+static SysRes do_clone ( ThreadId ptid, 
+                         UInt flags, Addr sp, 
+                         Int *parent_tidptr, 
+                         Int *child_tidptr, 
+                         Addr child_tls)
+{
+   const Bool debug = False;
+
+   ThreadId     ctid = VG_(alloc_ThreadState)();
+   ThreadState* ptst = VG_(get_ThreadState)(ptid);
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
+   ULong        word64;
+   UWord*       stack;
+   NSegment*    seg;
+   SysRes       res;
+   vki_sigset_t blockall, savedmask;
+
+   VG_(sigfillset)(&blockall);
+
+   vg_assert(VG_(is_running_thread)(ptid));
+   vg_assert(VG_(is_valid_tid)(ctid));
+
+   stack = (UWord*)ML_(allocstack)(ctid);
+   if (stack == NULL) {
+      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
+      goto out;
+   }
+
+//?   /* make a stack frame */
+//?   stack -= 16;
+//?   *(UWord *)stack = 0;
+
+
+   /* Copy register state
+
+      Both parent and child return to the same place, and the code
+      following the clone syscall works out which is which, so we
+      don't need to worry about it.
+
+      The parent gets the child's new tid returned from clone, but the
+      child gets 0.
+
+      If the clone call specifies a NULL SP for the new thread, then
+      it actually gets a copy of the parent's SP.
+
+      The child's TLS register (r2) gets set to the tlsaddr argument
+      if the CLONE_SETTLS flag is set.
+   */
+   setup_child( &ctst->arch, &ptst->arch );
+
+   /* Make sys_clone appear to have returned Success(0) in the
+      child. */
+   { UInt old_cr = LibVEX_GuestPPC64_get_CR( &ctst->arch.vex );
+     /* %r3 = 0 */
+     ctst->arch.vex.guest_GPR3 = 0;
+     /* %cr0.so = 0 */
+     LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
+   }
+
+   if (sp != 0)
+      ctst->arch.vex.guest_GPR1 = sp;
+
+   ctst->os_state.parent = ptid;
+
+   /* inherit signal mask */
+   ctst->sig_mask = ptst->sig_mask;
+   ctst->tmp_sig_mask = ptst->sig_mask;
+
+   /* We don't really know where the client stack is, because its
+      allocated by the client.  The best we can do is look at the
+      memory mappings and try to derive some useful information.  We
+      assume that esp starts near its highest possible value, and can
+      only go down to the start of the mmaped segment. */
+   seg = VG_(am_find_nsegment)(sp);
+   if (seg && seg->kind != SkResvn) {
+      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
+      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
+
+      if (debug)
+	 VG_(printf)("\ntid %d: guessed client stack range %p-%p\n",
+		     ctid, seg->start, VG_PGROUNDUP(sp));
+   } else {
+      VG_(message)(Vg_UserMsg, "!? New thread %d starts with R1(%p) unmapped\n",
+		   ctid, sp);
+      ctst->client_stack_szB  = 0;
+   }
+
+   if (flags & VKI_CLONE_SETTLS) {
+      if (debug)
+         VG_(printf)("clone child has SETTLS: tls at %p\n", child_tls);
+      ctst->arch.vex.guest_GPR13 = child_tls;
+   }
+
+   flags &= ~VKI_CLONE_SETTLS;
+
+   /* start the thread with everything blocked */
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+   /* Create the new thread */
+   word64 = do_syscall_clone_ppc64_linux(
+               ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
+               child_tidptr, parent_tidptr, NULL
+            );
+   /* Low half word64 is syscall return value.  Hi half is
+      the entire CR, from which we need to extract CR0.SO. */
+   /* VG_(printf)("word64 = 0x%llx\n", word64); */
+   res = VG_(mk_SysRes_ppc32_linux)( 
+            /*val*/(UInt)(word64 & 0xFFFFFFFFULL), 
+            /*errflag*/ (UInt)((word64 >> (32+28)) & 1)
+         );
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+  out:
+   if (res.isError) {
+      /* clone failed */
+      VG_(cleanup_thread)(&ctst->arch);
+      ctst->status = VgTs_Empty;
+   }
+
+   return res;
+}
+
+
+
+/* ---------------------------------------------------------------------
+   More thread stuff
+   ------------------------------------------------------------------ */
+
+void VG_(cleanup_thread) ( ThreadArchState* arch )
+{
+}  
+
+void setup_child ( /*OUT*/ ThreadArchState *child,
+                   /*IN*/  ThreadArchState *parent )
+{
+   /* We inherit our parent's guest state. */
+   child->vex = parent->vex;
+   child->vex_shadow = parent->vex_shadow;
+}
+
+
+/* ---------------------------------------------------------------------
+   PRE/POST wrappers for ppc64/Linux-specific syscalls
+   ------------------------------------------------------------------ */
+
+#define PRE(name)       DEFN_PRE_TEMPLATE(ppc32_linux, name)
+#define POST(name)      DEFN_POST_TEMPLATE(ppc32_linux, name)
+
+/* Add prototypes for the wrappers declared here, so that gcc doesn't
+   harass us for not having prototypes.  Really this is a kludge --
+   the right thing to do is to make these wrappers 'static' since they
+   aren't visible outside this file, but that requires even more macro
+   magic. */
+
+//zz DECL_TEMPLATE(ppc64_linux, sys_socketcall);
+//zz DECL_TEMPLATE(ppc64_linux, sys_mmap);
+//zz DECL_TEMPLATE(ppc64_linux, sys_mmap2);
+//zz DECL_TEMPLATE(ppc64_linux, sys_stat64);
+//zz DECL_TEMPLATE(ppc64_linux, sys_lstat64);
+//zz DECL_TEMPLATE(ppc64_linux, sys_fstat64);
+//zz DECL_TEMPLATE(ppc64_linux, sys_ipc);
+//zz DECL_TEMPLATE(ppc64_linux, sys_clone);
+//zz DECL_TEMPLATE(ppc64_linux, sys_sigreturn);
+//zz DECL_TEMPLATE(ppc64_linux, sys_rt_sigreturn);
+//zz DECL_TEMPLATE(ppc64_linux, sys_sigaction);
+//zz 
+//zz PRE(sys_socketcall)
+//zz {
+//zz #  define ARG2_0  (((UWord*)ARG2)[0])
+//zz #  define ARG2_1  (((UWord*)ARG2)[1])
+//zz #  define ARG2_2  (((UWord*)ARG2)[2])
+//zz #  define ARG2_3  (((UWord*)ARG2)[3])
+//zz #  define ARG2_4  (((UWord*)ARG2)[4])
+//zz #  define ARG2_5  (((UWord*)ARG2)[5])
+//zz 
+//zz    *flags |= SfMayBlock;
+//zz    PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2);
+//zz    PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
+//zz 
+//zz    switch (ARG1 /* request */) {
+//zz 
+//zz    case VKI_SYS_SOCKETPAIR:
+//zz      /* int socketpair(int d, int type, int protocol, int sv[2]); */
+//zz       PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
+//zz       ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
+//zz       break;
+//zz 
+//zz    case VKI_SYS_SOCKET:
+//zz      /* int socket(int domain, int type, int protocol); */
+//zz       PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
+//zz       break;
+//zz 
+//zz    case VKI_SYS_BIND:
+//zz      /* int bind(int sockfd, struct sockaddr *my_addr,
+//zz 	int addrlen); */
+//zz       PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
+//zz       ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
+//zz       break;
+//zz 
+//zz    case VKI_SYS_LISTEN:
+//zz      /* int listen(int s, int backlog); */
+//zz       PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
+//zz       break;
+//zz 
+//zz    case VKI_SYS_ACCEPT: {
+//zz      /* int accept(int s, struct sockaddr *addr, int *addrlen); */
+//zz       PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
+//zz       ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
+//zz       break;
+//zz    }
+//zz 
+//zz    case VKI_SYS_SENDTO:
+//zz      /* int sendto(int s, const void *msg, int len,
+//zz                     unsigned int flags,
+//zz                     const struct sockaddr *to, int tolen); */
+//zz      PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
+//zz 				  ARG2_3, ARG2_4, ARG2_5 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_SEND:
+//zz      /* int send(int s, const void *msg, size_t len, int flags); */
+//zz      PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_RECVFROM:
+//zz      /* int recvfrom(int s, void *buf, int len, unsigned int flags,
+//zz 	struct sockaddr *from, int *fromlen); */
+//zz      PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
+//zz 				    ARG2_3, ARG2_4, ARG2_5 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_RECV:
+//zz      /* int recv(int s, void *buf, int len, unsigned int flags); */
+//zz      /* man 2 recv says:
+//zz          The  recv call is normally used only on a connected socket
+//zz          (see connect(2)) and is identical to recvfrom with a  NULL
+//zz          from parameter.
+//zz      */
+//zz      PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_CONNECT:
+//zz      /* int connect(int sockfd,
+//zz 	struct sockaddr *serv_addr, int addrlen ); */
+//zz      PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_SETSOCKOPT:
+//zz      /* int setsockopt(int s, int level, int optname,
+//zz 	const void *optval, int optlen); */
+//zz      PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
+//zz 				      ARG2_3, ARG2_4 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_GETSOCKOPT:
+//zz      /* int getsockopt(int s, int level, int optname,
+//zz 	void *optval, socklen_t *optlen); */
+//zz      PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
+//zz 				      ARG2_3, ARG2_4 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_GETSOCKNAME:
+//zz      /* int getsockname(int s, struct sockaddr* name, int* namelen) */
+//zz      PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_GETPEERNAME:
+//zz      /* int getpeername(int s, struct sockaddr* name, int* namelen) */
+//zz      PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
+//zz      ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_SHUTDOWN:
+//zz      /* int shutdown(int s, int how); */
+//zz      PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
+//zz      break;
+//zz 
+//zz    case VKI_SYS_SENDMSG: {
+//zz      /* int sendmsg(int s, const struct msghdr *msg, int flags); */
+//zz 
+//zz      /* this causes warnings, and I don't get why. glibc bug?
+//zz       * (after all it's glibc providing the arguments array)
+//zz        PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
+//zz      */
+//zz      ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
+//zz      break;
+//zz    }
+//zz 
+//zz    case VKI_SYS_RECVMSG: {
+//zz      /* int recvmsg(int s, struct msghdr *msg, int flags); */
+//zz 
+//zz      /* this causes warnings, and I don't get why. glibc bug?
+//zz       * (after all it's glibc providing the arguments array)
+//zz        PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
+//zz      */
+//zz      ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
+//zz      break;
+//zz    }
+//zz 
+//zz    default:
+//zz      VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1);
+//zz      SET_STATUS_Failure( VKI_EINVAL );
+//zz      break;
+//zz    }
+//zz #  undef ARG2_0
+//zz #  undef ARG2_1
+//zz #  undef ARG2_2
+//zz #  undef ARG2_3
+//zz #  undef ARG2_4
+//zz #  undef ARG2_5
+//zz }
+//zz 
+//zz POST(sys_socketcall)
+//zz {
+//zz #  define ARG2_0  (((UWord*)ARG2)[0])
+//zz #  define ARG2_1  (((UWord*)ARG2)[1])
+//zz #  define ARG2_2  (((UWord*)ARG2)[2])
+//zz #  define ARG2_3  (((UWord*)ARG2)[3])
+//zz #  define ARG2_4  (((UWord*)ARG2)[4])
+//zz #  define ARG2_5  (((UWord*)ARG2)[5])
+//zz 
+//zz   SysRes r;
+//zz   vg_assert(SUCCESS);
+//zz   switch (ARG1 /* request */) {
+//zz 
+//zz   case VKI_SYS_SOCKETPAIR:
+//zz     r = ML_(generic_POST_sys_socketpair)(
+//zz 					 tid, VG_(mk_SysRes_Success)(RES),
+//zz 					 ARG2_0, ARG2_1, ARG2_2, ARG2_3
+//zz 					 );
+//zz     SET_STATUS_from_SysRes(r);
+//zz     break;
+//zz 
+//zz   case VKI_SYS_SOCKET:
+//zz     r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
+//zz     SET_STATUS_from_SysRes(r);
+//zz     break;
+//zz 
+//zz   case VKI_SYS_BIND:
+//zz     /* int bind(int sockfd, struct sockaddr *my_addr,
+//zz        int addrlen); */
+//zz     break;
+//zz 
+//zz   case VKI_SYS_LISTEN:
+//zz     /* int listen(int s, int backlog); */
+//zz     break;
+//zz 
+//zz   case VKI_SYS_ACCEPT:
+//zz     /* int accept(int s, struct sockaddr *addr, int *addrlen); */
+//zz     r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
+//zz 				      ARG2_0, ARG2_1, ARG2_2 );
+//zz     SET_STATUS_from_SysRes(r);
+//zz     break;
+//zz 
+//zz   case VKI_SYS_SENDTO:
+//zz     break;
+//zz 
+//zz   case VKI_SYS_SEND:
+//zz     break;
+//zz 
+//zz   case VKI_SYS_RECVFROM:
+//zz     ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
+//zz 				    ARG2_0, ARG2_1, ARG2_2,
+//zz 				    ARG2_3, ARG2_4, ARG2_5 );
+//zz     break;
+//zz 
+//zz   case VKI_SYS_RECV:
+//zz     ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
+//zz     break;
+//zz 
+//zz   case VKI_SYS_CONNECT:
+//zz     break;
+//zz 
+//zz   case VKI_SYS_SETSOCKOPT:
+//zz     break;
+//zz 
+//zz   case VKI_SYS_GETSOCKOPT:
+//zz     ML_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
+//zz 				      ARG2_0, ARG2_1,
+//zz 				      ARG2_2, ARG2_3, ARG2_4 );
+//zz     break;
+//zz 
+//zz   case VKI_SYS_GETSOCKNAME:
+//zz     ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
+//zz 				       ARG2_0, ARG2_1, ARG2_2 );
+//zz     break;
+//zz 
+//zz   case VKI_SYS_GETPEERNAME:
+//zz     ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
+//zz 				       ARG2_0, ARG2_1, ARG2_2 );
+//zz     break;
+//zz 
+//zz   case VKI_SYS_SHUTDOWN:
+//zz     break;
+//zz 
+//zz   case VKI_SYS_SENDMSG:
+//zz     break;
+//zz 
+//zz   case VKI_SYS_RECVMSG:
+//zz     ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
+//zz     break;
+//zz 
+//zz   default:
+//zz     VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1);
+//zz     VG_(core_panic)("... bye!\n");
+//zz     break; /*NOTREACHED*/
+//zz   }
+//zz #  undef ARG2_0
+//zz #  undef ARG2_1
+//zz #  undef ARG2_2
+//zz #  undef ARG2_3
+//zz #  undef ARG2_4
+//zz #  undef ARG2_5
+//zz }
+//zz 
+//zz PRE(sys_mmap)
+//zz {
+//zz    SysRes r;
+//zz 
+//zz    PRINT("sys_mmap ( %p, %llu, %d, %d, %d, %d )",
+//zz          ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
+//zz    PRE_REG_READ6(long, "mmap",
+//zz                  unsigned long, start, unsigned long, length,
+//zz                  unsigned long, prot,  unsigned long, flags,
+//zz                  unsigned long, fd,    unsigned long, offset);
+//zz 
+//zz    r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, 
+//zz                                        (Off64T)ARG6 );
+//zz    SET_STATUS_from_SysRes(r);
+//zz }
+//zz 
+//zz PRE(sys_mmap2)
+//zz {
+//zz    SysRes r;
+//zz 
+//zz    // Exactly like old_mmap() except:
+//zz    //  - the file offset is specified in pagesize units rather than bytes,
+//zz    //    so that it can be used for files bigger than 2^32 bytes.
+//zz    PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
+//zz          ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
+//zz    PRE_REG_READ6(long, "mmap2",
+//zz                  unsigned long, start, unsigned long, length,
+//zz                  unsigned long, prot,  unsigned long, flags,
+//zz                  unsigned long, fd,    unsigned long, offset);
+//zz 
+//zz    r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, 
+//zz                                        VKI_PAGE_SIZE * (Off64T)ARG6 );
+//zz    SET_STATUS_from_SysRes(r);
+//zz }
+//zz 
+//zz // XXX: lstat64/fstat64/stat64 are generic, but not necessarily
+//zz // applicable to every architecture -- I think only to 32-bit archs.
+//zz // We're going to need something like linux/core_os32.h for such
+//zz // things, eventually, I think.  --njn
+//zz PRE(sys_stat64)
+//zz {
+//zz    PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2);
+//zz    PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
+//zz    PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
+//zz    PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
+//zz }
+//zz 
+//zz POST(sys_stat64)
+//zz {
+//zz    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
+//zz }
+//zz 
+//zz PRE(sys_lstat64)
+//zz {
+//zz    PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
+//zz    PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
+//zz    PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
+//zz    PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
+//zz }
+//zz 
+//zz POST(sys_lstat64)
+//zz {
+//zz    vg_assert(SUCCESS);
+//zz    if (RES == 0) {
+//zz       POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
+//zz    }
+//zz }
+//zz 
+//zz PRE(sys_fstat64)
+//zz {
+//zz   PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
+//zz   PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
+//zz   PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
+//zz }
+//zz 
+//zz POST(sys_fstat64)
+//zz {
+//zz   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
+//zz }
+//zz 
+//zz static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
+//zz {
+//zz    Addr* a_p = (Addr*)a;
+//zz    PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
+//zz    return *a_p;
+//zz }
+//zz 
+//zz PRE(sys_ipc)
+//zz {
+//zz   PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+//zz   // XXX: this is simplistic -- some args are not used in all circumstances.
+//zz   PRE_REG_READ6(int, "ipc",
+//zz 		vki_uint, call, int, first, int, second, int, third,
+//zz 		void *, ptr, long, fifth)
+//zz 
+//zz     switch (ARG1 /* call */) {
+//zz     case VKI_SEMOP:
+//zz       ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
+//zz       *flags |= SfMayBlock;
+//zz       break;
+//zz     case VKI_SEMGET:
+//zz       break;
+//zz     case VKI_SEMCTL:
+//zz       {
+//zz 	UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
+//zz 	ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
+//zz 	break;
+//zz       }
+//zz     case VKI_SEMTIMEDOP:
+//zz       ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
+//zz       *flags |= SfMayBlock;
+//zz       break;
+//zz     case VKI_MSGSND:
+//zz       ML_(linux_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
+//zz       if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+//zz 	*flags |= SfMayBlock;
+//zz       break;
+//zz     case VKI_MSGRCV:
+//zz       {
+//zz 	Addr msgp;
+//zz 	Word msgtyp;
+//zz 
+//zz 	msgp = deref_Addr( tid,
+//zz 			   (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
+//zz 			   "msgrcv(msgp)" );
+//zz 	msgtyp = deref_Addr( tid,
+//zz 			     (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
+//zz 			     "msgrcv(msgp)" );
+//zz 
+//zz 	ML_(linux_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
+//zz 
+//zz 	if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+//zz 	  *flags |= SfMayBlock;
+//zz 	break;
+//zz       }
+//zz     case VKI_MSGGET:
+//zz       break;
+//zz     case VKI_MSGCTL:
+//zz       ML_(linux_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
+//zz       break;
+//zz     case VKI_SHMAT:
+//zz       {
+//zz 	UWord w;
+//zz 	PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
+//zz 	w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
+//zz 	if (w == 0)
+//zz 	  SET_STATUS_Failure( VKI_EINVAL );
+//zz 	else
+//zz 	  ARG5 = w;
+//zz 	break;
+//zz       }
+//zz     case VKI_SHMDT:
+//zz       if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
+//zz 	SET_STATUS_Failure( VKI_EINVAL );
+//zz       break;
+//zz     case VKI_SHMGET:
+//zz       break;
+//zz     case VKI_SHMCTL: /* IPCOP_shmctl */
+//zz       ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
+//zz       break;
+//zz     default:
+//zz       VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
+//zz       VG_(core_panic)("... bye!\n");
+//zz       break; /*NOTREACHED*/
+//zz     }
+//zz }
+//zz 
+//zz POST(sys_ipc)
+//zz {
+//zz   vg_assert(SUCCESS);
+//zz   switch (ARG1 /* call */) {
+//zz   case VKI_SEMOP:
+//zz   case VKI_SEMGET:
+//zz     break;
+//zz   case VKI_SEMCTL:
+//zz     {
+//zz       UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
+//zz       ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
+//zz       break;
+//zz     }
+//zz   case VKI_SEMTIMEDOP:
+//zz   case VKI_MSGSND:
+//zz     break;
+//zz   case VKI_MSGRCV:
+//zz     {
+//zz       Addr msgp;
+//zz       Word msgtyp;
+//zz 
+//zz       msgp = deref_Addr( tid,
+//zz                          (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
+//zz                          "msgrcv(msgp)" );
+//zz       msgtyp = deref_Addr( tid,
+//zz                            (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
+//zz                            "msgrcv(msgp)" );
+//zz 
+//zz       ML_(linux_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
+//zz       break;
+//zz     }
+//zz   case VKI_MSGGET:
+//zz     break;
+//zz   case VKI_MSGCTL:
+//zz     ML_(linux_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
+//zz     break;
+//zz   case VKI_SHMAT:
+//zz     {
+//zz       Addr addr;
+//zz 
+//zz       /* force readability. before the syscall it is
+//zz        * indeed uninitialized, as can be seen in
+//zz        * glibc/sysdeps/unix/sysv/linux/shmat.c */
+//zz       POST_MEM_WRITE( ARG4, sizeof( Addr ) );
+//zz 
+//zz       addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
+//zz       if ( addr > 0 ) {
+//zz 	ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
+//zz       }
+//zz       break;
+//zz     }
+//zz   case VKI_SHMDT:
+//zz     ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
+//zz     break;
+//zz   case VKI_SHMGET:
+//zz     break;
+//zz   case VKI_SHMCTL:
+//zz     ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
+//zz     break;
+//zz   default:
+//zz     VG_(message)(Vg_DebugMsg,
+//zz 		 "FATAL: unhandled syscall(ipc) %d",
+//zz 		 ARG1 );
+//zz     VG_(core_panic)("... bye!\n");
+//zz     break; /*NOTREACHED*/
+//zz   }
+//zz }
+//zz 
+//zz PRE(sys_clone)
+//zz {
+//zz    UInt cloneflags;
+//zz 
+//zz    PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
+//zz    PRE_REG_READ5(int, "clone",
+//zz                  unsigned long, flags,
+//zz                  void *,        child_stack,
+//zz                  int *,         parent_tidptr,
+//zz                  void *,        child_tls,
+//zz                  int *,         child_tidptr);
+//zz 
+//zz    if (ARG1 & VKI_CLONE_PARENT_SETTID) {
+//zz       PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
+//zz       if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), 
+//zz                                              VKI_PROT_WRITE)) {
+//zz          SET_STATUS_Failure( VKI_EFAULT );
+//zz          return;
+//zz       }
+//zz    }
+//zz    if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
+//zz       PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
+//zz       if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), 
+//zz                                              VKI_PROT_WRITE)) {
+//zz          SET_STATUS_Failure( VKI_EFAULT );
+//zz          return;
+//zz       }
+//zz    }
+//zz 
+//zz    cloneflags = ARG1;
+//zz 
+//zz    if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
+//zz       SET_STATUS_Failure( VKI_EINVAL );
+//zz       return;
+//zz    }
+//zz 
+//zz    /* Only look at the flags we really care about */
+//zz    switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
+//zz                          | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
+//zz    case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
+//zz       /* thread creation */
+//zz       SET_STATUS_from_SysRes(
+//zz          do_clone(tid,
+//zz                   ARG1,         /* flags */
+//zz                   (Addr)ARG2,   /* child SP */
+//zz                   (Int *)ARG3,  /* parent_tidptr */
+//zz                   (Int *)ARG5,  /* child_tidptr */
+//zz                   (Addr)ARG4)); /* child_tls */
+//zz       break;
+//zz 
+//zz    case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
+//zz       /* FALLTHROUGH - assume vfork == fork */
+//zz       cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
+//zz 
+//zz    case 0: /* plain fork */
+//zz       SET_STATUS_from_SysRes(
+//zz          ML_(do_fork_clone)(tid,
+//zz                        cloneflags,      /* flags */
+//zz                        (Int *)ARG3,     /* parent_tidptr */
+//zz                        (Int *)ARG5));   /* child_tidptr */
+//zz       break;
+//zz 
+//zz    default:
+//zz       /* should we just ENOSYS? */
+//zz       VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
+//zz       VG_(message)(Vg_UserMsg, "");
+//zz       VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
+//zz       VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
+//zz       VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
+//zz       VG_(unimplemented)
+//zz          ("Valgrind does not support general clone().");
+//zz    }
+//zz 
+//zz    if (SUCCESS) {
+//zz       if (ARG1 & VKI_CLONE_PARENT_SETTID)
+//zz          POST_MEM_WRITE(ARG3, sizeof(Int));
+//zz       if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
+//zz          POST_MEM_WRITE(ARG5, sizeof(Int));
+//zz 
+//zz       /* Thread creation was successful; let the child have the chance
+//zz          to run */
+//zz       *flags |= SfYieldAfter;
+//zz    }
+//zz }
+//zz 
+//zz PRE(sys_sigreturn)
+//zz {
+//zz    ThreadState* tst;
+//zz    PRINT("sigreturn ( )");
+//zz 
+//zz    vg_assert(VG_(is_valid_tid)(tid));
+//zz    vg_assert(tid >= 1 && tid < VG_N_THREADS);
+//zz    vg_assert(VG_(is_running_thread)(tid));
+//zz 
+//zz    ///* Adjust esp to point to start of frame; skip back up over
+//zz    //   sigreturn sequence's "popl %eax" and handler ret addr */
+//zz    tst = VG_(get_ThreadState)(tid);
+//zz    //tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
+//zz    // Should we do something equivalent on ppc64?  Who knows.
+//zz 
+//zz    ///* This is only so that the EIP is (might be) useful to report if
+//zz    //   something goes wrong in the sigreturn */
+//zz    //ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+//zz    // Should we do something equivalent on ppc64?  Who knows.
+//zz 
+//zz    VG_(sigframe_destroy)(tid, False);
+//zz 
+//zz    /* For unclear reasons, it appears we need the syscall to return
+//zz       without changing R3.  Since R3 is the return value, and can
+//zz       denote either success or failure, we must set up so that the
+//zz       driver logic copies it back unchanged.  Also, note R3 is of
+//zz       the guest registers written by VG_(sigframe_destroy). */
+//zz    /* jrs 16 Nov 05: for some reason this occasionally causes the 
+//zz       is-this-a-sane-error-value sanity check to fail:
+//zz       m_syswrap/syswrap-ppc64-linux.c:1037
+//zz         (vgSysWrap_ppc64_linux_sys_sigreturn_before): 
+//zz         Assertion 'wzz >= 0 && wzz < 10000' failed.
+//zz       Hence use a sanity-check-free version.  
+//zz       Perhaps we should ignore CR0.S0 here?
+//zz       In general I have no idea what this is for or if it is necessary.
+//zz       It's a conceptual copy-n-paste from the x86 equivalent, but I'm 
+//zz       equally unclear as to whether it is needed there either.
+//zz    */
+//zz    SET_STATUS_from_SysRes_NO_SANITY_CHECK(
+//zz       VG_(mk_SysRes_ppc64_linux)( 
+//zz          tst->arch.vex.guest_GPR3,
+//zz          /* get CR0.SO */
+//zz          (LibVEX_GuestPPC32_get_CR( &tst->arch.vex ) >> 28) & 1
+//zz       )
+//zz    );
+//zz 
+//zz    /* Check to see if some any signals arose as a result of this. */
+//zz    *flags |= SfPollAfter;
+//zz }
+//zz 
+//zz PRE(sys_rt_sigreturn)
+//zz {
+//zz    ThreadState* tst;
+//zz    PRINT("rt_sigreturn ( )");
+//zz 
+//zz    vg_assert(VG_(is_valid_tid)(tid));
+//zz    vg_assert(tid >= 1 && tid < VG_N_THREADS);
+//zz    vg_assert(VG_(is_running_thread)(tid));
+//zz 
+//zz    ///* Adjust esp to point to start of frame; skip back up over handler
+//zz    //   ret addr */
+//zz    tst = VG_(get_ThreadState)(tid);
+//zz    //tst->arch.vex.guest_ESP -= sizeof(Addr);
+//zz    // Should we do something equivalent on ppc64?  Who knows.
+//zz 
+//zz    ///* This is only so that the EIP is (might be) useful to report if
+//zz    //   something goes wrong in the sigreturn */
+//zz    //ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+//zz    // Should we do something equivalent on ppc64?  Who knows.
+//zz 
+//zz    VG_(sigframe_destroy)(tid, True);
+//zz 
+//zz    /* See comments above in PRE(sys_sigreturn) about this. */
+//zz    SET_STATUS_from_SysRes_NO_SANITY_CHECK(
+//zz       VG_(mk_SysRes_ppc64_linux)( 
+//zz          tst->arch.vex.guest_GPR3,
+//zz          /* get CR0.SO */
+//zz          (LibVEX_GuestPPC32_get_CR( &tst->arch.vex ) >> 28) & 1
+//zz       )
+//zz    );
+//zz 
+//zz    /* Check to see if some any signals arose as a result of this. */
+//zz    *flags |= SfPollAfter;
+//zz }
+//zz 
+//zz /* Convert from non-RT to RT sigset_t's */
+//zz static 
+//zz void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
+//zz {
+//zz    VG_(sigemptyset)(set);
+//zz    set->sig[0] = *oldset;
+//zz }
+//zz PRE(sys_sigaction)
+//zz {
+//zz    struct vki_sigaction new, old;
+//zz    struct vki_sigaction *newp, *oldp;
+//zz 
+//zz    PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
+//zz    PRE_REG_READ3(int, "sigaction",
+//zz                  int, signum, const struct old_sigaction *, act,
+//zz                  struct old_sigaction *, oldact);
+//zz 
+//zz    newp = oldp = NULL;
+//zz 
+//zz    if (ARG2 != 0) {
+//zz       struct vki_old_sigaction *sa = (struct vki_old_sigaction *)ARG2;
+//zz       PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
+//zz       PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
+//zz       PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
+//zz       if (ML_(safe_to_deref)(sa,sizeof(sa)) 
+//zz           && (sa->sa_flags & VKI_SA_RESTORER))
+//zz          PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
+//zz    }
+//zz 
+//zz    if (ARG3 != 0) {
+//zz       PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
+//zz       oldp = &old;
+//zz    }
+//zz 
+//zz    //jrs 20050207: what?!  how can this make any sense?
+//zz    //if (VG_(is_kerror)(SYSRES))
+//zz    //   return;
+//zz 
+//zz    if (ARG2 != 0) {
+//zz       struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
+//zz 
+//zz       new.ksa_handler = oldnew->ksa_handler;
+//zz       new.sa_flags = oldnew->sa_flags;
+//zz       new.sa_restorer = oldnew->sa_restorer;
+//zz       convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
+//zz       newp = &new;
+//zz    }
+//zz 
+//zz    SET_STATUS_from_SysRes( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
+//zz 
+//zz    if (ARG3 != 0 && SUCCESS && RES == 0) {
+//zz       struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
+//zz 
+//zz       oldold->ksa_handler = oldp->ksa_handler;
+//zz       oldold->sa_flags = oldp->sa_flags;
+//zz       oldold->sa_restorer = oldp->sa_restorer;
+//zz       oldold->sa_mask = oldp->sa_mask.sig[0];
+//zz    }
+//zz }
+//zz 
+//zz POST(sys_sigaction)
+//zz {
+//zz    vg_assert(SUCCESS);
+//zz    if (RES == 0 && ARG3 != 0)
+//zz       POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
+//zz }
+
+#undef PRE
+#undef POST
+
+/* ---------------------------------------------------------------------
+   The ppc64/Linux syscall table
+   ------------------------------------------------------------------ */
+
+/* Add an ppc64-linux specific wrapper to a syscall table. */
+#define PLAX_(sysno, name)    WRAPPER_ENTRY_X_(ppc64_linux, sysno, name) 
+#define PLAXY(sysno, name)    WRAPPER_ENTRY_XY(ppc64_linux, sysno, name)
+
+// This table maps from __NR_xxx syscall numbers (from
+// linux/include/asm-ppc/unistd.h) to the appropriate PRE/POST sys_foo()
+// wrappers on ppc64 (as per sys_call_table in linux/arch/ppc/kernel/entry.S).
+//
+// For those syscalls not handled by Valgrind, the annotation indicate its
+// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
+// (unknown).
+
+const SyscallTableEntry ML_(syscall_table)[] = {
+// _____(__NR_restart_syscall,   sys__NR_restart_syscall),    //   0
+// _____(__NR_exit,              sys__NR_exit),               //   1
+// _____(__NR_fork,              sys__NR_fork),               //   2
+// _____(__NR_read,              sys__NR_read),               //   3
+// _____(__NR_write,             sys__NR_write),              //   4
+
+// _____(__NR_open,              sys__NR_open),               //   5
+// _____(__NR_close,             sys__NR_close),              //   6
+// _____(__NR_waitpid,           sys__NR_waitpid),            //   7
+// _____(__NR_creat,             sys__NR_creat),              //   8
+// _____(__NR_link,              sys__NR_link),               //   9
+
+// _____(__NR_unlink,            sys__NR_unlink),             //  10
+// _____(__NR_execve,            sys__NR_execve),             //  11
+// _____(__NR_chdir,             sys__NR_chdir),              //  12
+// _____(__NR_time,              sys__NR_time),               //  13
+// _____(__NR_mknod,             sys__NR_mknod),              //  14
+
+// _____(__NR_chmod,             sys__NR_chmod),              //  15
+// _____(__NR_lchown,            sys__NR_lchown),             //  16
+// _____(__NR_break,             sys__NR_break),              //  17
+// _____(__NR_oldstat,           sys__NR_oldstat),            //  18
+// _____(__NR_lseek,             sys__NR_lseek),              //  19
+
+// _____(__NR_getpid,            sys__NR_getpid),             //  20
+// _____(__NR_mount,             sys__NR_mount),              //  21
+// _____(__NR_umount,            sys__NR_umount),             //  22
+// _____(__NR_setuid,            sys__NR_setuid),             //  23
+// _____(__NR_getuid,            sys__NR_getuid),             //  24
+
+// _____(__NR_stime,             sys__NR_stime),              //  25
+// _____(__NR_ptrace,            sys__NR_ptrace),             //  26
+// _____(__NR_alarm,             sys__NR_alarm),              //  27
+// _____(__NR_oldfstat,          sys__NR_oldfstat),           //  28
+// _____(__NR_pause,             sys__NR_pause),              //  29
+
+// _____(__NR_utime,             sys__NR_utime),              //  30
+// _____(__NR_stty,              sys__NR_stty),               //  31
+// _____(__NR_gtty,              sys__NR_gtty),               //  32
+// _____(__NR_access,            sys__NR_access),             //  33
+// _____(__NR_nice,              sys__NR_nice),               //  34
+
+// _____(__NR_ftime,             sys__NR_ftime),              //  35
+// _____(__NR_sync,              sys__NR_sync),               //  36
+// _____(__NR_kill,              sys__NR_kill),               //  37
+// _____(__NR_rename,            sys__NR_rename),             //  38
+// _____(__NR_mkdir,             sys__NR_mkdir),              //  39
+
+// _____(__NR_rmdir,             sys__NR_rmdir),              //  40
+// _____(__NR_dup,               sys__NR_dup),                //  41
+// _____(__NR_pipe,              sys__NR_pipe),               //  42
+// _____(__NR_times,             sys__NR_times),              //  43
+// _____(__NR_prof,              sys__NR_prof),               //  44
+
+// _____(__NR_brk,               sys__NR_brk),                //  45
+// _____(__NR_setgid,            sys__NR_setgid),             //  46
+// _____(__NR_getgid,            sys__NR_getgid),             //  47
+// _____(__NR_signal,            sys__NR_signal),             //  48
+// _____(__NR_geteuid,           sys__NR_geteuid),            //  49
+
+// _____(__NR_getegid,           sys__NR_getegid),            //  50
+// _____(__NR_acct,              sys__NR_acct),               //  51
+// _____(__NR_umount2,           sys__NR_umount2),            //  52
+// _____(__NR_lock,              sys__NR_lock),               //  53
+// _____(__NR_ioctl,             sys__NR_ioctl),              //  54
+
+// _____(__NR_fcntl,             sys__NR_fcntl),              //  55
+// _____(__NR_mpx,               sys__NR_mpx),                //  56
+// _____(__NR_setpgid,           sys__NR_setpgid),            //  57
+// _____(__NR_ulimit,            sys__NR_ulimit),             //  58
+// _____(__NR_oldolduname,       sys__NR_oldolduname),        //  59
+
+// _____(__NR_umask,             sys__NR_umask),              //  60
+// _____(__NR_chroot,            sys__NR_chroot),             //  61
+// _____(__NR_ustat,             sys__NR_ustat),              //  62
+// _____(__NR_dup2,              sys__NR_dup2),               //  63
+// _____(__NR_getppid,           sys__NR_getppid),            //  64
+
+// _____(__NR_getpgrp,           sys__NR_getpgrp),            //  65
+// _____(__NR_setsid,            sys__NR_setsid),             //  66
+// _____(__NR_sigaction,         sys__NR_sigaction),          //  67
+// _____(__NR_sgetmask,          sys__NR_sgetmask),           //  68
+// _____(__NR_ssetmask,          sys__NR_ssetmask),           //  69
+
+// _____(__NR_setreuid,          sys__NR_setreuid),           //  70
+// _____(__NR_setregid,          sys__NR_setregid),           //  71
+// _____(__NR_sigsuspend,        sys__NR_sigsuspend),         //  72
+// _____(__NR_sigpending,        sys__NR_sigpending),         //  73
+// _____(__NR_sethostname,       sys__NR_sethostname),        //  74
+
+// _____(__NR_setrlimit,         sys__NR_setrlimit),          //  75
+// _____(__NR_getrlimit,         sys__NR_getrlimit),          //  76
+// _____(__NR_getrusage,         sys__NR_getrusage),          //  77
+// _____(__NR_gettimeofday,      sys__NR_gettimeofday),       //  78
+// _____(__NR_settimeofday,      sys__NR_settimeofday),       //  79
+
+// _____(__NR_getgroups,         sys__NR_getgroups),          //  80
+// _____(__NR_setgroups,         sys__NR_setgroups),          //  81
+// _____(__NR_select,            sys__NR_select),             //  82
+// _____(__NR_symlink,           sys__NR_symlink),            //  83
+// _____(__NR_oldlstat,          sys__NR_oldlstat),           //  84
+
+// _____(__NR_readlink,          sys__NR_readlink),           //  85
+// _____(__NR_uselib,            sys__NR_uselib),             //  86
+// _____(__NR_swapon,            sys__NR_swapon),             //  87
+// _____(__NR_reboot,            sys__NR_reboot),             //  88
+// _____(__NR_readdir,           sys__NR_readdir),            //  89
+
+// _____(__NR_mmap,              sys__NR_mmap),               //  90
+// _____(__NR_munmap,            sys__NR_munmap),             //  91
+// _____(__NR_truncate,          sys__NR_truncate),           //  92
+// _____(__NR_ftruncate,         sys__NR_ftruncate),          //  93
+// _____(__NR_fchmod,            sys__NR_fchmod),             //  94
+
+// _____(__NR_fchown,            sys__NR_fchown),             //  95
+// _____(__NR_getpriority,       sys__NR_getpriority),        //  96
+// _____(__NR_setpriority,       sys__NR_setpriority),        //  97
+// _____(__NR_profil,            sys__NR_profil),             //  98
+// _____(__NR_statfs,            sys__NR_statfs),             //  99
+
+// _____(__NR_fstatfs,           sys__NR_fstatfs),            // 100
+// _____(__NR_ioperm,            sys__NR_ioperm),             // 101
+// _____(__NR_socketcall,        sys__NR_socketcall),         // 102
+// _____(__NR_syslog,            sys__NR_syslog),             // 103
+// _____(__NR_setitimer,         sys__NR_setitimer),          // 104
+
+// _____(__NR_getitimer,         sys__NR_getitimer),          // 105
+// _____(__NR_stat,              sys__NR_stat),               // 106
+// _____(__NR_lstat,             sys__NR_lstat),              // 107
+// _____(__NR_fstat,             sys__NR_fstat),              // 108
+// _____(__NR_olduname,          sys__NR_olduname),           // 109
+
+// _____(__NR_iopl,              sys__NR_iopl),               // 110
+// _____(__NR_vhangup,           sys__NR_vhangup),            // 111
+// _____(__NR_idle,              sys__NR_idle),               // 112
+// _____(__NR_vm86,              sys__NR_vm86),               // 113
+// _____(__NR_wait4,             sys__NR_wait4),              // 114
+
+// _____(__NR_swapoff,           sys__NR_swapoff),            // 115
+// _____(__NR_sysinfo,           sys__NR_sysinfo),            // 116
+// _____(__NR_ipc,               sys__NR_ipc),                // 117
+// _____(__NR_fsync,             sys__NR_fsync),              // 118
+// _____(__NR_sigreturn,         sys__NR_sigreturn),          // 119
+
+// _____(__NR_clone,             sys__NR_clone),              // 120
+// _____(__NR_setdomainname,     sys__NR_setdomainname),      // 121
+// _____(__NR_uname,             sys__NR_uname),              // 122
+// _____(__NR_modify_ldt,        sys__NR_modify_ldt),         // 123
+// _____(__NR_adjtimex,          sys__NR_adjtimex),           // 124
+
+// _____(__NR_mprotect,          sys__NR_mprotect),           // 125
+// _____(__NR_sigprocmask,       sys__NR_sigprocmask),        // 126
+// _____(__NR_create_module,     sys__NR_create_module),      // 127
+// _____(__NR_init_module,       sys__NR_init_module),        // 128
+// _____(__NR_delete_module,     sys__NR_delete_module),      // 129
+
+// _____(__NR_get_kernel_syms,   sys__NR_get_kernel_syms),    // 130
+// _____(__NR_quotactl,          sys__NR_quotactl),           // 131
+// _____(__NR_getpgid,           sys__NR_getpgid),            // 132
+// _____(__NR_fchdir,            sys__NR_fchdir),             // 133
+// _____(__NR_bdflush,           sys__NR_bdflush),            // 134
+
+// _____(__NR_sysfs,             sys__NR_sysfs),              // 135
+// _____(__NR_personality,       sys__NR_personality),        // 136
+// _____(__NR_afs_syscall,       sys__NR_afs_syscall),        // 137
+// _____(__NR_setfsuid,          sys__NR_setfsuid),           // 138
+// _____(__NR_setfsgid,          sys__NR_setfsgid),           // 139
+
+// _____(__NR__llseek,           sys__NR__llseek),            // 140
+// _____(__NR_getdents,          sys__NR_getdents),           // 141
+// _____(__NR__newselect,        sys__NR__newselect),         // 142
+// _____(__NR_flock,             sys__NR_flock),              // 143
+// _____(__NR_msync,             sys__NR_msync),              // 144
+
+// _____(__NR_readv,             sys__NR_readv),              // 145
+// _____(__NR_writev,            sys__NR_writev),             // 146
+// _____(__NR_getsid,            sys__NR_getsid),             // 147
+// _____(__NR_fdatasync,         sys__NR_fdatasync),          // 148
+// _____(__NR__sysctl,           sys__NR__sysctl),            // 149
+
+// _____(__NR_mlock,             sys__NR_mlock),              // 150
+// _____(__NR_munlock,           sys__NR_munlock),            // 151
+// _____(__NR_mlockall,          sys__NR_mlockall),           // 152
+// _____(__NR_munlockall,        sys__NR_munlockall),         // 153
+// _____(__NR_sched_setparam,    sys__NR_sched_setparam),     // 154
+
+// _____(__NR_sched_getparam,    sys__NR_sched_getparam),     // 155
+// _____(__NR_sched_setscheduler,      sys__NR_sched_setscheduler),     // 156
+// _____(__NR_sched_getscheduler,      sys__NR_sched_getscheduler),     // 157
+// _____(__NR_sched_yield,             sys__NR_sched_yield),            // 158
+// _____(__NR_sched_get_priority_max,  sys__NR_sched_get_priority_max), // 159
+
+// _____(__NR_sched_get_priority_min,  sys__NR_sched_get_priority_min), // 160
+// _____(__NR_sched_rr_get_interval,   sys__NR_sched_rr_get_interval),  // 161
+// _____(__NR_nanosleep,         sys__NR_nanosleep),          // 162
+// _____(__NR_mremap,            sys__NR_mremap),             // 163
+// _____(__NR_setresuid,         sys__NR_setresuid),          // 164
+
+// _____(__NR_getresuid,         sys__NR_getresuid),          // 165
+// _____(__NR_query_module,      sys__NR_query_module),       // 166
+// _____(__NR_poll,              sys__NR_poll),               // 167
+// _____(__NR_nfsservctl,        sys__NR_nfsservctl),         // 168
+// _____(__NR_setresgid,         sys__NR_setresgid),          // 169
+
+// _____(__NR_getresgid,         sys__NR_getresgid),          // 170
+// _____(__NR_prctl,             sys__NR_prctl),              // 171
+// _____(__NR_rt_sigreturn,      sys__NR_rt_sigreturn),       // 172
+// _____(__NR_rt_sigaction,      sys__NR_rt_sigaction),       // 173
+// _____(__NR_rt_sigprocmask,    sys__NR_rt_sigprocmask),     // 174
+
+// _____(__NR_rt_sigpending,     sys__NR_rt_sigpending),      // 175
+// _____(__NR_rt_sigtimedwait,   sys__NR_rt_sigtimedwait),    // 176
+// _____(__NR_rt_sigqueueinfo,   sys__NR_rt_sigqueueinfo),    // 177
+// _____(__NR_rt_sigsuspend,     sys__NR_rt_sigsuspend),      // 178
+// _____(__NR_pread64,           sys__NR_pread64),            // 179
+
+// _____(__NR_pwrite64,          sys__NR_pwrite64),           // 180
+// _____(__NR_chown,             sys__NR_chown),              // 181
+// _____(__NR_getcwd,            sys__NR_getcwd),             // 182
+// _____(__NR_capget,            sys__NR_capget),             // 183
+// _____(__NR_capset,            sys__NR_capset),             // 184
+
+// _____(__NR_sigaltstack,       sys__NR_sigaltstack),        // 185
+// _____(__NR_sendfile,          sys__NR_sendfile),           // 186
+// _____(__NR_getpmsg,           sys__NR_getpmsg),            // 187
+// _____(__NR_putpmsg,           sys__NR_putpmsg),            // 188
+// _____(__NR_vfork,             sys__NR_vfork),              // 189
+
+// _____(__NR_ugetrlimit,        sys__NR_ugetrlimit),         // 190
+// _____(__NR_readahead,         sys__NR_readahead),          // 191
+// /* #define __NR_mmap2           192     32bit only */
+// /* #define __NR_truncate64      193     32bit only */
+// /* #define __NR_ftruncate64     194     32bit only */
+
+// /* #define __NR_stat64          195     32bit only */
+// /* #define __NR_lstat64         196     32bit only */
+// /* #define __NR_fstat64         197     32bit only */
+// _____(__NR_pciconfig_read,    sys__NR_pciconfig_read),     // 198
+// _____(__NR_pciconfig_write,   sys__NR_pciconfig_write),    // 199
+
+// _____(__NR_pciconfig_iobase,  sys__NR_pciconfig_iobase),   // 200
+// _____(__NR_multiplexer,       sys__NR_multiplexer),        // 201
+// _____(__NR_getdents64,        sys__NR_getdents64),         // 202
+// _____(__NR_pivot_root,        sys__NR_pivot_root),         // 203
+// /* #define __NR_fcntl64         204     32bit only */
+
+// _____(__NR_madvise,           sys__NR_madvise),            // 205
+// _____(__NR_mincore,           sys__NR_mincore),            // 206
+// _____(__NR_gettid,            sys__NR_gettid),             // 207
+// _____(__NR_tkill,             sys__NR_tkill),              // 208
+// _____(__NR_setxattr,          sys__NR_setxattr),           // 209
+
+// _____(__NR_lsetxattr,         sys__NR_lsetxattr),          // 210
+// _____(__NR_fsetxattr,         sys__NR_fsetxattr),          // 211
+// _____(__NR_getxattr,          sys__NR_getxattr),           // 212
+// _____(__NR_lgetxattr,         sys__NR_lgetxattr),          // 213
+// _____(__NR_fgetxattr,         sys__NR_fgetxattr),          // 214
+
+// _____(__NR_listxattr,         sys__NR_listxattr),          // 215
+// _____(__NR_llistxattr,        sys__NR_llistxattr),         // 216
+// _____(__NR_flistxattr,        sys__NR_flistxattr),         // 217
+// _____(__NR_removexattr,       sys__NR_removexattr),        // 218
+// _____(__NR_lremovexattr,      sys__NR_lremovexattr),       // 219
+
+// _____(__NR_fremovexattr,      sys__NR_fremovexattr),       // 220
+// _____(__NR_futex,             sys__NR_futex),              // 221
+// _____(__NR_sched_setaffinity, sys__NR_sched_setaffinity),  // 222
+// _____(__NR_sched_getaffinity, sys__NR_sched_getaffinity),  // 223
+// /* 224 currently unused */
+
+// _____(__NR_tuxcall,           sys__NR_tuxcall),            // 225
+// /* #define __NR_sendfile64      226     32bit only */
+// _____(__NR_io_setup,          sys__NR_io_setup),           // 227
+// _____(__NR_io_destroy,        sys__NR_io_destroy),         // 228
+// _____(__NR_io_getevents,      sys__NR_io_getevents),       // 229
+
+// _____(__NR_io_submit,         sys__NR_io_submit),          // 230
+// _____(__NR_io_cancel,         sys__NR_io_cancel),          // 231
+// _____(__NR_set_tid_address,   sys__NR_set_tid_address),    // 232
+// _____(__NR_fadvise64,         sys__NR_fadvise64),          // 233
+// _____(__NR_exit_group,        sys__NR_exit_group),         // 234
+
+// _____(__NR_lookup_dcookie,    sys__NR_lookup_dcookie),     // 235
+// _____(__NR_epoll_create,      sys__NR_epoll_create),       // 236
+// _____(__NR_epoll_ctl,         sys__NR_epoll_ctl),          // 237
+// _____(__NR_epoll_wait,        sys__NR_epoll_wait),         // 238
+// _____(__NR_remap_file_pages,  sys__NR_remap_file_pages),   // 239
+
+// _____(__NR_timer_create,      sys__NR_timer_create),       // 240
+// _____(__NR_timer_settime,     sys__NR_timer_settime),      // 241
+// _____(__NR_timer_gettime,     sys__NR_timer_gettime),      // 242
+// _____(__NR_timer_getoverrun,  sys__NR_timer_getoverrun),   // 243
+// _____(__NR_timer_delete,      sys__NR_timer_delete),       // 244
+
+// _____(__NR_clock_settime,     sys__NR_clock_settime),      // 245
+// _____(__NR_clock_gettime,     sys__NR_clock_gettime),      // 246
+// _____(__NR_clock_getres,      sys__NR_clock_getres),       // 247
+// _____(__NR_clock_nanosleep,   sys__NR_clock_nanosleep),    // 248
+// _____(__NR_swapcontext,       sys__NR_swapcontext),        // 249
+
+// _____(__NR_tgkill,            sys__NR_tgkill),             // 250
+// _____(__NR_utimes,            sys__NR_utimes),             // 251
+// _____(__NR_statfs64,          sys__NR_statfs64),           // 252
+// _____(__NR_fstatfs64,         sys__NR_fstatfs64),          // 253
+// /* #define __NR_fadvise64_64    254     32bit only */
+
+// _____(__NR_rtas,              sys__NR_rtas),               // 255
+// /* Number 256 is reserved for sys_debug_setcontext */
+// /* Number 257 is reserved for vserver */
+// /* 258 currently unused */
+// _____(__NR_mbind,             sys__NR_mbind),              // 259
+
+// _____(__NR_get_mempolicy,     sys__NR_get_mempolicy),      // 260
+// _____(__NR_set_mempolicy,     sys__NR_set_mempolicy),      // 261
+// _____(__NR_mq_open,           sys__NR_mq_open),            // 262
+// _____(__NR_mq_unlink,         sys__NR_mq_unlink),          // 263
+// _____(__NR_mq_timedsend,      sys__NR_mq_timedsend),       // 264
+
+// _____(__NR_mq_timedreceive,   sys__NR_mq_timedreceive),    // 265
+// _____(__NR_mq_notify,         sys__NR_mq_notify),          // 266
+// _____(__NR_mq_getsetattr,     sys__NR_mq_getsetattr),      // 267
+// _____(__NR_kexec_load,        sys__NR_kexec_load),         // 268
+// _____(__NR_add_key,           sys__NR_add_key),            // 269
+
+// _____(__NR_request_key,       sys__NR_request_key),        // 270
+// _____(__NR_keyctl,            sys__NR_keyctl),             // 271
+// _____(__NR_waitid,            sys__NR_waitid),             // 272
+// _____(__NR_ioprio_set,        sys__NR_ioprio_set),         // 273
+// _____(__NR_ioprio_get,        sys__NR_ioprio_get),         // 274
+
+// _____(__NR_inotify_init,      sys__NR_inotify_init),       // 275
+// _____(__NR_inotify_add_watch, sys__NR_inotify_add_watch),  // 276
+// _____(__NR_inotify_rm_watch,  sys__NR_inotify_rm_watch)    // 277
+};
+
+const UInt ML_(syscall_table_size) = 
+            sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S
index e4930f9..8423fed 100644
--- a/coregrind/m_trampoline.S
+++ b/coregrind/m_trampoline.S
@@ -283,6 +283,31 @@
 #	undef UD2_1024
 #	undef UD2_PAGE
 
+/*---------------- ppc64-linux ----------------*/
+#else
+#if defined(VGP_ppc64_linux)
+
+#	define UD2_16     trap ; trap ; trap; trap
+#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
+#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
+#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
+#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
+
+	/* a leading page of unexecutable code */
+	UD2_PAGE
+
+.global VG_(trampoline_stuff_start)
+VG_(trampoline_stuff_start):
+	
+.global VG_(trampoline_stuff_end)
+VG_(trampoline_stuff_end):
+
+#	undef UD2_16
+#	undef UD2_64
+#	undef UD2_256
+#	undef UD2_1024
+#	undef UD2_PAGE
+
 /*---------------- unknown ----------------*/
 #else
 #  error Unknown platform
@@ -290,6 +315,7 @@
 #endif
 #endif
 #endif
+#endif
 
 
 /* Let the linker know we don't need an executable stack */
diff --git a/coregrind/m_transtab.c b/coregrind/m_transtab.c
index bf57d09..d8f671a 100644
--- a/coregrind/m_transtab.c
+++ b/coregrind/m_transtab.c
@@ -734,7 +734,7 @@
 
 static void invalidate_icache ( void *ptr, Int nbytes )
 {
-#  if defined(VGA_ppc32)
+#  if defined(VGA_ppc32) || defined(VGA_ppc64)
    Addr startaddr = (Addr) ptr;
    Addr endaddr   = startaddr + nbytes;
    Addr cls;
diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h
index c421b84..160add6 100644
--- a/coregrind/pub_core_basics.h
+++ b/coregrind/pub_core_basics.h
@@ -55,6 +55,8 @@
 #  include "libvex_guest_amd64.h"
 #elif defined(VGA_ppc32)
 #  include "libvex_guest_ppc32.h"
+#elif defined(VGA_ppc64)
+#  include "libvex_guest_ppc64.h"
 #else
 #  error Unknown arch
 #endif
diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h
index 389f757..1b68204 100644
--- a/coregrind/pub_core_machine.h
+++ b/coregrind/pub_core_machine.h
@@ -51,6 +51,10 @@
 #  define VG_ELF_DATA2XXX     ELFDATA2MSB
 #  define VG_ELF_MACHINE      EM_PPC
 #  define VG_ELF_CLASS        ELFCLASS32
+#elif defined(VGA_ppc64)
+#  define VG_ELF_DATA2XXX     ELFDATA2MSB
+#  define VG_ELF_MACHINE      EM_PPC64
+#  define VG_ELF_CLASS        ELFCLASS64
 #else
 #  error Unknown arch
 #endif
@@ -67,6 +71,10 @@
 #  define VG_INSTR_PTR        guest_CIA
 #  define VG_STACK_PTR        guest_GPR1
 #  define VG_FRAME_PTR        guest_GPR1   // No frame ptr for PPC
+#elif defined(VGA_ppc64)
+#  define VG_INSTR_PTR        guest_CIA
+#  define VG_STACK_PTR        guest_GPR1
+#  define VG_FRAME_PTR        guest_GPR1   // No frame ptr for PPC
 #else
 #  error Unknown arch
 #endif
@@ -100,6 +108,12 @@
           then safe to use VG_(machine_get_VexArchInfo) 
                        and VG_(machine_ppc32_has_FP)
                        and VG_(machine_ppc32_has_VMX)
+   -------------
+   ppc64: initially:  call VG_(machine_get_hwcaps)
+                      call VG_(machine_ppc64_set_clszB)
+
+          then safe to use VG_(machine_get_VexArchInfo) 
+                       and VG_(machine_ppc64_has_VMX)
 
    VG_(machine_get_hwcaps) may use signals (although it attempts to
    leave signal state unchanged) and therefore should only be
@@ -120,6 +134,10 @@
 extern void VG_(machine_ppc32_set_clszB)( Int );
 #endif
 
+#if defined(VGA_ppc64)
+extern void VG_(machine_ppc64_set_clszB)( Int );
+#endif
+
 /* X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
    the SSE control/status register), else zero.  Is referenced from
    assembly code, so do not change from a 32-bit int. */
@@ -141,6 +159,13 @@
 extern UInt VG_(machine_ppc32_has_VMX);
 #endif
 
+/* PPC64: set to 1 if Altivec instructions are supported in
+   user-space, else 0.  Is referenced from assembly code, so do not
+   change from a 64-bit int. */
+#if defined(VGA_ppc64)
+extern ULong VG_(machine_ppc64_has_VMX);
+#endif
+
 #endif   // __PUB_CORE_MACHINE_H
 
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h
index f5c7628..1fef4d9 100644
--- a/coregrind/pub_core_syscall.h
+++ b/coregrind/pub_core_syscall.h
@@ -61,9 +61,10 @@
 #define vgPlain_do_syscall6(s,a,b,c,d,e,f) VG_(do_syscall)((s),(a),(b),\
                                                            (c),(d),(e),(f))
 
-extern SysRes VG_(mk_SysRes_x86_linux)   ( Word val );
-extern SysRes VG_(mk_SysRes_amd64_linux) ( Word val );
-extern SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so );
+extern SysRes VG_(mk_SysRes_x86_linux)   ( UInt  val );
+extern SysRes VG_(mk_SysRes_amd64_linux) ( ULong val );
+extern SysRes VG_(mk_SysRes_ppc32_linux) ( UInt  val, UInt  cr0so );
+extern SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so );
 extern SysRes VG_(mk_SysRes_Error)       ( UWord val );
 extern SysRes VG_(mk_SysRes_Success)     ( UWord val );
 
diff --git a/coregrind/pub_core_threadstate.h b/coregrind/pub_core_threadstate.h
index e58e032..c4dd5f7 100644
--- a/coregrind/pub_core_threadstate.h
+++ b/coregrind/pub_core_threadstate.h
@@ -81,6 +81,8 @@
    typedef VexGuestAMD64State VexGuestArchState;
 #elif defined(VGA_ppc32)
    typedef VexGuestPPC32State VexGuestArchState;
+#elif defined(VGA_ppc64)
+   typedef VexGuestPPC64State VexGuestArchState;
 #else
 #  error Unknown architecture
 #endif
diff --git a/coregrind/vki_unistd-ppc64-linux.h b/coregrind/vki_unistd-ppc64-linux.h
new file mode 100644
index 0000000..17f640c
--- /dev/null
+++ b/coregrind/vki_unistd-ppc64-linux.h
@@ -0,0 +1,312 @@
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2005 Julian Seward
+      jseward@acm.org
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __VKI_UNISTD_PPC64_LINUX_H
+#define __VKI_UNISTD_PPC64_LINUX_H
+
+// From linux-2.6.13/include/asm-ppc64/unistd.h
+
+#define __NR_restart_syscall      0
+#define __NR_exit                 1
+#define __NR_fork                 2
+#define __NR_read                 3
+#define __NR_write                4
+#define __NR_open                 5
+#define __NR_close                6
+#define __NR_waitpid              7
+#define __NR_creat                8
+#define __NR_link                 9
+#define __NR_unlink              10
+#define __NR_execve              11
+#define __NR_chdir               12
+#define __NR_time                13
+#define __NR_mknod               14
+#define __NR_chmod               15
+#define __NR_lchown              16
+#define __NR_break               17
+#define __NR_oldstat             18
+#define __NR_lseek               19
+#define __NR_getpid              20
+#define __NR_mount               21
+#define __NR_umount              22
+#define __NR_setuid              23
+#define __NR_getuid              24
+#define __NR_stime               25
+#define __NR_ptrace              26
+#define __NR_alarm               27
+#define __NR_oldfstat            28
+#define __NR_pause               29
+#define __NR_utime               30
+#define __NR_stty                31
+#define __NR_gtty                32
+#define __NR_access              33
+#define __NR_nice                34
+#define __NR_ftime               35
+#define __NR_sync                36
+#define __NR_kill                37
+#define __NR_rename              38
+#define __NR_mkdir               39
+#define __NR_rmdir               40
+#define __NR_dup                 41
+#define __NR_pipe                42
+#define __NR_times               43
+#define __NR_prof                44
+#define __NR_brk                 45
+#define __NR_setgid              46
+#define __NR_getgid              47
+#define __NR_signal              48
+#define __NR_geteuid             49
+#define __NR_getegid             50
+#define __NR_acct                51
+#define __NR_umount2             52
+#define __NR_lock                53
+#define __NR_ioctl               54
+#define __NR_fcntl               55
+#define __NR_mpx                 56
+#define __NR_setpgid             57
+#define __NR_ulimit              58
+#define __NR_oldolduname         59
+#define __NR_umask               60
+#define __NR_chroot              61
+#define __NR_ustat               62
+#define __NR_dup2                63
+#define __NR_getppid             64
+#define __NR_getpgrp             65
+#define __NR_setsid              66
+#define __NR_sigaction           67
+#define __NR_sgetmask            68
+#define __NR_ssetmask            69
+#define __NR_setreuid            70
+#define __NR_setregid            71
+#define __NR_sigsuspend          72
+#define __NR_sigpending          73
+#define __NR_sethostname         74
+#define __NR_setrlimit           75
+#define __NR_getrlimit           76
+#define __NR_getrusage           77
+#define __NR_gettimeofday        78
+#define __NR_settimeofday        79
+#define __NR_getgroups           80
+#define __NR_setgroups           81
+#define __NR_select              82
+#define __NR_symlink             83
+#define __NR_oldlstat            84
+#define __NR_readlink            85
+#define __NR_uselib              86
+#define __NR_swapon              87
+#define __NR_reboot              88
+#define __NR_readdir             89
+#define __NR_mmap                90
+#define __NR_munmap              91
+#define __NR_truncate            92
+#define __NR_ftruncate           93
+#define __NR_fchmod              94
+#define __NR_fchown              95
+#define __NR_getpriority         96
+#define __NR_setpriority         97
+#define __NR_profil              98
+#define __NR_statfs              99
+#define __NR_fstatfs            100
+#define __NR_ioperm             101
+#define __NR_socketcall         102
+#define __NR_syslog             103
+#define __NR_setitimer          104
+#define __NR_getitimer          105
+#define __NR_stat               106
+#define __NR_lstat              107
+#define __NR_fstat              108
+#define __NR_olduname           109
+#define __NR_iopl               110
+#define __NR_vhangup            111
+#define __NR_idle               112
+#define __NR_vm86               113
+#define __NR_wait4              114
+#define __NR_swapoff            115
+#define __NR_sysinfo            116
+#define __NR_ipc                117
+#define __NR_fsync              118
+#define __NR_sigreturn          119
+#define __NR_clone              120
+#define __NR_setdomainname      121
+#define __NR_uname              122
+#define __NR_modify_ldt         123
+#define __NR_adjtimex           124
+#define __NR_mprotect           125
+#define __NR_sigprocmask        126
+#define __NR_create_module      127
+#define __NR_init_module        128
+#define __NR_delete_module      129
+#define __NR_get_kernel_syms    130
+#define __NR_quotactl           131
+#define __NR_getpgid            132
+#define __NR_fchdir             133
+#define __NR_bdflush            134
+#define __NR_sysfs              135
+#define __NR_personality        136
+#define __NR_afs_syscall        137 /* Syscall for Andrew File System */
+#define __NR_setfsuid           138
+#define __NR_setfsgid           139
+#define __NR__llseek            140
+#define __NR_getdents           141
+#define __NR__newselect         142
+#define __NR_flock              143
+#define __NR_msync              144
+#define __NR_readv              145
+#define __NR_writev             146
+#define __NR_getsid             147
+#define __NR_fdatasync          148
+#define __NR__sysctl            149
+#define __NR_mlock              150
+#define __NR_munlock            151
+#define __NR_mlockall           152
+#define __NR_munlockall         153
+#define __NR_sched_setparam             154
+#define __NR_sched_getparam             155
+#define __NR_sched_setscheduler         156
+#define __NR_sched_getscheduler         157
+#define __NR_sched_yield                158
+#define __NR_sched_get_priority_max     159
+#define __NR_sched_get_priority_min     160
+#define __NR_sched_rr_get_interval      161
+#define __NR_nanosleep          162
+#define __NR_mremap             163
+#define __NR_setresuid          164
+#define __NR_getresuid          165
+#define __NR_query_module       166
+#define __NR_poll               167
+#define __NR_nfsservctl         168
+#define __NR_setresgid          169
+#define __NR_getresgid          170
+#define __NR_prctl              171
+#define __NR_rt_sigreturn       172
+#define __NR_rt_sigaction       173
+#define __NR_rt_sigprocmask     174
+#define __NR_rt_sigpending      175
+#define __NR_rt_sigtimedwait    176
+#define __NR_rt_sigqueueinfo    177
+#define __NR_rt_sigsuspend      178
+#define __NR_pread64            179
+#define __NR_pwrite64           180
+#define __NR_chown              181
+#define __NR_getcwd             182
+#define __NR_capget             183
+#define __NR_capset             184
+#define __NR_sigaltstack        185
+#define __NR_sendfile           186
+#define __NR_getpmsg            187     /* some people actually want streams */
+#define __NR_putpmsg            188     /* some people actually want streams */
+#define __NR_vfork              189
+#define __NR_ugetrlimit         190     /* SuS compliant getrlimit */
+#define __NR_readahead          191
+/* #define __NR_mmap2           192     32bit only */
+/* #define __NR_truncate64      193     32bit only */
+/* #define __NR_ftruncate64     194     32bit only */
+/* #define __NR_stat64          195     32bit only */
+/* #define __NR_lstat64         196     32bit only */
+/* #define __NR_fstat64         197     32bit only */
+#define __NR_pciconfig_read     198
+#define __NR_pciconfig_write    199
+#define __NR_pciconfig_iobase   200
+#define __NR_multiplexer        201
+#define __NR_getdents64         202
+#define __NR_pivot_root         203
+/* #define __NR_fcntl64         204     32bit only */
+#define __NR_madvise            205
+#define __NR_mincore            206
+#define __NR_gettid             207
+#define __NR_tkill              208
+#define __NR_setxattr           209
+#define __NR_lsetxattr          210
+#define __NR_fsetxattr          211
+#define __NR_getxattr           212
+#define __NR_lgetxattr          213
+#define __NR_fgetxattr          214
+#define __NR_listxattr          215
+#define __NR_llistxattr         216
+#define __NR_flistxattr         217
+#define __NR_removexattr        218
+#define __NR_lremovexattr       219
+#define __NR_fremovexattr       220
+#define __NR_futex              221
+#define __NR_sched_setaffinity  222
+#define __NR_sched_getaffinity  223
+/* 224 currently unused */
+#define __NR_tuxcall            225
+/* #define __NR_sendfile64      226     32bit only */
+#define __NR_io_setup           227
+#define __NR_io_destroy         228
+#define __NR_io_getevents       229
+#define __NR_io_submit          230
+#define __NR_io_cancel          231
+#define __NR_set_tid_address    232
+#define __NR_fadvise64          233
+#define __NR_exit_group         234
+#define __NR_lookup_dcookie     235
+#define __NR_epoll_create       236
+#define __NR_epoll_ctl          237
+#define __NR_epoll_wait         238
+#define __NR_remap_file_pages   239
+#define __NR_timer_create       240
+#define __NR_timer_settime      241
+#define __NR_timer_gettime      242
+#define __NR_timer_getoverrun   243
+#define __NR_timer_delete       244
+#define __NR_clock_settime      245
+#define __NR_clock_gettime      246
+#define __NR_clock_getres       247
+#define __NR_clock_nanosleep    248
+#define __NR_swapcontext        249
+#define __NR_tgkill             250
+#define __NR_utimes             251
+#define __NR_statfs64           252
+#define __NR_fstatfs64          253
+/* #define __NR_fadvise64_64    254     32bit only */
+#define __NR_rtas               255
+/* Number 256 is reserved for sys_debug_setcontext */
+/* Number 257 is reserved for vserver */
+/* 258 currently unused */
+#define __NR_mbind              259
+#define __NR_get_mempolicy      260
+#define __NR_set_mempolicy      261
+#define __NR_mq_open            262
+#define __NR_mq_unlink          263
+#define __NR_mq_timedsend       264
+#define __NR_mq_timedreceive    265
+#define __NR_mq_notify          266
+#define __NR_mq_getsetattr      267
+#define __NR_kexec_load         268
+#define __NR_add_key            269
+#define __NR_request_key        270
+#define __NR_keyctl             271
+#define __NR_waitid             272
+#define __NR_ioprio_set         273
+#define __NR_ioprio_get         274
+#define __NR_inotify_init       275
+#define __NR_inotify_add_watch  276
+#define __NR_inotify_rm_watch   277
+
+
+#endif /* __VKI_UNISTD_PPC32_LINUX_H */
diff --git a/coregrind/vki_unistd.h b/coregrind/vki_unistd.h
index 4945cb0..934442d 100644
--- a/coregrind/vki_unistd.h
+++ b/coregrind/vki_unistd.h
@@ -38,6 +38,8 @@
 #  include "vki_unistd-amd64-linux.h" 
 #elif defined(VGP_ppc32_linux)
 #  include "vki_unistd-ppc32-linux.h" 
+#elif defined(VGP_ppc64_linux)
+#  include "vki_unistd-ppc64-linux.h" 
 #else
 #  error Unknown platform
 #endif
diff --git a/helgrind/Makefile.am b/helgrind/Makefile.am
index 469a55e..cf47a01 100644
--- a/helgrind/Makefile.am
+++ b/helgrind/Makefile.am
@@ -10,6 +10,9 @@
 if VG_PPC32_LINUX
 noinst_PROGRAMS += helgrind-ppc32-linux vgpreload_helgrind-ppc32-linux.so
 endif
+if VG_PPC64_LINUX
+noinst_PROGRAMS += helgrind-ppc64-linux vgpreload_helgrind-ppc64-linux.so
+endif
 
 vgpreload_helgrind_x86_linux_so_SOURCES      = 
 vgpreload_helgrind_x86_linux_so_CPPFLAGS     = $(AM_CPPFLAGS_X86_LINUX)
@@ -35,6 +38,14 @@
 	$(PRELOAD_LDFLAGS_PPC32_LINUX) \
 	$(LIBREPLACEMALLOC_LDFLAGS_PPC32_LINUX)
 
+vgpreload_helgrind_ppc64_linux_so_SOURCES      = 
+vgpreload_helgrind_ppc64_linux_so_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+vgpreload_helgrind_ppc64_linux_so_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX) $(AM_CFLAGS_PIC)
+vgpreload_helgrind_ppc64_linux_so_DEPENDENCIES = $(LIBREPLACEMALLOC_PPC64_LINUX)
+vgpreload_helgrind_ppc64_linux_so_LDFLAGS      = \
+	$(PRELOAD_LDFLAGS_PPC64_LINUX) \
+	$(LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX)
+
 HELGRIND_SOURCES_COMMON = hg_main.c
 
 helgrind_x86_linux_SOURCES      = $(HELGRIND_SOURCES_COMMON)
@@ -58,6 +69,13 @@
 helgrind_ppc32_linux_LDADD        = $(TOOL_LDADD_PPC32_LINUX)
 helgrind_ppc32_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC32_LINUX)
 
+helgrind_ppc64_linux_SOURCES      = $(HELGRIND_SOURCES_COMMON)
+helgrind_ppc64_linux_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+helgrind_ppc64_linux_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX)
+helgrind_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_LINUX)
+helgrind_ppc64_linux_LDADD        = $(TOOL_LDADD_PPC64_LINUX)
+helgrind_ppc64_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC64_LINUX)
+
 hgincludedir = $(includedir)/valgrind
 
 hginclude_HEADERS = helgrind.h
diff --git a/include/Makefile.am b/include/Makefile.am
index b575825..5b9ed13 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -32,7 +32,9 @@
 	vki-linux.h			\
 	vki-amd64-linux.h		\
 	vki-ppc32-linux.h		\
+	vki-ppc64-linux.h		\
 	vki-x86-linux.h			\
 	vki_posixtypes-amd64-linux.h	\
 	vki_posixtypes-ppc32-linux.h	\
+	vki_posixtypes-ppc64-linux.h	\
 	vki_posixtypes-x86-linux.h
diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h
index 2733007..4947d44 100644
--- a/include/pub_tool_basics.h
+++ b/include/pub_tool_basics.h
@@ -121,14 +121,14 @@
 
 #if defined(VGA_x86) || defined(VGA_amd64)
 #  define VG_LITTLEENDIAN 1
-#elif defined(VGA_ppc32)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #  define VG_BIGENDIAN 1
 #endif
 
 /* Regparmness */
 #if defined(VGA_x86)
 #  define VG_REGPARM(n)            __attribute__((regparm(n)))
-#elif defined(VGA_amd64) || defined(VGA_ppc32)
+#elif defined(VGA_amd64) || defined(VGA_ppc32) || defined(VGA_ppc64)
 #  define VG_REGPARM(n)            /* */
 #else
 #  error Unknown arch
diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h
index b569e85..fe4d847 100644
--- a/include/pub_tool_machine.h
+++ b/include/pub_tool_machine.h
@@ -47,6 +47,11 @@
 #  define VG_MAX_INSTR_SZB          4 
 #  define VG_CLREQ_SZB             24
 #  define VG_STACK_REDZONE_SZB      0
+#elif defined(VGA_ppc64)
+#  define VG_MIN_INSTR_SZB          4
+#  define VG_MAX_INSTR_SZB          4 
+#  define VG_CLREQ_SZB             24
+#  define VG_STACK_REDZONE_SZB      0
 #else
 #  error Unknown arch
 #endif
diff --git a/include/valgrind.h b/include/valgrind.h
index a712085..ff7fd72 100644
--- a/include/valgrind.h
+++ b/include/valgrind.h
@@ -81,7 +81,9 @@
 /* If we're not compiling for our target architecture, don't generate
    any inline asms.  Note that in this file we're using the compiler's
    CPP symbols for identifying architectures, which are different to
-   the ones we use within the rest of Valgrind. */
+   the ones we use within the rest of Valgrind.  Note, __powerpc__ is
+   active for both 32 and 64-bit PPC, whereas __powerpc64__ is only
+   active for the latter. */
 #if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__)
 #  ifndef NVALGRIND
 #    define NVALGRIND	1
@@ -165,7 +167,7 @@
   }
 #endif  /* __i386__ */
 
-#ifdef __powerpc__
+#if defined(__powerpc__) && !defined(__powerpc64__)
 #define VALGRIND_MAGIC_SEQUENCE(                                        \
         _zzq_rlval, _zzq_default, _zzq_request,                         \
         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4)                     \
@@ -190,7 +192,34 @@
                      : "memory");                                       \
     _zzq_rlval = (__typeof__(_zzq_rlval)) _zzq_tmp;                     \
   }
-#endif   /* __powerpc__ */
+#endif   /* __powerpc__ 32-bit only */
+
+#if defined(__powerpc__) && defined(__powerpc64__)
+#define VALGRIND_MAGIC_SEQUENCE(                                        \
+        _zzq_rlval, _zzq_default, _zzq_request,                         \
+        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4)                     \
+                                                                        \
+  { volatile unsigned long long int _zzq_args[5];                       \
+    register unsigned long long int _zzq_tmp __asm__("r3");             \
+    register volatile unsigned long long int *_zzq_ptr __asm__("r4");   \
+    _zzq_args[0] = (volatile unsigned long long int)(_zzq_request);     \
+    _zzq_args[1] = (volatile unsigned long long int)(_zzq_arg1);        \
+    _zzq_args[2] = (volatile unsigned long long int)(_zzq_arg2);        \
+    _zzq_args[3] = (volatile unsigned long long int)(_zzq_arg3);        \
+    _zzq_args[4] = (volatile unsigned long long int)(_zzq_arg4);        \
+    _zzq_ptr = _zzq_args;                                               \
+    __asm__ volatile("tw 0,3,27\n\t"                                    \
+                     "rotldi  0,0,61\n\t"                               \
+                     "rotldi  0,0,3\n\t"                                \
+                     "rotldi  0,0,13\n\t"                               \
+                     "rotldi  0,0,51\n\t"                               \
+                     "nop\n\t"                                          \
+                     : "=r" (_zzq_tmp)                                  \
+                     : "0" (_zzq_default), "r" (_zzq_ptr)               \
+                     : "memory");                                       \
+    _zzq_rlval = (__typeof__(_zzq_rlval)) _zzq_tmp;                     \
+  }
+#endif   /* __powerpc__ 64-bit only */
 
 /* Insert assembly code for other architectures here... */
 
diff --git a/include/vki-linux.h b/include/vki-linux.h
index 1eb61d6..5232596 100644
--- a/include/vki-linux.h
+++ b/include/vki-linux.h
@@ -70,6 +70,8 @@
 #  include "vki_posixtypes-amd64-linux.h"
 #elif defined(VGA_ppc32)
 #  include "vki_posixtypes-ppc32-linux.h"
+#elif defined(VGA_ppc64)
+#  include "vki_posixtypes-ppc64-linux.h"
 #else
 #  error Unknown platform
 #endif
@@ -150,6 +152,8 @@
 #  include "vki-amd64-linux.h"
 #elif defined(VGA_ppc32)
 #  include "vki-ppc32-linux.h"
+#elif defined(VGA_ppc64)
+#  include "vki-ppc64-linux.h"
 #else
 #  error Unknown platform
 #endif
diff --git a/include/vki-ppc64-linux.h b/include/vki-ppc64-linux.h
new file mode 100644
index 0000000..1e8c1b0
--- /dev/null
+++ b/include/vki-ppc64-linux.h
@@ -0,0 +1,750 @@
+
+/*--------------------------------------------------------------------*/
+/*--- PPC64/Linux-specific kernel interface.                       ---*/
+/*---                                ppc64-linux/vki-ppc64-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2005 Julian Seward
+      jseward@acm.org
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PPC64_LINUX_VKI_ARCH_H
+#define __PPC64_LINUX_VKI_ARCH_H
+
+// ppc64 is big-endian.
+#define VKI_BIG_ENDIAN  1
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/types.h
+//----------------------------------------------------------------------
+
+typedef __signed__ char __vki_s8;
+typedef unsigned char __vki_u8;
+
+typedef __signed__ short __vki_s16;
+typedef unsigned short __vki_u16;
+
+typedef __signed__ int __vki_s32;
+typedef unsigned int __vki_u32;
+
+typedef __signed__ long __vki_s64;
+typedef unsigned long __vki_u64;
+
+typedef struct {
+  __vki_u32 u[4];
+} __attribute((aligned(16))) __vki_vector128;
+
+typedef unsigned short vki_u16;
+
+typedef unsigned int vki_u32;
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/page.h
+//----------------------------------------------------------------------
+
+/* PAGE_SHIFT determines the page size */
+#define VKI_PAGE_SHIFT  12
+#define VKI_PAGE_SIZE   (1UL << VKI_PAGE_SHIFT)
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/signal.h
+//----------------------------------------------------------------------
+
+#define VKI_MINSIGSTKSZ     2048
+
+/* Next 9 non-blank lines asm-generic/signal.h */
+#define VKI_SIG_BLOCK          0 /* for blocking signals */
+#define VKI_SIG_UNBLOCK        1 /* for unblocking signals */
+#define VKI_SIG_SETMASK        2 /* for setting the signal mask */
+
+typedef void __vki_signalfn_t(int);
+typedef __vki_signalfn_t __user *__vki_sighandler_t;
+
+typedef void __vki_restorefn_t(void);
+typedef __vki_restorefn_t __user *__vki_sigrestore_t;
+
+#define VKI_SIG_DFL ((__vki_sighandler_t)0)     /* default signal handling */
+#define VKI_SIG_IGN ((__vki_sighandler_t)1)     /* ignore signal */
+
+/* Back in asm-ppc64/signal.h */
+#define _VKI_NSIG           64
+#define _VKI_NSIG_BPW       64
+#define _VKI_NSIG_WORDS     (_VKI_NSIG / _VKI_NSIG_BPW)
+
+typedef unsigned long vki_old_sigset_t;             /* at least 32 bits */
+
+typedef struct {
+  unsigned long sig[_VKI_NSIG_WORDS];
+} vki_sigset_t;
+
+#define VKI_SIGHUP           1
+#define VKI_SIGINT           2
+#define VKI_SIGQUIT          3
+#define VKI_SIGILL           4
+#define VKI_SIGTRAP          5
+#define VKI_SIGABRT          6
+#define VKI_SIGIOT           6
+#define VKI_SIGBUS           7
+#define VKI_SIGFPE           8
+#define VKI_SIGKILL          9
+#define VKI_SIGUSR1         10
+#define VKI_SIGSEGV         11
+#define VKI_SIGUSR2         12
+#define VKI_SIGPIPE         13
+#define VKI_SIGALRM         14
+#define VKI_SIGTERM         15
+#define VKI_SIGSTKFLT       16
+#define VKI_SIGCHLD         17
+#define VKI_SIGCONT         18
+#define VKI_SIGSTOP         19
+#define VKI_SIGTSTP         20
+#define VKI_SIGTTIN         21
+#define VKI_SIGTTOU         22
+#define VKI_SIGURG          23
+#define VKI_SIGXCPU         24
+#define VKI_SIGXFSZ         25
+#define VKI_SIGVTALRM       26
+#define VKI_SIGPROF         27
+#define VKI_SIGWINCH        28
+#define VKI_SIGIO           29
+#define VKI_SIGPOLL         VKI_SIGIO
+#define VKI_SIGPWR          30
+#define VKI_SIGSYS          31
+#define VKI_SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define VKI_SIGRTMIN        32
+#define VKI_SIGRTMAX        _VKI_NSIG
+
+#define VKI_SA_NOCLDSTOP    0x00000001u
+#define VKI_SA_NOCLDWAIT    0x00000002u
+#define VKI_SA_SIGINFO      0x00000004u
+#define VKI_SA_ONSTACK      0x08000000u
+#define VKI_SA_RESTART      0x10000000u
+#define VKI_SA_NODEFER      0x40000000u
+#define VKI_SA_RESETHAND    0x80000000u
+
+#define VKI_SA_NOMASK       VKI_SA_NODEFER
+#define VKI_SA_ONESHOT      VKI_SA_RESETHAND
+//#define VKI_SA_INTERRUPT    0x20000000u /* dummy -- ignored */
+
+#define VKI_SA_RESTORER     0x04000000u
+
+#define VKI_SS_ONSTACK      1
+#define VKI_SS_DISABLE      2
+
+// See comments on corresponding decls in vki-x86-linux.h re ksa_handler
+struct vki_old_sigaction {
+  __vki_sighandler_t ksa_handler;
+  vki_old_sigset_t sa_mask;
+  unsigned long sa_flags;
+  __vki_sigrestore_t sa_restorer;
+};
+
+struct vki_sigaction {
+  __vki_sighandler_t ksa_handler;
+  unsigned long sa_flags;
+  __vki_sigrestore_t sa_restorer;
+  vki_sigset_t sa_mask;               /* mask last for extensibility */
+};
+
+typedef struct vki_sigaltstack {
+  void __user *ss_sp;
+  int ss_flags;
+  vki_size_t ss_size;
+} vki_stack_t;
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/ptrace.h
+//----------------------------------------------------------------------
+
+#define VKI_PPC_REG unsigned long
+struct vki_pt_regs {
+  VKI_PPC_REG gpr[32];
+  VKI_PPC_REG nip;
+  VKI_PPC_REG msr;
+  VKI_PPC_REG orig_gpr3;      /* Used for restarting system calls */
+  VKI_PPC_REG ctr;
+  VKI_PPC_REG link;
+  VKI_PPC_REG xer;
+  VKI_PPC_REG ccr;
+  VKI_PPC_REG softe;          /* Soft enabled/disabled */
+  VKI_PPC_REG trap;           /* Reason for being here */
+  VKI_PPC_REG dar;            /* Fault registers */
+  VKI_PPC_REG dsisr;
+  VKI_PPC_REG result;         /* Result of a system call */
+};
+
+/* Kludge?  I don't know where this came from or if it is right. */
+#define vki_user_regs_struct vki_pt_regs
+
+#define VKI_PT_R0   0
+#define VKI_PT_R1   1
+#define VKI_PT_R2   2
+#define VKI_PT_R3   3
+#define VKI_PT_R4   4
+#define VKI_PT_R5   5
+#define VKI_PT_R6   6
+#define VKI_PT_R7   7
+#define VKI_PT_R8   8
+#define VKI_PT_R9   9
+#define VKI_PT_R10  10
+#define VKI_PT_R11  11
+#define VKI_PT_R12  12
+#define VKI_PT_R13  13
+#define VKI_PT_R14  14
+#define VKI_PT_R15  15
+#define VKI_PT_R16  16
+#define VKI_PT_R17  17
+#define VKI_PT_R18  18
+#define VKI_PT_R19  19
+#define VKI_PT_R20  20
+#define VKI_PT_R21  21
+#define VKI_PT_R22  22
+#define VKI_PT_R23  23
+#define VKI_PT_R24  24
+#define VKI_PT_R25  25
+#define VKI_PT_R26  26
+#define VKI_PT_R27  27
+#define VKI_PT_R28  28
+#define VKI_PT_R29  29
+#define VKI_PT_R30  30
+#define VKI_PT_R31  31
+#define VKI_PT_NIP  32
+#define VKI_PT_MSR  33
+#define VKI_PT_ORIG_R3 34
+#define VKI_PT_CTR  35
+#define VKI_PT_LNK  36
+#define VKI_PT_XER  37
+#define VKI_PT_CCR  38
+#define VKI_PT_SOFTE 39
+#define VKI_PT_RESULT 43
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/elf.h
+//----------------------------------------------------------------------
+
+#define VKI_ELF_NGREG       48      /* includes nip, msr, lr, etc. */
+#define VKI_ELF_NFPREG      33      /* includes fpscr */
+#define VKI_ELF_NVRREG      34      /* includes vscr & vrsave in split vectors */
+
+typedef unsigned long vki_elf_greg_t64;
+typedef vki_elf_greg_t64 vki_elf_gregset_t64[VKI_ELF_NGREG];
+
+typedef vki_elf_gregset_t64 vki_elf_gregset_t;
+
+typedef double vki_elf_fpreg_t;
+typedef vki_elf_fpreg_t vki_elf_fpregset_t[VKI_ELF_NFPREG];
+
+/* Altivec registers */
+/*
+ * The entries with indexes 0-31 contain the corresponding vector registers.
+ * The entry with index 32 contains the vscr as the last word (offset 12)
+ * within the quadword.  This allows the vscr to be stored as either a
+ * quadword (since it must be copied via a vector register to/from storage)
+ * or as a word.  The entry with index 33 contains the vrsave as the first
+ * word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface.  This allows signal handling and ptrace to use the same
+ * structures.  This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ *
+ * Note that it's _not_ compatible with 32 bits ucontext which stuffs the
+ * vrsave along with vscr and so only uses 33 vectors for the register set
+ */
+typedef __vki_vector128 vki_elf_vrreg_t;
+typedef vki_elf_vrreg_t vki_elf_vrregset_t[VKI_ELF_NVRREG];
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/sigcontext.h
+//----------------------------------------------------------------------
+
+struct vki_sigcontext {
+  unsigned long       _unused[4];
+  int                 signal;
+  int                 _pad0;
+  unsigned long       handler;
+  unsigned long       oldmask;
+  struct vki_pt_regs  __user *regs;
+  vki_elf_gregset_t   gp_regs;
+  vki_elf_fpregset_t  fp_regs;
+  /*
+   * To maintain compatibility with current implementations the sigcontext is
+   * extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t)
+   * followed by an unstructured (vmx_reserve) field of 69 doublewords.  This
+   * allows the array of vector registers to be quadword aligned independent of
+   * the alignment of the containing sigcontext or ucontext. It is the
+   * responsibility of the code setting the sigcontext to set this pointer to
+   * either NULL (if this processor does not support the VMX feature) or the
+   * address of the first quadword within the allocated (vmx_reserve) area.
+   *
+   * The pointer (v_regs) of vector type (elf_vrreg_t) is type compatible with
+   * an array of 34 quadword entries (elf_vrregset_t).  The entries with
+   * indexes 0-31 contain the corresponding vector registers.  The entry with
+   * index 32 contains the vscr as the last word (offset 12) within the
+   * quadword.  This allows the vscr to be stored as either a quadword (since
+   * it must be copied via a vector register to/from storage) or as a word.
+   * The entry with index 33 contains the vrsave as the first word (offset 0)
+   * within the quadword.
+   */
+  vki_elf_vrreg_t  __user *v_regs;
+  long             vmx_reserve[VKI_ELF_NVRREG+VKI_ELF_NVRREG+1];
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/mman.h
+//----------------------------------------------------------------------
+
+#define VKI_PROT_NONE       0x0             /* page can not be accessed */
+#define VKI_PROT_READ       0x1             /* page can be read */
+#define VKI_PROT_WRITE      0x2             /* page can be written */
+#define VKI_PROT_EXEC       0x4             /* page can be executed */
+#define VKI_PROT_GROWSDOWN  0x01000000      /* mprotect flag: extend
+					       change to start of
+					       growsdown vma */
+#define VKI_PROT_GROWSUP    0x02000000      /* mprotect flag: extend
+					       change to end of
+					       growsup vma */
+
+#define VKI_MAP_SHARED      0x01            /* Share changes */
+#define VKI_MAP_PRIVATE     0x02            /* Changes are private */
+#define VKI_MAP_FIXED       0x10            /* Interpret addr exactly */
+#define VKI_MAP_ANONYMOUS   0x20            /* don't use a file */
+#define VKI_MAP_NORESERVE   0x40            /* don't reserve swap pages */
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/fcntl.h
+//----------------------------------------------------------------------
+
+#define VKI_O_RDONLY             00
+#define VKI_O_WRONLY             01
+#define VKI_O_RDWR               02
+#define VKI_O_CREAT            0100 /* not fcntl */
+#define VKI_O_EXCL             0200 /* not fcntl */
+#define VKI_O_TRUNC           01000 /* not fcntl */
+#define VKI_O_APPEND          02000
+#define VKI_O_NONBLOCK        04000
+
+#define VKI_F_DUPFD         0       /* dup */
+#define VKI_F_GETFD         1       /* get close_on_exec */
+#define VKI_F_SETFD         2       /* set/clear close_on_exec */
+#define VKI_F_GETFL         3       /* get file->f_flags */
+#define VKI_F_SETFL         4       /* set file->f_flags */
+#define VKI_F_GETLK         5
+#define VKI_F_SETLK         6
+#define VKI_F_SETLKW        7
+
+#define VKI_F_SETOWN        8       /*  for sockets. */
+#define VKI_F_GETOWN        9       /*  for sockets. */
+#define VKI_F_SETSIG        10      /*  for sockets. */
+#define VKI_F_GETSIG        11      /*  for sockets. */
+
+/* for F_[GET|SET]FL */
+#define VKI_FD_CLOEXEC  1  /* actually anything with low bit set goes */
+
+#define VKI_F_LINUX_SPECIFIC_BASE   1024
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/resource.h
+//----------------------------------------------------------------------
+
+// which just does #include <asm-generic/resource.h>
+
+#define VKI_RLIMIT_DATA             2       /* max data size */
+#define VKI_RLIMIT_STACK            3       /* max stack size */
+#define VKI_RLIMIT_CORE             4       /* max core file size */
+#define VKI_RLIMIT_NOFILE           7       /* max number of open files */
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/socket.h
+//----------------------------------------------------------------------
+
+#define VKI_SOL_SOCKET      1
+
+#define VKI_SO_TYPE         3
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/sockios.h
+//----------------------------------------------------------------------
+
+#define VKI_SIOCSPGRP       0x8902
+#define VKI_SIOCGPGRP       0x8904
+#define VKI_SIOCGSTAMP      0x8906          /* Get stamp */
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/stat.h
+//----------------------------------------------------------------------
+
+struct vki_stat {
+  unsigned long   st_dev;
+  unsigned long   st_ino;
+  unsigned short  st_nlink;
+  unsigned short  st_mode;
+  unsigned short  st_uid;
+  unsigned short  st_gid;
+  unsigned long   st_rdev;
+  long            st_size;
+  unsigned long   st_blksize;
+  unsigned long   st_blocks;
+  unsigned long   st_atime;
+  unsigned long   st_atime_nsec;
+  unsigned long   st_mtime;
+  unsigned long   st_mtime_nsec;
+  unsigned long   st_ctime;
+  unsigned long   st_ctime_nsec;
+  unsigned long   __unused4;
+  unsigned long   __unused5;
+  unsigned long   __unused6;
+};
+
+#define VKI_STAT_HAVE_NSEC 1
+
+/* This matches struct stat64 in glibc2.1. Only used for 32 bit. */
+struct vki_stat64 {
+  unsigned long st_dev;           /* Device.  */
+  unsigned long st_ino;           /* File serial number.  */
+  unsigned int st_mode;           /* File mode.  */
+  unsigned int st_nlink;          /* Link count.  */
+  unsigned int st_uid;            /* User ID of the file's owner.  */
+  unsigned int st_gid;            /* Group ID of the file's group. */
+  unsigned long st_rdev;          /* Device number, if device.  */
+  unsigned short __pad2;
+  long st_size;                   /* Size of file, in bytes.  */
+  int  st_blksize;                /* Optimal block size for I/O.  */
+
+  long st_blocks;                 /* Number 512-byte blocks allocated. */
+  int   st_atime;                 /* Time of last access.  */
+  int   st_atime_nsec;
+  int   st_mtime;                 /* Time of last modification.  */
+  int   st_mtime_nsec;
+  int   st_ctime;                 /* Time of last status change.  */
+  int   st_ctime_nsec;
+  unsigned int   __unused4;
+  unsigned int   __unused5;
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/statfs.h
+//----------------------------------------------------------------------
+
+struct vki_statfs {
+  long f_type;
+  long f_bsize;
+  long f_blocks;
+  long f_bfree;
+  long f_bavail;
+  long f_files;
+  long f_ffree;
+  __vki_kernel_fsid_t f_fsid;
+  long f_namelen;
+  long f_frsize;
+  long f_spare[5];
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/termios.h
+//----------------------------------------------------------------------
+
+struct vki_winsize {
+  unsigned short ws_row;
+  unsigned short ws_col;
+  unsigned short ws_xpixel;
+  unsigned short ws_ypixel;
+};
+
+#define VKI_NCC 10
+struct vki_termio {
+  unsigned short c_iflag;         /* input mode flags */
+  unsigned short c_oflag;         /* output mode flags */
+  unsigned short c_cflag;         /* control mode flags */
+  unsigned short c_lflag;         /* local mode flags */
+  unsigned char c_line;           /* line discipline */
+  unsigned char c_cc[VKI_NCC];    /* control characters */
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/termbits.h
+//----------------------------------------------------------------------
+
+typedef unsigned char   vki_cc_t;
+typedef unsigned int    vki_speed_t;
+typedef unsigned int    vki_tcflag_t;
+
+#define VKI_NCCS 19
+struct vki_termios {
+  vki_tcflag_t c_iflag;               /* input mode flags */
+  vki_tcflag_t c_oflag;               /* output mode flags */
+  vki_tcflag_t c_cflag;               /* control mode flags */
+  vki_tcflag_t c_lflag;               /* local mode flags */
+  vki_cc_t c_cc[VKI_NCCS];            /* control characters */
+  vki_cc_t c_line;                    /* line discipline (== c_cc[19]) */
+  vki_speed_t c_ispeed;               /* input speed */
+  vki_speed_t c_ospeed;               /* output speed */
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/ioctl.h
+//----------------------------------------------------------------------
+
+#define _VKI_IOC_NRBITS     8
+#define _VKI_IOC_TYPEBITS   8
+#define _VKI_IOC_SIZEBITS   13
+#define _VKI_IOC_DIRBITS    3
+
+#define _VKI_IOC_NRMASK     ((1 << _VKI_IOC_NRBITS)-1)
+#define _VKI_IOC_TYPEMASK   ((1 << _VKI_IOC_TYPEBITS)-1)
+#define _VKI_IOC_SIZEMASK   ((1 << _VKI_IOC_SIZEBITS)-1)
+#define _VKI_IOC_DIRMASK    ((1 << _VKI_IOC_DIRBITS)-1)
+
+#define _VKI_IOC_NRSHIFT    0
+#define _VKI_IOC_TYPESHIFT  (_VKI_IOC_NRSHIFT+_VKI_IOC_NRBITS)
+#define _VKI_IOC_SIZESHIFT  (_VKI_IOC_TYPESHIFT+_VKI_IOC_TYPEBITS)
+#define _VKI_IOC_DIRSHIFT   (_VKI_IOC_SIZESHIFT+_VKI_IOC_SIZEBITS)
+
+/*
+ * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
+ * And this turns out useful to catch old ioctl numbers in header
+ * files for us.
+ */
+#define _VKI_IOC_NONE       1U
+#define _VKI_IOC_READ       2U
+#define _VKI_IOC_WRITE      4U
+
+#define _VKI_IOC(dir,type,nr,size) \
+        (((dir)  << _VKI_IOC_DIRSHIFT) | \
+         ((type) << _VKI_IOC_TYPESHIFT) | \
+         ((nr)   << _VKI_IOC_NRSHIFT) | \
+         ((size) << _VKI_IOC_SIZESHIFT))
+
+/* provoke compile error for invalid uses of size argument */
+extern unsigned int __invalid_size_argument_for_IOC;
+#define _VKI_IOC_TYPECHECK(t) \
+       ((sizeof(t) == sizeof(t[1]) && \
+         sizeof(t) < (1 << _VKI_IOC_SIZEBITS)) ? \
+         sizeof(t) : __invalid_size_argument_for_IOC)
+
+/* used to create numbers */
+#define _VKI_IO(type,nr)            _VKI_IOC(_VKI_IOC_NONE,(type),(nr),0)
+#define _VKI_IOR(type,nr,size)      _VKI_IOC(_VKI_IOC_READ,(type),(nr), \
+                                       (_VKI_IOC_TYPECHECK(size)))
+#define _VKI_IOW(type,nr,size)      _VKI_IOC(_VKI_IOC_WRITE,(type),(nr), \
+                                       (_VKI_IOC_TYPECHECK(size)))
+#define _VKI_IOWR(type,nr,size)     _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE, \
+                                       (type),(nr),(_VKI_IOC_TYPECHECK(size)))
+#define _VKI_IOR_BAD(type,nr,size)  _VKI_IOC(_VKI_IOC_READ,(type),(nr), \
+                                       sizeof(size))
+#define _VKI_IOW_BAD(type,nr,size)  _VKI_IOC(_VKI_IOC_WRITE,(type),(nr), \
+                                       sizeof(size))
+#define _VKI_IOWR_BAD(type,nr,size) _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE, \
+                                       (type),(nr),sizeof(size))
+
+/* used to decode them.. */
+#define _VKI_IOC_DIR(nr)        (((nr) >> _VKI_IOC_DIRSHIFT) & _VKI_IOC_DIRMASK)
+#define _VKI_IOC_TYPE(nr)       (((nr) >> _VKI_IOC_TYPESHIFT) & _VKI_IOC_TYPEMASK)
+#define _VKI_IOC_NR(nr)         (((nr) >> _VKI_IOC_NRSHIFT) & _VKI_IOC_NRMASK)
+#define _VKI_IOC_SIZE(nr)       (((nr) >> _VKI_IOC_SIZESHIFT) & _VKI_IOC_SIZEMASK)
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/ioctls.h
+//----------------------------------------------------------------------
+
+#define VKI_TCGETS          _VKI_IOR('t', 19, struct vki_termios)
+#define VKI_TCSETS          _VKI_IOW('t', 20, struct vki_termios)
+#define VKI_TCSETSW         _VKI_IOW('t', 21, struct vki_termios)
+#define VKI_TCSETSF         _VKI_IOW('t', 22, struct vki_termios)
+#define VKI_TCGETA          _VKI_IOR('t', 23, struct vki_termio)
+#define VKI_TCSETA          _VKI_IOW('t', 24, struct vki_termio)
+#define VKI_TCSETAW         _VKI_IOW('t', 25, struct vki_termio)
+#define VKI_TCSETAF         _VKI_IOW('t', 28, struct vki_termio)
+#define VKI_TCSBRK          _VKI_IO('t', 29)
+#define VKI_TCXONC          _VKI_IO('t', 30)
+#define VKI_TCFLSH          _VKI_IO('t', 31)
+#define VKI_TIOCSCTTY       0x540E
+#define VKI_TIOCGPGRP       _VKI_IOR('t', 119, int)
+#define VKI_TIOCSPGRP       _VKI_IOW('t', 118, int)
+#define VKI_TIOCOUTQ        _VKI_IOR('t', 115, int)     /* output queue size */
+#define VKI_TIOCGWINSZ      _VKI_IOR('t', 104, struct vki_winsize)
+#define VKI_TIOCSWINSZ      _VKI_IOW('t', 103, struct vki_winsize)
+#define VKI_TIOCMGET        0x5415
+#define VKI_TIOCMBIS        0x5416
+#define VKI_TIOCMBIC        0x5417
+#define VKI_TIOCMSET        0x5418
+#define VKI_FIONREAD        _VKI_IOR('f', 127, int)
+#define VKI_TIOCLINUX       0x541C
+#define VKI_FIONBIO         _VKI_IOW('f', 126, int)
+#define VKI_TCSBRKP         0x5425  /* Needed for POSIX tcsendbreak() */
+#define VKI_TIOCGPTN        _VKI_IOR('T',0x30, unsigned int) 
+                            /* Get Pty Number (of pty-mux device) */
+#define VKI_TIOCSPTLCK      _VKI_IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define VKI_FIOASYNC        _VKI_IOW('f', 125, int)
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/poll.h
+//----------------------------------------------------------------------
+
+#define VKI_POLLIN          0x0001
+
+struct vki_pollfd {
+  int fd;
+  short events;
+  short revents;
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/user.h
+//----------------------------------------------------------------------
+
+// Not sure what's needed from here
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/elf.h
+//----------------------------------------------------------------------
+
+// Not sure what's needed from here
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/ucontext.h
+//----------------------------------------------------------------------
+
+struct vki_ucontext {
+  unsigned long         uc_flags;
+  struct vki_ucontext  *uc_link;
+  vki_stack_t           uc_stack;
+  vki_sigset_t          uc_sigmask;
+  vki_sigset_t          __unused[15]; /* Allow for uc_sigmask growth */
+  struct vki_sigcontext uc_mcontext;  /* last for extensibility */
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/ipcbuf.h
+//----------------------------------------------------------------------
+
+struct vki_ipc64_perm
+{
+  __vki_kernel_key_t  key;
+  __vki_kernel_uid_t  uid;
+  __vki_kernel_gid_t  gid;
+  __vki_kernel_uid_t  cuid;
+  __vki_kernel_gid_t  cgid;
+  __vki_kernel_mode_t mode;
+  unsigned int        seq;
+  unsigned int        __pad1;
+  unsigned long       __unused1;
+  unsigned long       __unused2;
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/sembuf.h
+//----------------------------------------------------------------------
+
+struct vki_semid64_ds {
+  struct vki_ipc64_perm sem_perm;     /* permissions .. see ipc.h */
+  __vki_kernel_time_t   sem_otime;      /* last semop time */
+  __vki_kernel_time_t   sem_ctime;      /* last change time */
+  unsigned long         sem_nsems;      /* no. of semaphores in array */
+  unsigned long         __unused1;
+  unsigned long         __unused2;
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/msgbuf.h
+//----------------------------------------------------------------------
+
+struct vki_msqid64_ds {
+  struct vki_ipc64_perm msg_perm;
+  __vki_kernel_time_t   msg_stime;      /* last msgsnd time */
+  __vki_kernel_time_t   msg_rtime;      /* last msgrcv time */
+  __vki_kernel_time_t   msg_ctime;      /* last change time */
+  unsigned long         msg_cbytes;      /* current number of bytes on queue */
+  unsigned long         msg_qnum;        /* number of messages in queue */
+  unsigned long         msg_qbytes;      /* max number of bytes on queue */
+  __vki_kernel_pid_t    msg_lspid;       /* pid of last msgsnd */
+  __vki_kernel_pid_t    msg_lrpid;       /* last receive pid */
+  unsigned long         __unused1;
+  unsigned long         __unused2;
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/ipc.h
+//----------------------------------------------------------------------
+
+// this just does #include <asm-generic/ipc.h>
+
+struct vki_ipc_kludge {
+  struct vki_msgbuf __user *msgp;
+  long msgtyp;
+};
+
+#define VKI_SEMOP            1
+#define VKI_SEMGET           2
+#define VKI_SEMCTL           3
+#define VKI_SEMTIMEDOP       4
+#define VKI_MSGSND          11
+#define VKI_MSGRCV          12
+#define VKI_MSGGET          13
+#define VKI_MSGCTL          14
+#define VKI_SHMAT           21
+#define VKI_SHMDT           22
+#define VKI_SHMGET          23
+#define VKI_SHMCTL          24
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/shmbuf.h
+//----------------------------------------------------------------------
+
+struct vki_shmid64_ds {
+  struct vki_ipc64_perm       shm_perm;       /* operation perms */
+  __vki_kernel_time_t         shm_atime;      /* last attach time */
+  __vki_kernel_time_t         shm_dtime;      /* last detach time */
+  __vki_kernel_time_t         shm_ctime;      /* last change time */
+  vki_size_t                  shm_segsz;      /* size of segment (bytes) */
+  __vki_kernel_pid_t          shm_cpid;       /* pid of creator */
+  __vki_kernel_pid_t          shm_lpid;       /* pid of last operator */
+  unsigned long               shm_nattch;     /* no. of current attaches */
+  unsigned long               __unused1;
+  unsigned long               __unused2;
+};
+
+struct vki_shminfo64 {
+  unsigned long   shmmax;
+  unsigned long   shmmin;
+  unsigned long   shmmni;
+  unsigned long   shmseg;
+  unsigned long   shmall;
+  unsigned long   __unused1;
+  unsigned long   __unused2;
+  unsigned long   __unused3;
+  unsigned long   __unused4;
+};
+
+//----------------------------------------------------------------------
+// end
+//----------------------------------------------------------------------
+
+#endif // __PPC64_LINUX_VKI_ARCH_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/vki_posixtypes-ppc64-linux.h b/include/vki_posixtypes-ppc64-linux.h
new file mode 100644
index 0000000..d9d38cb
--- /dev/null
+++ b/include/vki_posixtypes-ppc64-linux.h
@@ -0,0 +1,75 @@
+
+/*--------------------------------------------------------------------*/
+/*--- PPC64/Linux-specific kernel interface: posix types.          ---*/
+/*---                                 vki_posixtypes-ppc64-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2005 Julian Seward
+      jseward@acm.org
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PPC64_LINUX_VKI_ARCH_POSIXTYPES_H
+#define __PPC64_LINUX_VKI_ARCH_POSIXTYPES_H
+
+//----------------------------------------------------------------------
+// From linux-2.6.13/include/asm-ppc64/posix_types.h
+//----------------------------------------------------------------------
+
+typedef unsigned long   __vki_kernel_ino_t;
+typedef unsigned long   __vki_kernel_nlink_t;
+typedef unsigned int    __vki_kernel_mode_t;
+typedef long            __vki_kernel_off_t;
+typedef long long       __vki_kernel_loff_t;
+typedef int             __vki_kernel_pid_t;
+typedef int             __vki_kernel_ipc_pid_t;
+typedef unsigned int    __vki_kernel_uid_t;
+typedef unsigned int    __vki_kernel_gid_t;
+typedef unsigned long   __vki_kernel_size_t;
+typedef long            __vki_kernel_ssize_t;
+typedef long            __vki_kernel_ptrdiff_t;
+typedef long            __vki_kernel_time_t;
+typedef int             __vki_kernel_timer_t;
+typedef int             __vki_kernel_clockid_t;
+typedef long            __vki_kernel_suseconds_t;
+typedef long            __vki_kernel_clock_t;
+typedef int             __vki_kernel_daddr_t;
+typedef char *          __vki_kernel_caddr_t;
+typedef unsigned short  __vki_kernel_uid16_t;
+typedef unsigned short  __vki_kernel_gid16_t;
+typedef unsigned int    __vki_kernel_uid32_t;
+typedef unsigned int    __vki_kernel_gid32_t;
+
+typedef unsigned int    __vki_kernel_old_uid_t;
+typedef unsigned int    __vki_kernel_old_gid_t;
+typedef unsigned long   __vki_kernel_old_dev_t;
+
+typedef struct {
+  int     val[2];
+} __vki_kernel_fsid_t;
+
+#endif // __PPC64_LINUX_VKI_ARCH_POSIXTYPES_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/lackey/Makefile.am b/lackey/Makefile.am
index b25f67a..50b1b07 100644
--- a/lackey/Makefile.am
+++ b/lackey/Makefile.am
@@ -10,6 +10,9 @@
 if VG_PPC32_LINUX
 noinst_PROGRAMS += lackey-ppc32-linux
 endif
+if VG_PPC64_LINUX
+noinst_PROGRAMS += lackey-ppc64-linux
+endif
 
 LACKEY_SOURCES_COMMON = lk_main.c
 
@@ -33,3 +36,10 @@
 lackey_ppc32_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC32_LINUX)
 lackey_ppc32_linux_LDADD        = $(TOOL_LDADD_PPC32_LINUX)
 lackey_ppc32_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC32_LINUX)
+
+lackey_ppc64_linux_SOURCES      = $(LACKEY_SOURCES_COMMON)
+lackey_ppc64_linux_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+lackey_ppc64_linux_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX)
+lackey_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_LINUX)
+lackey_ppc64_linux_LDADD        = $(TOOL_LDADD_PPC64_LINUX)
+lackey_ppc64_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC64_LINUX)
diff --git a/massif/Makefile.am b/massif/Makefile.am
index ca30d72..39480dd 100644
--- a/massif/Makefile.am
+++ b/massif/Makefile.am
@@ -12,6 +12,9 @@
 if VG_PPC32_LINUX
 noinst_PROGRAMS += massif-ppc32-linux vgpreload_massif-ppc32-linux.so
 endif
+if VG_PPC64_LINUX
+noinst_PROGRAMS += massif-ppc64-linux vgpreload_massif-ppc64-linux.so
+endif
 
 vgpreload_massif_x86_linux_so_SOURCES      = 
 vgpreload_massif_x86_linux_so_CPPFLAGS     = $(AM_CPPFLAGS_X86_LINUX)
@@ -37,6 +40,14 @@
 	$(PRELOAD_LDFLAGS_PPC32_LINUX) \
 	$(LIBREPLACEMALLOC_LDFLAGS_PPC32_LINUX)
 
+vgpreload_massif_ppc64_linux_so_SOURCES      = 
+vgpreload_massif_ppc64_linux_so_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+vgpreload_massif_ppc64_linux_so_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX) $(AM_CFLAGS_PIC)
+vgpreload_massif_ppc64_linux_so_DEPENDENCIES = $(LIBREPLACEMALLOC_PPC64_LINUX)
+vgpreload_massif_ppc64_linux_so_LDFLAGS      = \
+	$(PRELOAD_LDFLAGS_PPC64_LINUX) \
+	$(LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX)
+
 MASSIF_SOURCES_COMMON = ms_main.c
 
 massif_x86_linux_SOURCES      = $(MASSIF_SOURCES_COMMON)
@@ -59,3 +70,10 @@
 massif_ppc32_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC32_LINUX)
 massif_ppc32_linux_LDADD        = $(TOOL_LDADD_PPC32_LINUX)
 massif_ppc32_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC32_LINUX)
+
+massif_ppc64_linux_SOURCES      = $(MASSIF_SOURCES_COMMON)
+massif_ppc64_linux_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+massif_ppc64_linux_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX)
+massif_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_LINUX)
+massif_ppc64_linux_LDADD        = $(TOOL_LDADD_PPC64_LINUX)
+massif_ppc64_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC64_LINUX)
diff --git a/memcheck/Makefile.am b/memcheck/Makefile.am
index a47a8e5..b003e4c 100644
--- a/memcheck/Makefile.am
+++ b/memcheck/Makefile.am
@@ -10,6 +10,9 @@
 if VG_PPC32_LINUX
 noinst_PROGRAMS += memcheck-ppc32-linux vgpreload_memcheck-ppc32-linux.so
 endif
+if VG_PPC64_LINUX
+noinst_PROGRAMS += memcheck-ppc64-linux vgpreload_memcheck-ppc64-linux.so
+endif
 
 VGPRELOAD_MEMCHECK_SOURCES_COMMON = mac_replace_strmem.c
 
@@ -40,6 +43,15 @@
 	$(PRELOAD_LDFLAGS_PPC32_LINUX) \
 	$(LIBREPLACEMALLOC_LDFLAGS_PPC32_LINUX)
 
+vgpreload_memcheck_ppc64_linux_so_SOURCES      = $(VGPRELOAD_MEMCHECK_SOURCES_COMMON)
+vgpreload_memcheck_ppc64_linux_so_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+vgpreload_memcheck_ppc64_linux_so_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX) $(AM_CFLAGS_PIC) -O2
+vgpreload_memcheck_ppc64_linux_so_CCASFLAGS    = $(AM_CCASFLAGS_PPC64_LINUX)
+vgpreload_memcheck_ppc64_linux_so_DEPENDENCIES = $(LIBREPLACEMALLOC_PPC64_LINUX)
+vgpreload_memcheck_ppc64_linux_so_LDFLAGS      = \
+	$(PRELOAD_LDFLAGS_PPC64_LINUX) \
+	$(LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX)
+
 MEMCHECK_SOURCES_COMMON = \
 	mac_leakcheck.c \
 	mac_malloc_wrappers.c \
@@ -71,6 +83,14 @@
 memcheck_ppc32_linux_LDADD        = $(TOOL_LDADD_PPC32_LINUX)
 memcheck_ppc32_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC32_LINUX)
 
+memcheck_ppc64_linux_SOURCES      = $(MEMCHECK_SOURCES_COMMON)
+memcheck_ppc64_linux_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+memcheck_ppc64_linux_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX) -O2
+memcheck_ppc64_linux_CCASFLAGS    = $(AM_CCASFLAGS_PPC64_LINUX)
+memcheck_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_LINUX)
+memcheck_ppc64_linux_LDADD        = $(TOOL_LDADD_PPC64_LINUX)
+memcheck_ppc64_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC64_LINUX)
+
 mcincludedir = $(includedir)/valgrind
 
 mcinclude_HEADERS = \
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index 03b245c..3f424fd 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -8,6 +8,9 @@
 if VG_PPC32_LINUX
 SUBDIRS += ppc32
 endif
+if VG_PPC64_LINUX
+SUBDIRS += ppc64
+endif
 
 DIST_SUBDIRS = ${VG_ARCH_ALL} .
 
diff --git a/none/Makefile.am b/none/Makefile.am
index 01a501f..aa340bb 100644
--- a/none/Makefile.am
+++ b/none/Makefile.am
@@ -10,6 +10,9 @@
 if VG_PPC32_LINUX
 noinst_PROGRAMS += none-ppc32-linux
 endif
+if VG_PPC64_LINUX
+noinst_PROGRAMS += none-ppc64-linux
+endif
 
 NONE_SOURCES_COMMON = nl_main.c
 
@@ -33,3 +36,10 @@
 none_ppc32_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC32_LINUX)
 none_ppc32_linux_LDADD        = $(TOOL_LDADD_PPC32_LINUX)
 none_ppc32_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC32_LINUX)
+
+none_ppc64_linux_SOURCES      = $(NONE_SOURCES_COMMON)
+none_ppc64_linux_CPPFLAGS     = $(AM_CPPFLAGS_PPC64_LINUX)
+none_ppc64_linux_CFLAGS       = $(AM_CFLAGS_PPC64_LINUX)
+none_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_LINUX)
+none_ppc64_linux_LDADD        = $(TOOL_LDADD_PPC64_LINUX)
+none_ppc64_linux_LDFLAGS      = $(TOOL_LDFLAGS_PPC64_LINUX)
diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
index 3360c76..9668140 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -8,6 +8,9 @@
 if VG_PPC32_LINUX
 SUBDIRS += ppc32
 endif
+if VG_PPC64_LINUX
+SUBDIRS += ppc64
+endif
 
 DIST_SUBDIRS = ${VG_ARCH_ALL} .