Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 902460 Details for
Bug 1105030
valgrind do not build on ppc64le archi
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
valgrind_ppc64le_step2.patch
valgrind_ppc64le_step2.patch (text/plain), 183.46 KB, created by
Michel Normand
on 2014-06-05 09:12:24 UTC
(
hide
)
Description:
valgrind_ppc64le_step2.patch
Filename:
MIME Type:
Creator:
Michel Normand
Created:
2014-06-05 09:12:24 UTC
Size:
183.46 KB
patch
obsolete
>From 3bc48bb0a56f0f48c727efe6d414fddf57a548f0 Mon Sep 17 00:00:00 2001 >From: Carl Love <carll@us.ibm.com> >Date: Mon, 2 Jun 2014 11:07:22 -0500 >Subject: [PATCH 2/3] POWER PC, add the functional Little Endian support > >The IBM POWER processor now supports both Big Endian and Little Endian. >The ABI for Little Endian also changes. Specifically, the function >descriptor is not used, the stack size changed, accessing the TOC >changed. Functions now have a local and a global entry point. Register >r2 contains the TOC for local calls and register r12 contains the TOC >for global calls. This patch makes the functional changes to the >Valgrind tool. The patch makes the changes needed for the >none/tests/ppc32 and none/tests/ppc64 Makefile.am. A number of the >ppc specific tests have Endian dependencies that are not fixed in >this patch. They are fixed in the next patch. > >Signed-off-by: Carl Love <carll@us.ibm.com> >--- > Makefile.all.am | 23 - > Makefile.tool.am | 11 > VEX/priv/guest_ppc_helpers.c | 23 - > VEX/priv/guest_ppc_toIR.c | 432 +++++++++++++----- > VEX/priv/host_ppc_defs.c | 22 > VEX/priv/host_ppc_isel.c | 171 +++++-- > VEX/priv/main_main.c | 8 > configure.ac | 23 - > coregrind/launcher-linux.c | 5 > coregrind/m_coredump/coredump-elf.c | 23 - > coregrind/m_debuginfo/debuginfo.c | 22 > coregrind/m_debuginfo/priv_storage.h | 5 > coregrind/m_debuginfo/readelf.c | 74 +++ > coregrind/m_dispatch/dispatch-ppc64-linux.S | 97 +++- > coregrind/m_initimg/initimg-linux.c | 22 > coregrind/m_libcsetjmp.c | 112 ++++ > coregrind/m_main.c | 57 ++ > coregrind/m_redir.c | 44 + > coregrind/m_sigframe/sigframe-ppc64-linux.c | 13 > coregrind/m_signals.c | 16 > coregrind/m_stacktrace.c | 6 > coregrind/m_syscall.c | 38 + > coregrind/m_syswrap/syscall-ppc64-linux.S | 26 - > coregrind/m_syswrap/syswrap-main.c | 29 + > coregrind/m_syswrap/syswrap-ppc64-linux.c | 130 +++++ > coregrind/m_trampoline.S | 40 + > coregrind/m_translate.c | 88 +++ > coregrind/m_ume/elf.c | 16 > coregrind/m_ume/macho.c | 2 > coregrind/pub_core_machine.h | 11 > coregrind/vgdb-invoker-ptrace.c | 14 > helgrind/hg_main.c | 1 > include/pub_tool_basics.h | 2 > include/pub_tool_debuginfo.h | 1 > include/pub_tool_redir.h | 1 > include/valgrind.h | 639 +++++++++++++++++++++++++++- > include/vki/vki-ppc64-linux.h | 5 > memcheck/mc_machine.c | 4 > tests/arch_test.c | 4 > 39 files changed, 1975 insertions(+), 285 deletions(-) > >Index: valgrind-3.9.0-svn20140513r13961/Makefile.all.am >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/Makefile.all.am >+++ valgrind-3.9.0-svn20140513r13961/Makefile.all.am >@@ -228,15 +228,16 @@ if VGCONF_PLATVARIANT_IS_ANDROID > PRELOAD_LDFLAGS_COMMON_LINUX += -nostdlib > endif > >-PRELOAD_LDFLAGS_X86_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >-PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >-PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >-PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >-PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >-PRELOAD_LDFLAGS_ARM64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >-PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386 >-PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64 >-PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >-PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >-PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >+PRELOAD_LDFLAGS_X86_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >+PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >+PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >+PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >+PRELOAD_LDFLAGS_PPC64LE_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >+PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >+PRELOAD_LDFLAGS_ARM64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >+PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386 >+PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64 >+PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >+PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ >+PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ > >Index: valgrind-3.9.0-svn20140513r13961/Makefile.tool.am >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/Makefile.tool.am >+++ valgrind-3.9.0-svn20140513r13961/Makefile.tool.am >@@ -49,6 +49,9 @@ TOOL_LDFLAGS_PPC32_LINUX = \ > TOOL_LDFLAGS_PPC64_LINUX = \ > $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@ > >+TOOL_LDFLAGS_PPC64LE_LINUX = \ >+ $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@ >+ > TOOL_LDFLAGS_ARM_LINUX = \ > $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@ > >@@ -105,6 +108,9 @@ LIBREPLACEMALLOC_PPC32_LINUX = \ > LIBREPLACEMALLOC_PPC64_LINUX = \ > $(top_builddir)/coregrind/libreplacemalloc_toolpreload-ppc64-linux.a > >+LIBREPLACEMALLOC_PPC64LE_LINUX = \ >+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-ppc64le-linux.a >+ > LIBREPLACEMALLOC_ARM_LINUX = \ > $(top_builddir)/coregrind/libreplacemalloc_toolpreload-arm-linux.a > >@@ -146,6 +152,11 @@ LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX = \ > $(LIBREPLACEMALLOC_PPC64_LINUX) \ > -Wl,--no-whole-archive > >+LIBREPLACEMALLOC_LDFLAGS_PPC64LE_LINUX = \ >+ -Wl,--whole-archive \ >+ $(LIBREPLACEMALLOC_PPC64LE_LINUX) \ >+ -Wl,--no-whole-archive >+ > LIBREPLACEMALLOC_LDFLAGS_ARM_LINUX = \ > -Wl,--whole-archive \ > $(LIBREPLACEMALLOC_ARM_LINUX) \ >Index: valgrind-3.9.0-svn20140513r13961/VEX/priv/guest_ppc_helpers.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/VEX/priv/guest_ppc_helpers.c >+++ valgrind-3.9.0-svn20140513r13961/VEX/priv/guest_ppc_helpers.c >@@ -45,6 +45,12 @@ > #include "guest_generic_bb_to_IR.h" > #include "guest_ppc_defs.h" > >+#if defined(VGP_ppc64le_linux) >+#define IENDIANESS Iend_LE >+#else >+#define IENDIANESS Iend_BE >+#endif >+ > > /* This file contains helper functions for ppc32 and ppc64 guest code. > Calls to these functions are generated by the back end. These >@@ -157,6 +163,7 @@ void ppc64g_dirtyhelper_LVS ( VexGuestPP > { > UChar ref[32]; > ULong i; >+ Int k; > /* ref[] used to be a static const array, but this doesn't work on > ppc64 because VEX doesn't load the TOC pointer for the call here, > and so we wind up picking up some totally random other data. >@@ -179,10 +186,18 @@ void ppc64g_dirtyhelper_LVS ( VexGuestPP > pU128_src = (U128*)&ref[sh]; > pU128_dst = (U128*)( ((UChar*)gst) + vD_off ); > >- (*pU128_dst)[0] = (*pU128_src)[0]; >- (*pU128_dst)[1] = (*pU128_src)[1]; >- (*pU128_dst)[2] = (*pU128_src)[2]; >- (*pU128_dst)[3] = (*pU128_src)[3]; >+ if (IENDIANESS == Iend_LE) { >+ unsigned char *srcp, *dstp; >+ srcp = (unsigned char *)pU128_src; >+ dstp = (unsigned char *)pU128_dst; >+ for (k = 15; k >= 0; k--, srcp++) >+ dstp[k] = *srcp; >+ } else { >+ (*pU128_dst)[0] = (*pU128_src)[0]; >+ (*pU128_dst)[1] = (*pU128_src)[1]; >+ (*pU128_dst)[2] = (*pU128_src)[2]; >+ (*pU128_dst)[3] = (*pU128_src)[3]; >+ } > } > > >Index: valgrind-3.9.0-svn20140513r13961/VEX/priv/guest_ppc_toIR.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/VEX/priv/guest_ppc_toIR.c >+++ valgrind-3.9.0-svn20140513r13961/VEX/priv/guest_ppc_toIR.c >@@ -97,7 +97,8 @@ > > 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) > 7C421378 (or 2,2,2) %R3 = guest_NRADDR >- 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 >+ 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian >+ 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian > 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 > 7CA52B78 (or 5,5,5) IR injection > >@@ -107,7 +108,55 @@ > fragments designed for Valgrind to catch. > */ > >- >+/* Little Endian notes */ >+/* >+ * Vector operations in little Endian mode behave in non-obvious ways at times. >+ * Below is an attempt at explaining this. >+ * >+ * LE/BE vector example >+ * With a vector of unsigned ints declared as follows: >+ * vector unsigned int vec_inA = >+ { 0x11111111, 0x22222222, 0x33333333, 0x44444444 }; >+ * The '0x11111111' word is word zero in both LE and BE format. But the >+ * loaded vector register will have word zero on the far left in BE mode and >+ * on the far right in LE mode. The lvx and stvx instructions work naturally >+ * for whatever endianness is in effect. For example, in LE mode, the stvx >+ * stores word zero (far right word) of the vector at the lowest memory >+ * address of the EA; in BE mode, stvx still stores word zero at the lowest >+ * memory address, but with word zero interpreted as the one at the far left >+ * of the register. >+ * >+ * The lxvd2x and stxvd2x instructions are not so well suited for LE mode. >+ * When the compiler generates an lxvd2x instruction to load the >+ * above-declared vector of unsigned integers, it loads the vector as two >+ * double words, but they are in BE word-wise format. To put the vector in >+ * the right order for LE, the compiler also generates an xxswapd after the >+ * load, which puts it in proper LE format. Similarly, the stxvd2x >+ * instruction has a BE bias, storing the vector in BE word-wise format. But >+ * the compiler also generates an xxswapd prior to the store, thus ensuring >+ * the vector is stored in memory in the correct LE order. >+ * >+ * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts >+ * of a double words and words within a vector. Because of the reverse order >+ * of numbering for LE as described above, the high part refers to word 1 in >+ * LE format. When input data is saved to a guest state vector register >+ * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the >+ * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction. >+ * The saving of the data to memory must be done in proper LE order. For the >+ * inverse operation of extracting data from a vector register (e.g., >+ * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting >+ * in stvx), and then integer registers are loaded from the memory location >+ * from where the vector register was saved. Again, this must be done in >+ * proper LE order. So for these various vector Iops, we have LE-specific >+ * code in host_ppc_isel.c >+ * >+ * Another unique behavior of vectors in LE mode is with the vector scalar >+ * (VSX) operations that operate on "double word 0" of the source register, >+ * storing the result in "double word 0" of the output vector register. For >+ * these operations, "double word 0" is interpreted as "high half of the >+ * register" (i.e, the part on the left side). >+ * >+ */ > /* Translates PPC32/64 code to IR. */ > > /* References >@@ -144,6 +193,12 @@ > #include "guest_ppc_defs.h" > > >+#if defined(VGP_ppc64le_linux) >+#define IENDIANESS Iend_LE >+#else >+#define IENDIANESS Iend_BE >+#endif >+ > /*------------------------------------------------------------*/ > /*--- Globals ---*/ > /*------------------------------------------------------------*/ >@@ -503,15 +558,24 @@ static ULong extend_s_32to64 ( UInt x ) > return (ULong)((((Long)x) << 32) >> 32); > } > >-/* Do a big-endian load of a 32-bit word, regardless of the endianness >+/* Do a proper-endian load of a 32-bit word, regardless of the endianness > of the underlying host. */ >-static UInt getUIntBigendianly ( UChar* p ) >+static UInt getUIntPPCendianly ( UChar* p ) > { > UInt w = 0; >+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) > w = (w << 8) | p[0]; > w = (w << 8) | p[1]; > w = (w << 8) | p[2]; > w = (w << 8) | p[3]; >+#elif defined(VGP_ppc64le_linux) >+ w = (w << 8) | p[3]; >+ w = (w << 8) | p[2]; >+ w = (w << 8) | p[1]; >+ w = (w << 8) | p[0]; >+#else >+ vex_printf("ERROR: call to getUIntPPCendianly(); Unknown variant of PowerPC\n"); >+#endif > return w; > } > >@@ -530,7 +594,7 @@ static void storeBE ( IRExpr* addr, IREx > { > IRType tyA = typeOfIRExpr(irsb->tyenv, addr); > vassert(tyA == Ity_I32 || tyA == Ity_I64); >- stmt( IRStmt_Store(Iend_BE, addr, data) ); >+ stmt( IRStmt_Store(IENDIANESS, addr, data) ); > } > > static IRExpr* unop ( IROp op, IRExpr* a ) >@@ -588,7 +652,7 @@ static IRExpr* mkV128 ( UShort i ) > /* This generates a normal (non load-linked) load. */ > static IRExpr* loadBE ( IRType ty, IRExpr* addr ) > { >- return IRExpr_Load(Iend_BE, ty, addr); >+ return IRExpr_Load(IENDIANESS, ty, addr); > } > > static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) >@@ -1039,7 +1103,6 @@ static Int integerGuestRegOffset ( UInt > // jrs: probably not necessary; only matters if we reference sub-parts > // of the ppc registers, but that isn't the case > // later: this might affect Altivec though? >- vassert(host_is_bigendian); > > switch (archreg) { > case 0: return offsetofPPCGuestState(guest_GPR0); >@@ -1101,40 +1164,78 @@ static Int floatGuestRegOffset ( UInt ar > { > vassert(archreg < 32); > >- switch (archreg) { >- case 0: return offsetofPPCGuestState(guest_VSR0); >- case 1: return offsetofPPCGuestState(guest_VSR1); >- case 2: return offsetofPPCGuestState(guest_VSR2); >- case 3: return offsetofPPCGuestState(guest_VSR3); >- case 4: return offsetofPPCGuestState(guest_VSR4); >- case 5: return offsetofPPCGuestState(guest_VSR5); >- case 6: return offsetofPPCGuestState(guest_VSR6); >- case 7: return offsetofPPCGuestState(guest_VSR7); >- case 8: return offsetofPPCGuestState(guest_VSR8); >- case 9: return offsetofPPCGuestState(guest_VSR9); >- case 10: return offsetofPPCGuestState(guest_VSR10); >- case 11: return offsetofPPCGuestState(guest_VSR11); >- case 12: return offsetofPPCGuestState(guest_VSR12); >- case 13: return offsetofPPCGuestState(guest_VSR13); >- case 14: return offsetofPPCGuestState(guest_VSR14); >- case 15: return offsetofPPCGuestState(guest_VSR15); >- case 16: return offsetofPPCGuestState(guest_VSR16); >- case 17: return offsetofPPCGuestState(guest_VSR17); >- case 18: return offsetofPPCGuestState(guest_VSR18); >- case 19: return offsetofPPCGuestState(guest_VSR19); >- case 20: return offsetofPPCGuestState(guest_VSR20); >- case 21: return offsetofPPCGuestState(guest_VSR21); >- case 22: return offsetofPPCGuestState(guest_VSR22); >- case 23: return offsetofPPCGuestState(guest_VSR23); >- case 24: return offsetofPPCGuestState(guest_VSR24); >- case 25: return offsetofPPCGuestState(guest_VSR25); >- case 26: return offsetofPPCGuestState(guest_VSR26); >- case 27: return offsetofPPCGuestState(guest_VSR27); >- case 28: return offsetofPPCGuestState(guest_VSR28); >- case 29: return offsetofPPCGuestState(guest_VSR29); >- case 30: return offsetofPPCGuestState(guest_VSR30); >- case 31: return offsetofPPCGuestState(guest_VSR31); >- default: break; >+ if (IENDIANESS == Iend_LE) { >+ switch (archreg) { >+ case 0: return offsetofPPCGuestState(guest_VSR0 + 8); >+ case 1: return offsetofPPCGuestState(guest_VSR1 + 8); >+ case 2: return offsetofPPCGuestState(guest_VSR2 + 8); >+ case 3: return offsetofPPCGuestState(guest_VSR3 + 8); >+ case 4: return offsetofPPCGuestState(guest_VSR4 + 8); >+ case 5: return offsetofPPCGuestState(guest_VSR5 + 8); >+ case 6: return offsetofPPCGuestState(guest_VSR6 + 8); >+ case 7: return offsetofPPCGuestState(guest_VSR7 + 8); >+ case 8: return offsetofPPCGuestState(guest_VSR8 + 8); >+ case 9: return offsetofPPCGuestState(guest_VSR9 + 8); >+ case 10: return offsetofPPCGuestState(guest_VSR10 + 8); >+ case 11: return offsetofPPCGuestState(guest_VSR11 + 8); >+ case 12: return offsetofPPCGuestState(guest_VSR12 + 8); >+ case 13: return offsetofPPCGuestState(guest_VSR13 + 8); >+ case 14: return offsetofPPCGuestState(guest_VSR14 + 8); >+ case 15: return offsetofPPCGuestState(guest_VSR15 + 8); >+ case 16: return offsetofPPCGuestState(guest_VSR16 + 8); >+ case 17: return offsetofPPCGuestState(guest_VSR17 + 8); >+ case 18: return offsetofPPCGuestState(guest_VSR18 + 8); >+ case 19: return offsetofPPCGuestState(guest_VSR19 + 8); >+ case 20: return offsetofPPCGuestState(guest_VSR20 + 8); >+ case 21: return offsetofPPCGuestState(guest_VSR21 + 8); >+ case 22: return offsetofPPCGuestState(guest_VSR22 + 8); >+ case 23: return offsetofPPCGuestState(guest_VSR23 + 8); >+ case 24: return offsetofPPCGuestState(guest_VSR24 + 8); >+ case 25: return offsetofPPCGuestState(guest_VSR25 + 8); >+ case 26: return offsetofPPCGuestState(guest_VSR26 + 8); >+ case 27: return offsetofPPCGuestState(guest_VSR27 + 8); >+ case 28: return offsetofPPCGuestState(guest_VSR28 + 8); >+ case 29: return offsetofPPCGuestState(guest_VSR29 + 8); >+ case 30: return offsetofPPCGuestState(guest_VSR30 + 8); >+ case 31: return offsetofPPCGuestState(guest_VSR31 + 8); >+ default: break; >+ } >+ } else { >+ switch (archreg) { >+ case 0: return offsetofPPCGuestState(guest_VSR0); >+ case 1: return offsetofPPCGuestState(guest_VSR1); >+ case 2: return offsetofPPCGuestState(guest_VSR2); >+ case 3: return offsetofPPCGuestState(guest_VSR3); >+ case 4: return offsetofPPCGuestState(guest_VSR4); >+ case 5: return offsetofPPCGuestState(guest_VSR5); >+ case 6: return offsetofPPCGuestState(guest_VSR6); >+ case 7: return offsetofPPCGuestState(guest_VSR7); >+ case 8: return offsetofPPCGuestState(guest_VSR8); >+ case 9: return offsetofPPCGuestState(guest_VSR9); >+ case 10: return offsetofPPCGuestState(guest_VSR10); >+ case 11: return offsetofPPCGuestState(guest_VSR11); >+ case 12: return offsetofPPCGuestState(guest_VSR12); >+ case 13: return offsetofPPCGuestState(guest_VSR13); >+ case 14: return offsetofPPCGuestState(guest_VSR14); >+ case 15: return offsetofPPCGuestState(guest_VSR15); >+ case 16: return offsetofPPCGuestState(guest_VSR16); >+ case 17: return offsetofPPCGuestState(guest_VSR17); >+ case 18: return offsetofPPCGuestState(guest_VSR18); >+ case 19: return offsetofPPCGuestState(guest_VSR19); >+ case 20: return offsetofPPCGuestState(guest_VSR20); >+ case 21: return offsetofPPCGuestState(guest_VSR21); >+ case 22: return offsetofPPCGuestState(guest_VSR22); >+ case 23: return offsetofPPCGuestState(guest_VSR23); >+ case 24: return offsetofPPCGuestState(guest_VSR24); >+ case 25: return offsetofPPCGuestState(guest_VSR25); >+ case 26: return offsetofPPCGuestState(guest_VSR26); >+ case 27: return offsetofPPCGuestState(guest_VSR27); >+ case 28: return offsetofPPCGuestState(guest_VSR28); >+ case 29: return offsetofPPCGuestState(guest_VSR29); >+ case 30: return offsetofPPCGuestState(guest_VSR30); >+ case 31: return offsetofPPCGuestState(guest_VSR31); >+ default: break; >+ } > } > vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ > } >@@ -6145,7 +6246,7 @@ static Bool dis_memsync ( UInt theInstr > > // and actually do the load > res = newTemp(Ity_I32); >- stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); >+ stmt( IRStmt_LLSC(IENDIANESS, res, mkexpr(EA), NULL/*this is a load*/) ); > > putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); > break; >@@ -6171,7 +6272,7 @@ static Bool dis_memsync ( UInt theInstr > > // Do the store, and get success/failure bit into resSC > resSC = newTemp(Ity_I1); >- stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); >+ stmt( IRStmt_LLSC(IENDIANESS, resSC, mkexpr(EA), mkexpr(rS)) ); > > // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure > // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success >@@ -6238,7 +6339,7 @@ static Bool dis_memsync ( UInt theInstr > > // and actually do the load > res = newTemp(Ity_I64); >- stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); >+ stmt( IRStmt_LLSC(IENDIANESS, res, mkexpr(EA), NULL/*this is a load*/) ); > > putIReg( rD_addr, mkexpr(res) ); > break; >@@ -6264,7 +6365,7 @@ static Bool dis_memsync ( UInt theInstr > > // Do the store, and get success/failure bit into resSC > resSC = newTemp(Ity_I1); >- stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); >+ stmt( IRStmt_LLSC(IENDIANESS, resSC, mkexpr(EA), mkexpr(rS)) ); > > // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure > // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success >@@ -6294,16 +6395,16 @@ static Bool dis_memsync ( UInt theInstr > > // and actually do the load > if (mode64) { >- stmt( IRStmt_LLSC( Iend_BE, res_hi, >+ stmt( IRStmt_LLSC( IENDIANESS, res_hi, > mkexpr(EA), NULL/*this is a load*/) ); >- stmt( IRStmt_LLSC( Iend_BE, res_lo, >+ stmt( IRStmt_LLSC( IENDIANESS, res_lo, > binop(Iop_Add64, mkexpr(EA), mkU64(8) ), > NULL/*this is a load*/) ); > } else { >- stmt( IRStmt_LLSC( Iend_BE, res_hi, >+ stmt( IRStmt_LLSC( IENDIANESS, res_hi, > binop( Iop_Add32, mkexpr(EA), mkU32(4) ), > NULL/*this is a load*/) ); >- stmt( IRStmt_LLSC( Iend_BE, res_lo, >+ stmt( IRStmt_LLSC( IENDIANESS, res_lo, > binop( Iop_Add32, mkexpr(EA), mkU32(12) ), > NULL/*this is a load*/) ); > } >@@ -6334,10 +6435,10 @@ static Bool dis_memsync ( UInt theInstr > resSC = newTemp(Ity_I1); > > if (mode64) { >- stmt( IRStmt_LLSC( Iend_BE, resSC, mkexpr(EA), mkexpr(rS_hi) ) ); >+ stmt( IRStmt_LLSC( IENDIANESS, resSC, mkexpr(EA), mkexpr(rS_hi) ) ); > storeBE(binop( Iop_Add64, mkexpr(EA), mkU64(8) ), mkexpr(rS_lo) ); > } else { >- stmt( IRStmt_LLSC( Iend_BE, resSC, binop( Iop_Add32, >+ stmt( IRStmt_LLSC( IENDIANESS, resSC, binop( Iop_Add32, > mkexpr(EA), > mkU32(4) ), > mkexpr(rS_hi) ) ); >@@ -6690,7 +6791,10 @@ static Bool dis_int_ldst_rev ( UInt theI > ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); > assign( w3, loadBE( Ity_I32, nextAddr ) ); > assign( w4, gen_byterev32( w3 ) ); >- putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); >+ if (IENDIANESS == Iend_LE) >+ putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) ); >+ else >+ putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); > break; > } > >@@ -14769,6 +14873,7 @@ dis_vvec_cmp( UInt theInstr, UInt opc2 ) > static Bool > dis_vxs_misc( UInt theInstr, UInt opc2 ) > { >+#define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL > /* XX3-Form and XX2-Form */ > UChar opc1 = ifieldOPC( theInstr ); > UChar XT = ifieldRegXT ( theInstr ); >@@ -14795,7 +14900,20 @@ dis_vxs_misc( UInt theInstr, UInt opc2 ) > { > /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ > IRTemp absVal = newTemp(Ity_V128); >- assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1))); >+ if (IENDIANESS == Iend_LE) { >+ IRTemp hi64 = newTemp(Ity_I64); >+ IRTemp lo64 = newTemp(Ity_I64); >+ assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) ); >+ assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) ); >+ assign( absVal, binop( Iop_64HLtoV128, >+ binop( Iop_And64, mkexpr(hi64), >+ mkU64(VG_PPC_SIGN_MASK) ), >+ mkexpr(lo64) ) ); >+ } else { >+ assign(absVal, binop(Iop_ShrV128, >+ binop(Iop_ShlV128, mkexpr(vB), >+ mkU8(1)), mkU8(1))); >+ } > DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); > putVSReg(XT, mkexpr(absVal)); > break; >@@ -14803,51 +14921,73 @@ dis_vxs_misc( UInt theInstr, UInt opc2 ) > case 0x2C0: // xscpsgndp > { > /* Scalar copy sign double-precision */ >- IRTemp vecA_signbit = newTemp(Ity_V128); >- IRTemp vecB_no_signbit = newTemp(Ity_V128); >+ IRTemp vecA_signed = newTemp(Ity_I64); >+ IRTemp vecB_unsigned = newTemp(Ity_I64); > IRTemp vec_result = newTemp(Ity_V128); > DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); >- assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, >- mkexpr( vB ), >- mkU8( 1 ) ), >- mkU8( 1 ) ) ); >- assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128, >- mkexpr( vA ), >- mkU8( 127 ) ), >- mkU8( 127 ) ) ); >- assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) ); >+ assign( vecA_signed, binop( Iop_And64, >+ unop( Iop_V128HIto64, >+ mkexpr(vA)), >+ mkU64(~VG_PPC_SIGN_MASK) ) ); >+ assign( vecB_unsigned, binop( Iop_And64, >+ unop( Iop_V128HIto64, >+ mkexpr(vB) ), >+ mkU64(VG_PPC_SIGN_MASK) ) ); >+ assign( vec_result, binop( Iop_64HLtoV128, >+ binop( Iop_Or64, >+ mkexpr(vecA_signed), >+ mkexpr(vecB_unsigned) ), >+ mkU64(0x0ULL))); > putVSReg(XT, mkexpr(vec_result)); > break; > } > case 0x2D2: // xsnabsdp > { > /* Scalar negative absolute value double-precision */ >- IRTemp vec_neg_signbit = newTemp(Ity_V128); >+ IRTemp BHi_signed = newTemp(Ity_I64); > DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); >- assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128, >- mkV128( 0xffff ), >- mkU8( 1 ) ) ) ); >- putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB))); >+ assign( BHi_signed, binop( Iop_Or64, >+ unop( Iop_V128HIto64, >+ mkexpr(vB) ), >+ mkU64(~VG_PPC_SIGN_MASK) ) ); >+ putVSReg(XT, binop( Iop_64HLtoV128, >+ mkexpr(BHi_signed), mkU64(0x0ULL) ) ); > break; > } > case 0x2F2: // xsnegdp > { > /* Scalar negate double-precision */ >- IRTemp vecB_no_signbit = newTemp(Ity_V128); >- IRTemp vecB_signbit_comp = newTemp(Ity_V128); >+ IRTemp BHi_signed = newTemp(Ity_I64); >+ IRTemp BHi_unsigned = newTemp(Ity_I64); >+ IRTemp BHi_negated = newTemp(Ity_I64); >+ IRTemp BHi_negated_signbit = newTemp(Ity_I1); >+ IRTemp vec_result = newTemp(Ity_V128); > DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); >- assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, >- mkexpr( vB ), >- mkU8( 1 ) ), >- mkU8( 1 ) ) ); >- assign( vecB_signbit_comp, binop( Iop_ShlV128, >- unop( Iop_NotV128, >- binop( Iop_ShrV128, >- mkexpr( vB ), >- mkU8( 127 ) ) ), >- mkU8( 127 ) ) ); >- putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ), >- mkexpr( vecB_signbit_comp ) ) ); >+ assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) ); >+ assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed), >+ mkU64(VG_PPC_SIGN_MASK) ) ); >+ assign( BHi_negated_signbit, >+ unop( Iop_Not1, >+ unop( Iop_32to1, >+ binop( Iop_Shr32, >+ unop( Iop_64HIto32, >+ binop( Iop_And64, >+ mkexpr(BHi_signed), >+ mkU64(~VG_PPC_SIGN_MASK) ) >+ ), >+ mkU8(31) ) ) ) ); >+ assign( BHi_negated, >+ binop( Iop_Or64, >+ binop( Iop_32HLto64, >+ binop( Iop_Shl32, >+ unop( Iop_1Uto32, >+ mkexpr(BHi_negated_signbit) ), >+ mkU8(31) ), >+ mkU32(0) ), >+ mkexpr(BHi_unsigned) ) ); >+ assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated), >+ mkU64(0x0ULL))); >+ putVSReg( XT, mkexpr(vec_result)); > break; > } > case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) >@@ -15070,21 +15210,19 @@ dis_vx_load ( UInt theInstr ) > switch (opc2) { > case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed) > { >- IRExpr * exp; > DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); >- exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) ); > putVSReg( XT, binop( Iop_64HLtoV128, >- unop( Iop_32Uto64, exp), >+ unop( Iop_32Uto64, >+ loadBE( Ity_I32, mkexpr( EA ) ) ), > mkU64(0) ) ); > break; > } > case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed) > { >- IRExpr * exp; > DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); >- exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) ); > putVSReg( XT, binop( Iop_64HLtoV128, >- unop( Iop_32Sto64, exp), >+ unop( Iop_32Sto64, >+ loadBE( Ity_I32, mkexpr( EA ) )), > mkU64(0) ) ); > break; > } >@@ -15099,8 +15237,7 @@ dis_vx_load ( UInt theInstr ) > exp = unop( Iop_ReinterpF64asI64, > unop( Iop_F32toF64, > unop( Iop_ReinterpI32asF32, >- unop( Iop_64HIto32, >- loadBE( Ity_I64, mkexpr( EA ) ) ) ) ) ); >+ loadBE( Ity_I32, mkexpr( EA ) ) ) ) ); > > putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) ); > break; >@@ -15237,7 +15374,7 @@ dis_vx_store ( UInt theInstr ) > low64 = unop( Iop_V128to64, mkexpr( vS ) ); > storeBE( mkexpr( EA ), high64 ); > storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 ) >- : mkU32( 8 ) ), low64 ); >+ : mkU32( 8 ) ), low64 ); > break; > } > case 0x38C: >@@ -15253,7 +15390,6 @@ dis_vx_store ( UInt theInstr ) > // quad-word aligned. Therefore, do 4 individual word-size stores. > assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); > assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); >- > storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); > ea_off += 4; > irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), >@@ -15564,9 +15700,13 @@ static Bool dis_av_store ( UInt theInstr > assign( eb, binop(Iop_And8, mkU8(0xF), > unop(Iop_32to8, > mkNarrowTo32(ty, mkexpr(EA)) )) ); >- assign( idx, binop(Iop_Shl8, >- binop(Iop_Sub8, mkU8(15), mkexpr(eb)), >- mkU8(3)) ); >+ if (IENDIANESS == Iend_LE) { >+ assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); >+ } else { >+ assign( idx, binop(Iop_Shl8, >+ binop(Iop_Sub8, mkU8(15), mkexpr(eb)), >+ mkU8(3)) ); >+ } > storeBE( mkexpr(EA), > unop(Iop_32to8, unop(Iop_V128to32, > binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); >@@ -15577,9 +15717,13 @@ static Bool dis_av_store ( UInt theInstr > assign( addr_aligned, addr_align(mkexpr(EA), 2) ); > assign( eb, binop(Iop_And8, mkU8(0xF), > mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); >- assign( idx, binop(Iop_Shl8, >- binop(Iop_Sub8, mkU8(14), mkexpr(eb)), >- mkU8(3)) ); >+ if (IENDIANESS == Iend_LE) { >+ assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); >+ } else { >+ assign( idx, binop(Iop_Shl8, >+ binop(Iop_Sub8, mkU8(14), mkexpr(eb)), >+ mkU8(3)) ); >+ } > storeBE( mkexpr(addr_aligned), > unop(Iop_32to16, unop(Iop_V128to32, > binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); >@@ -15590,9 +15734,13 @@ static Bool dis_av_store ( UInt theInstr > assign( addr_aligned, addr_align(mkexpr(EA), 4) ); > assign( eb, binop(Iop_And8, mkU8(0xF), > mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); >- assign( idx, binop(Iop_Shl8, >- binop(Iop_Sub8, mkU8(12), mkexpr(eb)), >- mkU8(3)) ); >+ if (IENDIANESS == Iend_LE) { >+ assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); >+ } else { >+ assign( idx, binop(Iop_Shl8, >+ binop(Iop_Sub8, mkU8(12), mkexpr(eb)), >+ mkU8(3)) ); >+ } > storeBE( mkexpr(addr_aligned), > unop(Iop_V128to32, > binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); >@@ -17628,7 +17776,7 @@ static Bool dis_av_quad ( UInt theInstr > res, > binop( Iop_ShlV128, > mkexpr( perm_bit ), >- mkU8( i ) ) ); >+ mkU8( i + 64) ) ); > vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) ); > } > putVReg( vRT_addr, res); >@@ -17774,6 +17922,7 @@ static Bool dis_av_fp_arith ( UInt theIn > UChar vB_addr = ifieldRegB(theInstr); > UChar vC_addr = ifieldRegC(theInstr); > UInt opc2=0; >+ IRExpr* rm = get_IR_roundingmode(); > > IRTemp vA = newTemp(Ity_V128); > IRTemp vB = newTemp(Ity_V128); >@@ -17787,9 +17936,6 @@ static Bool dis_av_fp_arith ( UInt theIn > return False; > } > >- IRTemp rm = newTemp(Ity_I32); >- assign(rm, get_IR_roundingmode()); >- > opc2 = IFIELD( theInstr, 0, 6 ); > switch (opc2) { > case 0x2E: // vmaddfp (Multiply Add FP, AV p177) >@@ -17806,10 +17952,9 @@ static Bool dis_av_fp_arith ( UInt theIn > DIP("vnmsubfp v%d,v%d,v%d,v%d\n", > vD_addr, vA_addr, vC_addr, vB_addr); > putVReg( vD_addr, >- triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), >+ triop(Iop_Sub32Fx4, rm, > mkexpr(vB), >- triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), >- mkexpr(vA), mkexpr(vC))) ); >+ triop(Iop_Mul32Fx4, rm, mkexpr(vA), mkexpr(vC))) ); > return True; > } > >@@ -17821,14 +17966,12 @@ static Bool dis_av_fp_arith ( UInt theIn > switch (opc2) { > case 0x00A: // vaddfp (Add FP, AV p137) > DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); >- putVReg( vD_addr, triop(Iop_Add32Fx4, >- mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); >+ putVReg( vD_addr, triop(Iop_Add32Fx4, rm, mkexpr(vA), mkexpr(vB)) ); > return True; > > case 0x04A: // vsubfp (Subtract FP, AV p261) > DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); >- putVReg( vD_addr, triop(Iop_Sub32Fx4, >- mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); >+ putVReg( vD_addr, triop(Iop_Sub32Fx4, rm, mkexpr(vA), mkexpr(vB)) ); > return True; > > case 0x40A: // vmaxfp (Maximum FP, AV p178) >@@ -17891,6 +18034,7 @@ static Bool dis_av_fp_cmp ( UInt theInst > UChar vB_addr = ifieldRegB(theInstr); > UChar flag_rC = ifieldBIT10(theInstr); > UInt opc2 = IFIELD( theInstr, 0, 10 ); >+ IRExpr* rm = get_IR_roundingmode(); > > Bool cmp_bounds = False; > >@@ -17945,9 +18089,8 @@ static Bool dis_av_fp_cmp ( UInt theInst > binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); > assign( lt, unop(Iop_NotV128, > binop(Iop_CmpGE32Fx4, mkexpr(vA), >- triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), >- mkexpr(zeros), >- mkexpr(vB)))) ); >+ triop(Iop_Sub32Fx4, rm, mkexpr(zeros), >+ mkexpr(vB)))) ); > > // finally, just shift gt,lt to correct position > assign( vD, binop(Iop_ShlN32x4, >@@ -17984,6 +18127,7 @@ static Bool dis_av_fp_convert ( UInt the > UChar UIMM_5 = ifieldRegA(theInstr); > UChar vB_addr = ifieldRegB(theInstr); > UInt opc2 = IFIELD( theInstr, 0, 11 ); >+ IRExpr* rm = get_IR_roundingmode(); > > IRTemp vB = newTemp(Ity_V128); > IRTemp vScale = newTemp(Ity_V128); >@@ -18016,7 +18160,7 @@ static Bool dis_av_fp_convert ( UInt the > case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) > DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); > >- putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), >+ putVReg( vD_addr, triop(Iop_Mul32Fx4, rm, > unop(Iop_I32StoFx4, mkexpr(vB)), > mkexpr(vInvScale)) ); > return True; >@@ -18025,16 +18169,14 @@ static Bool dis_av_fp_convert ( UInt the > DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); > putVReg( vD_addr, > unop(Iop_QFtoI32Ux4_RZ, >- triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), >- mkexpr(vB), mkexpr(vScale))) ); >+ triop(Iop_Mul32Fx4, rm, mkexpr(vB), mkexpr(vScale))) ); > return True; > > case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) > DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); > putVReg( vD_addr, >- unop(Iop_QFtoI32Sx4_RZ, >- triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), >- mkexpr(vB), mkexpr(vScale))) ); >+ unop( Iop_QFtoI32Sx4_RZ, >+ triop(Iop_Mul32Fx4, rm, mkexpr(vB), mkexpr(vScale))) ); > return True; > > default: >@@ -18535,7 +18677,7 @@ DisResult disInstr_PPC_WRK ( > /* At least this is simple on PPC32: insns are all 4 bytes long, and > 4-aligned. So just fish the whole thing out of memory right now > and have done. */ >- theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) ); >+ theInstr = getUIntPPCendianly( (UChar*)(&guest_code[delta]) ); > > if (0) vex_printf("insn: 0x%x\n", theInstr); > >@@ -18560,12 +18702,12 @@ DisResult disInstr_PPC_WRK ( > UInt word2 = mode64 ? 0x78006800 : 0x5400683E; > UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E; > UInt word4 = mode64 ? 0x78009802 : 0x5400983E; >- if (getUIntBigendianly(code+ 0) == word1 && >- getUIntBigendianly(code+ 4) == word2 && >- getUIntBigendianly(code+ 8) == word3 && >- getUIntBigendianly(code+12) == word4) { >+ if (getUIntPPCendianly(code+ 0) == word1 && >+ getUIntPPCendianly(code+ 4) == word2 && >+ getUIntPPCendianly(code+ 8) == word3 && >+ getUIntPPCendianly(code+12) == word4) { > /* Got a "Special" instruction preamble. Which one is it? */ >- if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { >+ if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { > /* %R3 = client_request ( %R4 ) */ > DIP("r3 = client_request ( %%r4 )\n"); > delta += 20; >@@ -18575,7 +18717,7 @@ DisResult disInstr_PPC_WRK ( > goto decode_success; > } > else >- if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { >+ if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { > /* %R3 = guest_NRADDR */ > DIP("r3 = guest_NRADDR\n"); > delta += 20; >@@ -18584,7 +18726,19 @@ DisResult disInstr_PPC_WRK ( > goto decode_success; > } > else >- if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { >+#if defined(VGP_ppc64le_linux) >+ if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { >+ /* branch-and-link-to-noredir %R12 */ >+ DIP("branch-and-link-to-noredir r12\n"); >+ delta += 20; >+ putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); >+ putGST( PPC_GST_CIA, getIReg(12)); >+ dres.jk_StopHere = Ijk_NoRedir; >+ dres.whatNext = Dis_StopHere; >+ goto decode_success; >+ } >+#else >+ if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { > /* branch-and-link-to-noredir %R11 */ > DIP("branch-and-link-to-noredir r11\n"); > delta += 20; >@@ -18594,8 +18748,9 @@ DisResult disInstr_PPC_WRK ( > dres.whatNext = Dis_StopHere; > goto decode_success; > } >+#endif > else >- if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { >+ if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { > /* %R3 = guest_NRADDR_GPR2 */ > DIP("r3 = guest_NRADDR_GPR2\n"); > delta += 20; >@@ -18604,10 +18759,10 @@ DisResult disInstr_PPC_WRK ( > goto decode_success; > } > else >- if (getUIntBigendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) { >+ if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) { > DIP("IR injection\n"); > >- vex_inject_ir(irsb, Iend_BE); >+ vex_inject_ir(irsb, IENDIANESS); > > delta += 20; > dres.len = 20; >@@ -18627,7 +18782,7 @@ DisResult disInstr_PPC_WRK ( > } > /* We don't know what it is. Set opc1/opc2 so decode_failure > can print the insn following the Special-insn preamble. */ >- theInstr = getUIntBigendianly(code+16); >+ theInstr = getUIntPPCendianly(code+16); > opc1 = ifieldOPC(theInstr); > opc2 = ifieldOPClo10(theInstr); > goto decode_failure; >@@ -19323,7 +19478,7 @@ DisResult disInstr_PPC_WRK ( > case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci. > case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt. > if (dis_transactional_memory( theInstr, >- getUIntBigendianly( (UChar*)(&guest_code[delta + 4])), >+ getUIntPPCendianly( (UChar*)(&guest_code[delta + 4])), > abiinfo, &dres, > resteerOkFn, callback_opaque)) > goto decode_success; >@@ -19956,6 +20111,13 @@ DisResult disInstr_PPC ( IRSB* ir > /* global -- ick */ > mode64 = guest_arch == VexArchPPC64; > ty = mode64 ? Ity_I64 : Ity_I32; >+ if (!mode64 && IENDIANESS == Iend_LE) { >+ vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n"); >+ dres.whatNext = Dis_StopHere; >+ dres.jk_StopHere = Ijk_NoDecode; >+ dres.len = 0; >+ return dres; >+ } > > /* do some sanity checks */ > mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V >Index: valgrind-3.9.0-svn20140513r13961/VEX/priv/host_ppc_defs.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/VEX/priv/host_ppc_defs.c >+++ valgrind-3.9.0-svn20140513r13961/VEX/priv/host_ppc_defs.c >@@ -3115,24 +3115,42 @@ static UInt vregNo ( HReg v ) > return n; > } > >-/* Emit an instruction big-endianly */ >+/* Emit an instruction ppc-endianly */ > static UChar* emit32 ( UChar* p, UInt w32 ) > { >+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) > *p++ = toUChar((w32 >> 24) & 0x000000FF); > *p++ = toUChar((w32 >> 16) & 0x000000FF); > *p++ = toUChar((w32 >> 8) & 0x000000FF); > *p++ = toUChar((w32) & 0x000000FF); >+#elif defined(VGP_ppc64le_linux) >+ *p++ = toUChar((w32) & 0x000000FF); >+ *p++ = toUChar((w32 >> 8) & 0x000000FF); >+ *p++ = toUChar((w32 >> 16) & 0x000000FF); >+ *p++ = toUChar((w32 >> 24) & 0x000000FF); >+#else >+ //error Unknown variant of PowerPC >+#endif > return p; > } > >-/* Fetch an instruction big-endianly */ >+/* Fetch an instruction ppc-endianly */ > static UInt fetch32 ( UChar* p ) > { > UInt w32 = 0; >+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) > w32 |= ((0xFF & (UInt)p[0]) << 24); > w32 |= ((0xFF & (UInt)p[1]) << 16); > w32 |= ((0xFF & (UInt)p[2]) << 8); > w32 |= ((0xFF & (UInt)p[3]) << 0); >+#elif defined(VGP_ppc64le_linux) >+ w32 |= ((0xFF & (UInt)p[3]) << 24); >+ w32 |= ((0xFF & (UInt)p[2]) << 16); >+ w32 |= ((0xFF & (UInt)p[1]) << 8); >+ w32 |= ((0xFF & (UInt)p[0]) << 0); >+#else >+ //error Unknown variant of PowerPC >+#endif > return w32; > } > >Index: valgrind-3.9.0-svn20140513r13961/VEX/priv/host_ppc_isel.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/VEX/priv/host_ppc_isel.c >+++ valgrind-3.9.0-svn20140513r13961/VEX/priv/host_ppc_isel.c >@@ -47,6 +47,11 @@ > /* GPR register class for ppc32/64 */ > #define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32) > >+#if defined(VGP_ppc64le_linux) >+#define IENDIANESS Iend_LE >+#else >+#define IENDIANESS Iend_BE >+#endif > > /*---------------------------------------------------------*/ > /*--- Register Usage Conventions ---*/ >@@ -1275,29 +1280,28 @@ static HReg mk_AvDuplicateRI( ISelEnv* e > r_src = ri->Pri.Reg; > } > >- /* default case: store r_src in lowest lane of 16-aligned mem, >- load vector, splat lowest lane to dst */ > { >- /* CAB: Maybe faster to store r_src multiple times (sz dependent), >- and simply load the vector? */ >+ /* Store r_src multiple times (sz dependent); then load the dest vector. */ > HReg r_aligned16; >- HReg v_src = newVRegV(env); >- PPCAMode *am_off12; >+ PPCAMode *am_offset, *am_offset_zero; > > sub_from_sp( env, 32 ); // Move SP down > /* Get a 16-aligned address within our stack space */ > r_aligned16 = get_sp_aligned16( env ); >- am_off12 = PPCAMode_IR( 12, r_aligned16 ); > >- /* Store r_src in low word of 16-aligned mem */ >- addInstr(env, PPCInstr_Store( 4, am_off12, r_src, env->mode64 )); >+ Int i; >+ Int stride = (sz == 8) ? 1 : (sz == 16) ? 2 : 4; >+ UChar num_bytes_to_store = stride; >+ am_offset_zero = PPCAMode_IR( 0, r_aligned16 ); >+ am_offset = am_offset_zero; >+ for (i = 0; i < 16; i+=stride, am_offset = PPCAMode_IR( i, r_aligned16)) { >+ addInstr(env, PPCInstr_Store( num_bytes_to_store, am_offset, r_src, env->mode64 )); >+ } > >- /* Load src to vector[low lane] */ >- addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, v_src, am_off12 ) ); >+ /* Effectively splat the r_src value to dst */ >+ addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_offset_zero ) ); > add_to_sp( env, 32 ); // Reset SP > >- /* Finally, splat v_src[low_lane] to dst */ >- addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Reg(v_src))); > return dst; > } > } >@@ -1382,7 +1386,7 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > case Iex_Load: { > HReg r_dst; > PPCAMode* am_addr; >- if (e->Iex.Load.end != Iend_BE) >+ if (e->Iex.Load.end != IENDIANESS) > goto irreducible; > r_dst = newVRegI(env); > am_addr = iselWordExpr_AMode( env, e->Iex.Load.addr, ty/*of xfer*/ ); >@@ -1828,7 +1832,7 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > DECLARE_PATTERN(p_LDbe16_then_16Uto32); > DEFINE_PATTERN(p_LDbe16_then_16Uto32, > unop(Iop_16Uto32, >- IRExpr_Load(Iend_BE,Ity_I16,bind(0))) ); >+ IRExpr_Load(IENDIANESS,Ity_I16,bind(0))) ); > if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) { > HReg r_dst = newVRegI(env); > PPCAMode* amode >@@ -2058,19 +2062,30 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > HReg r_aligned16; > HReg dst = newVRegI(env); > HReg vec = iselVecExpr(env, e->Iex.Unop.arg); >- PPCAMode *am_off0, *am_off12; >+ PPCAMode *am_off0, *am_off_word0; > sub_from_sp( env, 32 ); // Move SP down 32 bytes > > // get a quadword aligned address within our stack space > r_aligned16 = get_sp_aligned16( env ); > am_off0 = PPCAMode_IR( 0, r_aligned16 ); >- am_off12 = PPCAMode_IR( 12,r_aligned16 ); >+ >+ /* Note that the store below (done via PPCInstr_AvLdSt) uses >+ * stvx, which stores the vector in proper LE format, >+ * with byte zero (far right byte of the register in LE format) >+ * stored at the lowest memory address. Therefore, to obtain >+ * integer word zero, we need to use that lowest memory address >+ * as the base for the load. >+ */ >+ if (IENDIANESS == Iend_LE) >+ am_off_word0 = am_off0; >+ else >+ am_off_word0 = PPCAMode_IR( 12,r_aligned16 ); > > // store vec, load low word to dst > addInstr(env, > PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 )); > addInstr(env, >- PPCInstr_Load( 4, dst, am_off12, mode64 )); >+ PPCInstr_Load( 4, dst, am_off_word0, mode64 )); > > add_to_sp( env, 32 ); // Reset SP > return dst; >@@ -2082,7 +2097,7 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > HReg r_aligned16; > HReg dst = newVRegI(env); > HReg vec = iselVecExpr(env, e->Iex.Unop.arg); >- PPCAMode *am_off0, *am_off8; >+ PPCAMode *am_off0, *am_off8, *am_off_arg; > sub_from_sp( env, 32 ); // Move SP down 32 bytes > > // get a quadword aligned address within our stack space >@@ -2090,13 +2105,24 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > am_off0 = PPCAMode_IR( 0, r_aligned16 ); > am_off8 = PPCAMode_IR( 8 ,r_aligned16 ); > >- // store vec, load low word (+8) or high (+0) to dst >+ // store vec, load low word or high to dst > addInstr(env, > PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 )); >+ if (IENDIANESS == Iend_LE) { >+ if (op_unop == Iop_V128HIto64) >+ am_off_arg = am_off8; >+ else >+ am_off_arg = am_off0; >+ } else { >+ if (op_unop == Iop_V128HIto64) >+ am_off_arg = am_off0; >+ else >+ am_off_arg = am_off8; >+ } > addInstr(env, > PPCInstr_Load( > 8, dst, >- op_unop == Iop_V128HIto64 ? am_off0 : am_off8, >+ am_off_arg, > mode64 )); > > add_to_sp( env, 32 ); // Reset SP >@@ -2185,7 +2211,6 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > HReg argregs[1]; > HReg r_dst = newVRegI(env); > Int argreg; >- HWord* fdescr; > > argiregs = 0; > argreg = 0; >@@ -2196,11 +2221,18 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > iselWordExpr_R(env, e->Iex.Unop.arg) ) ); > > cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE ); >- >- fdescr = (HWord*)h_calc_BCDtoDPB; >- addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), >+#if defined(VGP_ppc64le_linux) >+ addInstr(env, PPCInstr_Call( cc, (Addr64) h_calc_BCDtoDPB, > argiregs, mk_RetLoc_simple(RLPri_Int)) ); >- >+#else >+ { >+ HWord* fdescr; >+ fdescr = (HWord*)h_calc_BCDtoDPB; >+ addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), >+ argiregs, >+ mk_RetLoc_simple(RLPri_Int)) ); >+ } >+#endif > addInstr(env, mk_iMOVds_RR(r_dst, argregs[0])); > return r_dst; > } >@@ -2214,7 +2246,6 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > HReg argregs[1]; > HReg r_dst = newVRegI(env); > Int argreg; >- HWord* fdescr; > > argiregs = 0; > argreg = 0; >@@ -2225,11 +2256,18 @@ static HReg iselWordExpr_R_wrk ( ISelEnv > iselWordExpr_R(env, e->Iex.Unop.arg) ) ); > > cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE ); >- >- fdescr = (HWord*)h_calc_DPBtoBCD; >- addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), >+#if defined(VGP_ppc64le_linux) >+ addInstr(env, PPCInstr_Call( cc, (Addr64)(h_calc_DPBtoBCD), > argiregs, mk_RetLoc_simple(RLPri_Int) ) ); >- >+#else >+ { >+ HWord* fdescr; >+ fdescr = (HWord*)h_calc_DPBtoBCD; >+ addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), >+ argiregs, >+ mk_RetLoc_simple(RLPri_Int) ) ); >+ } >+#endif > addInstr(env, mk_iMOVds_RR(r_dst, argregs[0])); > return r_dst; > } >@@ -3075,7 +3113,7 @@ static void iselInt64Expr_wrk ( HReg* rH > vassert(typeOfIRExpr(env->type_env,e) == Ity_I64); > > /* 64-bit load */ >- if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) { >+ if (e->tag == Iex_Load && e->Iex.Load.end == IENDIANESS) { > HReg tLo = newVRegI(env); > HReg tHi = newVRegI(env); > HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr); >@@ -3552,7 +3590,6 @@ static void iselInt64Expr_wrk ( HReg* rH > HReg tHi = newVRegI(env); > HReg tmpHi; > HReg tmpLo; >- ULong target; > Bool mode64 = env->mode64; > > argregs[0] = hregPPC_GPR3(mode64); >@@ -3570,11 +3607,19 @@ static void iselInt64Expr_wrk ( HReg* rH > addInstr( env, mk_iMOVds_RR( argregs[argreg], tmpLo ) ); > > cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE ); >- target = toUInt( Ptr_to_ULong(h_calc_BCDtoDPB ) ); >- >- addInstr( env, PPCInstr_Call( cc, (Addr64)target, >+#if defined(VGP_ppc64le_linux) >+ addInstr( env, PPCInstr_Call( cc, (Addr64)h_calc_BCDtoDPB, > argiregs, > mk_RetLoc_simple(RLPri_2Int) ) ); >+#else >+ { >+ ULong target; >+ target = toUInt( Ptr_to_ULong(h_calc_BCDtoDPB ) ); >+ addInstr( env, PPCInstr_Call( cc, (Addr64)target, >+ argiregs, >+ mk_RetLoc_simple(RLPri_2Int) ) ); >+ } >+#endif > addInstr( env, mk_iMOVds_RR( tHi, argregs[argreg-1] ) ); > addInstr( env, mk_iMOVds_RR( tLo, argregs[argreg] ) ); > >@@ -3592,7 +3637,6 @@ static void iselInt64Expr_wrk ( HReg* rH > HReg tHi = newVRegI(env); > HReg tmpHi; > HReg tmpLo; >- ULong target; > Bool mode64 = env->mode64; > > argregs[0] = hregPPC_GPR3(mode64); >@@ -3611,10 +3655,18 @@ static void iselInt64Expr_wrk ( HReg* rH > > cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE ); > >- target = toUInt( Ptr_to_ULong( h_calc_DPBtoBCD ) ); >- >- addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs, >+#if defined(VGP_ppc64le_linux) >+ addInstr(env, PPCInstr_Call( cc, (Addr64)h_calc_DPBtoBCD, argiregs, > mk_RetLoc_simple(RLPri_2Int) ) ); >+#else >+ { >+ ULong target; >+ target = toUInt( Ptr_to_ULong( h_calc_DPBtoBCD ) ); >+ addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs, >+ mk_RetLoc_simple(RLPri_2Int) ) ); >+ } >+#endif >+ > addInstr(env, mk_iMOVds_RR(tHi, argregs[argreg-1])); > addInstr(env, mk_iMOVds_RR(tLo, argregs[argreg])); > >@@ -3664,7 +3716,7 @@ static HReg iselFltExpr_wrk ( ISelEnv* e > return lookupIRTemp(env, e->Iex.RdTmp.tmp); > } > >- if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) { >+ if (e->tag == Iex_Load && e->Iex.Load.end == IENDIANESS) { > PPCAMode* am_addr; > HReg r_dst = newVRegF(env); > vassert(e->Iex.Load.ty == Ity_F32); >@@ -3866,7 +3918,7 @@ static HReg iselDblExpr_wrk ( ISelEnv* e > } > > /* --------- LOAD --------- */ >- if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) { >+ if (e->tag == Iex_Load && e->Iex.Load.end == IENDIANESS) { > HReg r_dst = newVRegF(env); > PPCAMode* am_addr; > vassert(e->Iex.Load.ty == Ity_F64); >@@ -4127,7 +4179,7 @@ static HReg iselDfp32Expr_wrk(ISelEnv* e > } > > /* --------- LOAD --------- */ >- if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) { >+ if (e->tag == Iex_Load && e->Iex.Load.end == IENDIANESS) { > PPCAMode* am_addr; > HReg r_dst = newVRegF(env); > vassert(e->Iex.Load.ty == Ity_D32); >@@ -4182,7 +4234,7 @@ static HReg iselDfp64Expr_wrk(ISelEnv* e > return r_dst; > } > >- if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) { >+ if (e->tag == Iex_Load && e->Iex.Load.end == IENDIANESS) { > PPCAMode* am_addr; > HReg r_dst = newVRegF(env); > vassert(e->Iex.Load.ty == Ity_D64); >@@ -4732,7 +4784,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* e > return dst; > } > >- if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) { >+ if (e->tag == Iex_Load && e->Iex.Load.end == IENDIANESS) { > PPCAMode* am_addr; > HReg v_dst = newVRegV(env); > vassert(e->Iex.Load.ty == Ity_V128); >@@ -4826,15 +4878,24 @@ static HReg iselVecExpr_wrk ( ISelEnv* e > /* Store zeros */ > r_zeros = newVRegI(env); > addInstr(env, PPCInstr_LI(r_zeros, 0x0, mode64)); >- addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 )); >+ if (IENDIANESS == Iend_LE) >+ addInstr(env, PPCInstr_Store( 4, am_off0, r_src, mode64 )); >+ else >+ addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 )); > addInstr(env, PPCInstr_Store( 4, am_off4, r_zeros, mode64 )); > addInstr(env, PPCInstr_Store( 4, am_off8, r_zeros, mode64 )); > > /* Store r_src in low word of quadword-aligned mem */ >- addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 )); >+ if (IENDIANESS == Iend_LE) >+ addInstr(env, PPCInstr_Store( 4, am_off12, r_zeros, mode64 )); >+ else >+ addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 )); > > /* Load word into low word of quadword vector reg */ >- addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 )); >+ if (IENDIANESS == Iend_LE) >+ addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off0 )); >+ else >+ addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 )); > > add_to_sp( env, 32 ); // Reset SP > return dst; >@@ -4918,9 +4979,13 @@ static HReg iselVecExpr_wrk ( ISelEnv* e > am_off8 = PPCAMode_IR( 8, r_aligned16 ); > > /* Store 2*I64 to stack */ >- addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 )); >- addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 )); >- >+ if (IENDIANESS == Iend_LE) { >+ addInstr(env, PPCInstr_Store( 8, am_off0, rLo, mode64 )); >+ addInstr(env, PPCInstr_Store( 8, am_off8, rHi, mode64 )); >+ } else { >+ addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 )); >+ addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 )); >+ } > /* Fetch result back from stack. */ > addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0)); > >@@ -5274,7 +5339,7 @@ static void iselStmt ( ISelEnv* env, IRS > IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data); > IREndness end = stmt->Ist.Store.end; > >- if (end != Iend_BE) >+ if (end != IENDIANESS) > goto stmt_fail; > if (!mode64 && (tya != Ity_I32)) > goto stmt_fail; >@@ -5532,7 +5597,7 @@ static void iselStmt ( ISelEnv* env, IRS > IRType tyRes = typeOfIRTemp(env->type_env, res); > IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr); > >- if (stmt->Ist.LLSC.end != Iend_BE) >+ if (stmt->Ist.LLSC.end != IENDIANESS) > goto stmt_fail; > if (!mode64 && (tyAddr != Ity_I32)) > goto stmt_fail; >Index: valgrind-3.9.0-svn20140513r13961/VEX/priv/main_main.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/VEX/priv/main_main.c >+++ valgrind-3.9.0-svn20140513r13961/VEX/priv/main_main.c >@@ -377,7 +377,15 @@ VexTranslateResult LibVEX_Translate ( Ve > emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, > void*,void*,void*,void*)) > emit_PPCInstr; >+#if defined(VGP_ppc64_linux) > host_is_bigendian = True; >+#elif defined(VGP_ppc64le_linux) >+ host_is_bigendian = False; >+#else >+ /* unknown varient of PPC64 */ >+ vex_printf("ERROR: call to getUIntPPCendianly(); Unknown variant of PowerPC\n"); >+#endif >+ > host_word_type = Ity_I64; > vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps)); > break; >Index: valgrind-3.9.0-svn20140513r13961/configure.ac >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/configure.ac >+++ valgrind-3.9.0-svn20140513r13961/configure.ac >@@ -179,6 +179,11 @@ case "${host_cpu}" in > ARCH_MAX="ppc64" > ;; > >+ powerpc64le) >+ AC_MSG_RESULT([ok (${host_cpu})]) >+ ARCH_MAX="ppc64le" >+ ;; >+ > powerpc) > # On Linux this means only a 32-bit capable CPU. > AC_MSG_RESULT([ok (${host_cpu})]) >@@ -518,6 +523,18 @@ case "$ARCH_MAX-$VGCONF_OS" in > fi > AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) > ;; >+ ppc64le-linux) >+ # Little Endian is only supported on PPC64 >+ valt_load_address_sec_norml="0xUNSET" >+ valt_load_address_sec_inner="0xUNSET" >+ VGCONF_ARCH_PRI="ppc64le" >+ VGCONF_ARCH_SEC="" >+ VGCONF_PLATFORM_PRI_CAPS="PPC64LE_LINUX" >+ VGCONF_PLATFORM_SEC_CAPS="" >+ valt_load_address_pri_norml="0x38000000" >+ valt_load_address_pri_inner="0x28000000" >+ AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) >+ ;; > # Darwin gets identified as 32-bit even when it supports 64-bit. > # (Not sure why, possibly because 'uname' returns "i386"?) Just about > # all Macs support both 32-bit and 64-bit, so we just build both. If >@@ -656,7 +673,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_PPC3 > test x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \ > -o x$VGCONF_PLATFORM_SEC_CAPS = xPPC32_LINUX ) > AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_PPC64, >- test x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX ) >+ test x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \ >+ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64LE_LINUX ) > AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_ARM, > test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ > -o x$VGCONF_PLATFORM_SEC_CAPS = xARM_LINUX ) >@@ -681,6 +699,8 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ > -o x$VGCONF_PLATFORM_SEC_CAPS = xPPC32_LINUX) > AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_PPC64_LINUX, > test x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX) >+AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_PPC64LE_LINUX, >+ test x$VGCONF_PLATFORM_PRI_CAPS = xPPC64LE_LINUX) > AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ARM_LINUX, > test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ > -o x$VGCONF_PLATFORM_SEC_CAPS = xARM_LINUX) >@@ -708,6 +728,7 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX, > -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \ > -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \ > -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \ >+ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64LE_LINUX \ > -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ > -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \ > -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/launcher-linux.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/launcher-linux.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/launcher-linux.c >@@ -228,6 +228,10 @@ static const char *select_platform(const > (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || > ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { > platform = "arm64-linux"; >+ } else if (ehdr->e_machine == EM_PPC64 && >+ (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || >+ ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { >+ platform = "ppc64le-linux"; > } > } else if (header[EI_DATA] == ELFDATA2MSB) { > # if !defined(VGPV_arm_linux_android) \ >@@ -321,6 +325,7 @@ int main(int argc, char** argv, char** e > (0==strcmp(VG_PLATFORM,"amd64-linux")) || > (0==strcmp(VG_PLATFORM,"ppc32-linux")) || > (0==strcmp(VG_PLATFORM,"ppc64-linux")) || >+ (0==strcmp(VG_PLATFORM,"ppc64le-linux")) || > (0==strcmp(VG_PLATFORM,"arm-linux")) || > (0==strcmp(VG_PLATFORM,"arm64-linux")) || > (0==strcmp(VG_PLATFORM,"s390x-linux")) || >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_coredump/coredump-elf.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_coredump/coredump-elf.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_coredump/coredump-elf.c >@@ -343,6 +343,27 @@ static void fill_prstatus(const ThreadSt > regs->dsisr = 0; > regs->result = 0; > >+#elif defined(VGP_ppc64le_linux) >+# 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 = 0xf033; /* 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; >+ > #elif defined(VGP_arm_linux) > regs->ARM_r0 = arch->vex.guest_R0; > regs->ARM_r1 = arch->vex.guest_R1; >@@ -458,7 +479,7 @@ static void fill_fpu(const ThreadState * > DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); > # undef DO > >-#elif defined(VGP_ppc64_linux) >+#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > /* The guest state has the FPR fields declared as ULongs, so need > to fish out the values without converting them. > NOTE: The 32 FP registers map to the first 32 VSX registers.*/ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_debuginfo/debuginfo.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_debuginfo/debuginfo.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_debuginfo/debuginfo.c >@@ -1,4 +1,5 @@ > >+ > /*--------------------------------------------------------------------*/ > /*--- Top level management of symbols and debugging information. ---*/ > /*--- debuginfo.c ---*/ >@@ -820,12 +821,12 @@ ULong VG_(di_notify_mmap)( Addr a, Bool > is_rw_map = False; > is_ro_map = False; > >-# if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \ >- || defined(VGA_mips64) >+# if defined(VGA_x86) || defined(VGA_ppc32) \ >+ || defined(VGA_mips32) || defined(VGA_mips64) > is_rx_map = seg->hasR && seg->hasX; > is_rw_map = seg->hasR && seg->hasW; >-# elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm) \ >- || defined(VGA_arm64) >+# elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_ppc64le) \ >+ || defined(VGA_arm) || defined(VGA_arm64) > is_rx_map = seg->hasR && seg->hasX && !seg->hasW; > is_rw_map = seg->hasR && seg->hasW && !seg->hasX; > # elif defined(VGP_s390x_linux) >@@ -2113,7 +2114,8 @@ UWord evalCfiExpr ( XArray* exprs, Int i > case Creg_IA_SP: return eec->uregs->sp; > case Creg_IA_BP: return eec->uregs->fp; > case Creg_MIPS_RA: return eec->uregs->ra; >-# elif defined(VGA_ppc32) || defined(VGA_ppc64) >+# elif defined(VGA_ppc32) \ >+ || defined(VGA_ppc64) || defined(VGA_ppc64le) > # elif defined(VGP_arm64_linux) > case Creg_ARM64_X30: return eec->uregs->x30; > # else >@@ -2359,7 +2361,7 @@ static Addr compute_cfa ( D3UnwindRegs* > case CFIC_IA_BPREL: > cfa = cfsi->cfa_off + uregs->fp; > break; >-# elif defined(VGA_ppc32) || defined(VGA_ppc64) >+# elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_ppc64le) > # elif defined(VGP_arm64_linux) > case CFIC_ARM64_SPREL: > cfa = cfsi->cfa_off + uregs->sp; >@@ -2472,7 +2474,7 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindR > ipHere = uregsHere->ia; > # elif defined(VGA_mips32) || defined(VGA_mips64) > ipHere = uregsHere->pc; >-# elif defined(VGA_ppc32) || defined(VGA_ppc64) >+# elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_ppc64le) > # elif defined(VGP_arm64_linux) > ipHere = uregsHere->pc; > # else >@@ -2554,7 +2556,7 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindR > COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi->ra_how, cfsi->ra_off); > COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off); > COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off); >-# elif defined(VGA_ppc32) || defined(VGA_ppc64) >+# elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_ppc64le) > # elif defined(VGP_arm64_linux) > COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi->ra_how, cfsi->ra_off); > COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off); >@@ -3862,6 +3864,7 @@ void VG_(DebugInfo_syms_getidx) ( const > Int idx, > /*OUT*/Addr* avma, > /*OUT*/Addr* tocptr, >+ /*OUT*/Addr* second_ep, > /*OUT*/UInt* size, > /*OUT*/HChar** pri_name, > /*OUT*/HChar*** sec_names, >@@ -3871,6 +3874,9 @@ void VG_(DebugInfo_syms_getidx) ( const > vg_assert(idx >= 0 && idx < si->symtab_used); > if (avma) *avma = si->symtab[idx].addr; > if (tocptr) *tocptr = si->symtab[idx].tocptr; >+#if defined(VGP_ppc64le_linux) >+ if (second_ep) *second_ep = si->symtab[idx].second_ep; >+#endif > if (size) *size = si->symtab[idx].size; > if (pri_name) *pri_name = si->symtab[idx].pri_name; > if (sec_names) *sec_names = (HChar **)si->symtab[idx].sec_names; // FIXME >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_debuginfo/priv_storage.h >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_debuginfo/priv_storage.h >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_debuginfo/priv_storage.h >@@ -71,6 +71,9 @@ typedef > struct { > Addr addr; /* lowest address of entity */ > Addr tocptr; /* ppc64-linux only: value that R2 should have */ >+#if defined(VGA_ppc64le) >+ Addr second_ep; /* address for secondary entry point, ppc64le */ >+#endif > HChar* pri_name; /* primary name, never NULL */ > HChar** sec_names; /* NULL, or a NULL term'd array of other names */ > // XXX: this could be shrunk (on 32-bit platforms) by using 30 >@@ -265,7 +268,7 @@ typedef > Int x29_off; > } > DiCfSI; >-#elif defined(VGA_ppc32) || defined(VGA_ppc64) >+#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_ppc64le) > /* Just have a struct with the common fields in, so that code that > processes the common fields doesn't have to be ifdef'd against > VGP_/VGA_ symbols. These are not used in any way on ppc32/64-linux >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_debuginfo/readelf.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_debuginfo/readelf.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_debuginfo/readelf.c >@@ -240,7 +240,11 @@ Bool get_elf_symbol_info ( > Bool* from_opd_out, /* ppc64-linux only: did we deref an > .opd entry? */ > Bool* is_text_out, /* is this a text symbol? */ >- Bool* is_ifunc /* is this a STT_GNU_IFUNC function ?*/ >+ Bool* is_ifunc, /* is this a STT_GNU_IFUNC function ?*/ >+ Addr* sym_second_ep /* addr for second entry point. PPC64 LE >+ supports a local and global entry point. >+ Use this value to return the local >+ entry point. */ > ) > { > Bool plausible; >@@ -258,6 +262,7 @@ Bool get_elf_symbol_info ( > *sym_tocptr_out = 0; /* unknown/inapplicable */ > *from_opd_out = False; > *is_ifunc = False; >+ *sym_second_ep = 0; /* unknown/inapplicable */ > /* Get the symbol size, but restrict it to fit in a signed 32 bit > int. Also, deal with the stupid case of negative size by making > the size be 1. Note that sym->st_size has type UWord, >@@ -679,13 +684,59 @@ Bool get_elf_symbol_info ( > } > # endif > >+# if defined(VGP_ppc64le_linux) >+ /* PPC64 LE ABI uses three bits in the st_other field to indicate the number >+ * of instructions between the function's global and local entry points. An >+ * offset of 0 indicates that there is one entry point. The value must be: >+ * >+ * 0 - one entry point, local and global are the same >+ * 1 - reserved >+ * 2 - local entry point is one instruction after the global entry point >+ * 3 - local entry point is two instructions after the global entry point >+ * 4 - local entry point is four instructions after the global entry point >+ * 5 - local entry point is eight instructions after the global entry point >+ * 6 - local entry point is sixteen two instructions after the global entry point >+ * 7 - reserved >+ * >+ * The extract the three bit field from the other field. >+ * (other_field & STO_PPC64_LOCAL_MASK) >> STO_PPC_LOCAL_BIT >+ * >+ * where the #define values are given in include/elf/powerpc.h file for >+ * the PPC binutils. >+ * >+ * coversion of the three bit field to bytes is given by >+ * >+ * ((1 << bit_field) >> 2) << 2 >+ */ >+ #define STO_PPC64_LOCAL_BIT 5 >+ #define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) >+ { >+ unsigned int bit_field, dist_to_local_entry; >+ /* extract the other filed */ >+ bit_field = (sym->st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT; >+ >+ if ((bit_field > 0) && (bit_field < 7)) { >+ /* store the local entry point address */ >+ dist_to_local_entry = ((1 << bit_field) >> 2) << 2; >+ *sym_second_ep = *sym_avma_out + dist_to_local_entry; >+ >+ if (TRACE_SYMTAB_ENABLED) { >+ HChar* sym_name = ML_(img_strdup)(escn_strtab->img, >+ "di.gesi.5", sym_name_ioff); >+ VG_(printf)("Second entry point: %s at %#010x\n", >+ sym_name, (unsigned int)*sym_second_ep); >+ } >+ } >+ } >+# endif >+ > /* Acquire! */ > return True; > } > > > /* Read an ELF symbol table (normal or dynamic). This one is for the >- "normal" case ({x86,amd64,ppc32,arm,mips32,mips64}-linux). */ >+ "normal" case ({x86,amd64,ppc32,arm,mips32,mips64}-linux, ppc64le). */ > static > __attribute__((unused)) /* not referred to on all targets */ > void read_elf_symtab__normal( >@@ -724,6 +775,7 @@ void read_elf_symtab__normal( > Addr sym_avma_really = 0; > Int sym_size = 0; > Addr sym_tocptr = 0; >+ Addr sym_second_ep = 0; > Bool from_opd = False, is_text = False, is_ifunc = False; > DiOffT sym_name_really = DiOffT_INVALID; > if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab, >@@ -733,14 +785,19 @@ void read_elf_symtab__normal( > &sym_avma_really, > &sym_size, > &sym_tocptr, >- &from_opd, &is_text, &is_ifunc)) { >+ &from_opd, &is_text, &is_ifunc, >+ &sym_second_ep)) { > > DiSym disym; > VG_(memset)(&disym, 0, sizeof(disym)); > HChar* cstr = ML_(img_strdup)(escn_strtab->img, > "di.res__n.1", sym_name_really); >+ > disym.addr = sym_avma_really; > disym.tocptr = sym_tocptr; >+# if defined(VGP_ppc64le_linux) >+ disym.second_ep = sym_second_ep; >+#endif > disym.pri_name = ML_(addStr) ( di, cstr, -1 ); > disym.sec_names = NULL; > disym.size = sym_size; >@@ -760,6 +817,10 @@ void read_elf_symtab__normal( > (Int)disym.size, > (HChar*)disym.pri_name > ); >+ if (sym_second_ep != 0) { >+ TRACE_SYMTAB(" second entry point %#010lx\n", >+ sym_second_ep) >+ } > } > > } >@@ -855,6 +916,7 @@ void read_elf_symtab__ppc64_linux( > Addr sym_avma_really = 0; > Int sym_size = 0; > Addr sym_tocptr = 0; >+ Addr sym_second_ep = 0; > Bool from_opd = False, is_text = False, is_ifunc = False; > DiOffT sym_name_really = DiOffT_INVALID; > DiSym disym; >@@ -866,7 +928,8 @@ void read_elf_symtab__ppc64_linux( > &sym_avma_really, > &sym_size, > &sym_tocptr, >- &from_opd, &is_text, &is_ifunc)) { >+ &from_opd, &is_text, &is_ifunc, >+ &sym_second_ep)) { > > /* Check if we've seen this (name,addr) key before. */ > key.addr = sym_avma_really; >@@ -2113,7 +2176,7 @@ Bool ML_(read_elf_debug_info) ( struct _ > BAD(".plt"); > } > } >-# elif defined(VGP_ppc64_linux) >+# elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > /* Accept .plt where mapped as rw (data), or unmapped */ > if (0 == VG_(strcmp)(name, ".plt")) { > if (inrw && !di->plt_present) { >@@ -2774,6 +2837,7 @@ Bool ML_(read_elf_debug_info) ( struct _ > # if !defined(VGP_amd64_linux) \ > && !defined(VGP_s390x_linux) \ > && !defined(VGP_ppc64_linux) \ >+ && !defined(VGP_ppc64le_linux) \ > && !defined(VGPV_arm_linux_android) \ > && !defined(VGPV_x86_linux_android) \ > && !defined(VGP_mips64_linux) >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_dispatch/dispatch-ppc64-linux.S >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_dispatch/dispatch-ppc64-linux.S >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_dispatch/dispatch-ppc64-linux.S >@@ -28,7 +28,7 @@ > The GNU General Public License is contained in the file COPYING. > */ > >-#if defined(VGP_ppc64_linux) >+#if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > #include "pub_core_basics_asm.h" > #include "pub_core_dispatch_asm.h" >@@ -74,14 +74,26 @@ void VG_(disp_run_translations)( UWord* > .section ".text" > .align 2 > .globl VG_(disp_run_translations) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+.type VG_(disp_run_translations),@function >+VG_(disp_run_translations): >+.type .VG_(disp_run_translations),@function >+#else > .section ".opd","aw" > .align 3 > VG_(disp_run_translations): > .quad .VG_(disp_run_translations),.TOC.@tocbase,0 > .previous > .type .VG_(disp_run_translations),@function >+#endif > .globl .VG_(disp_run_translations) > .VG_(disp_run_translations): >+#if _CALL_ELF == 2 >+0: addis 2, 12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(disp_run_translations), .-VG_(disp_run_translations) >+#endif >+ > /* r3 holds two_words */ > /* r4 holds guest_state */ > /* r5 holds host_addr */ >@@ -193,7 +205,7 @@ VG_(disp_run_translations): > /* 88(sp) used later to load fpscr with zero */ > /* 48:87(sp) free */ > >- /* Linkage Area (reserved) >+ /* Linkage Area (reserved) BE ABI > 40(sp) : TOC > 32(sp) : link editor doubleword > 24(sp) : compiler doubleword >@@ -231,6 +243,12 @@ VG_(disp_run_translations): > /* Set up the guest state ptr */ > mr 31,4 /* r31 (generated code gsp) = r4 */ > >+#if _CALL_ELF == 2 >+/* for the LE ABI need to setup r2 and r12 */ >+0: addis 2, 12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+#endif >+ > /* and jump into the code cache. Chained translations in > the code cache run, until for whatever reason, they can't > continue. When that happens, the translation in question >@@ -384,6 +402,9 @@ VG_(disp_run_translations): > mtlr 0 > addi 1,1,624 /* stack_size */ > blr >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(disp_run_translations),.-VG_(disp_run_translations) >+#endif > > > /*----------------------------------------------------*/ >@@ -394,14 +415,24 @@ VG_(disp_run_translations): > .section ".text" > .align 2 > .globl VG_(disp_cp_chain_me_to_slowEP) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .type VG_(disp_cp_chain_me_to_slowEP),@function >+VG_(disp_cp_chain_me_to_slowEP): >+#else > .section ".opd","aw" > .align 3 > VG_(disp_cp_chain_me_to_slowEP): > .quad .VG_(disp_cp_chain_me_to_slowEP),.TOC.@tocbase,0 > .previous >+#endif > .type .VG_(disp_cp_chain_me_to_slowEP),@function > .globl .VG_(disp_cp_chain_me_to_slowEP) > .VG_(disp_cp_chain_me_to_slowEP): >+#if _CALL_ELF == 2 >+0: addis 2, 12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(disp_cp_chain_me_to_slowEP), .-VG_(disp_cp_chain_me_to_slowEP) >+#endif > /* We got called. The return address indicates > where the patching needs to happen. Collect > the return address and, exit back to C land, >@@ -414,19 +445,32 @@ VG_(disp_cp_chain_me_to_slowEP): > */ > subi 7,7,20+4+4 > b .postamble >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(disp_cp_chain_me_to_slowEP),.-VG_(disp_cp_chain_me_to_slowEP) >+#endif > > /* ------ Chain me to fast entry point ------ */ > .section ".text" > .align 2 > .globl VG_(disp_cp_chain_me_to_fastEP) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .type VG_(disp_cp_chain_me_to_fastEP),@function >+VG_(disp_cp_chain_me_to_fastEP): >+#else > .section ".opd","aw" > .align 3 > VG_(disp_cp_chain_me_to_fastEP): > .quad .VG_(disp_cp_chain_me_to_fastEP),.TOC.@tocbase,0 > .previous >+#endif > .type .VG_(disp_cp_chain_me_to_fastEP),@function > .globl .VG_(disp_cp_chain_me_to_fastEP) > .VG_(disp_cp_chain_me_to_fastEP): >+#if _CALL_ELF == 2 >+0: addis 2, 12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(disp_cp_chain_me_to_fastEP), .-VG_(disp_cp_chain_me_to_fastEP) >+#endif > /* We got called. The return address indicates > where the patching needs to happen. Collect > the return address and, exit back to C land, >@@ -439,19 +483,32 @@ VG_(disp_cp_chain_me_to_fastEP): > */ > subi 7,7,20+4+4 > b .postamble >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(disp_cp_chain_me_to_fastEP),.-VG_(disp_cp_chain_me_to_fastEP) >+#endif > >-/* ------ Indirect but boring jump ------ */ >+ /* ------ Indirect but boring jump ------ */ > .section ".text" > .align 2 > .globl VG_(disp_cp_xindir) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .type VG_(disp_cp_xindir),@function >+VG_(disp_cp_xindir): >+#else > .section ".opd","aw" > .align 3 > VG_(disp_cp_xindir): > .quad .VG_(disp_cp_xindir),.TOC.@tocbase,0 > .previous >+#endif > .type .VG_(disp_cp_xindir),@function > .globl .VG_(disp_cp_xindir) > .VG_(disp_cp_xindir): >+#if _CALL_ELF == 2 >+0: addis 2, 12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(disp_cp_xindir), .-VG_(disp_cp_xindir) >+#endif > /* Where are we going? */ > ld 3,OFFSET_ppc64_CIA(31) > >@@ -478,6 +535,9 @@ VG_(disp_cp_xindir): > /* Found a match. Jump to .host. */ > mtctr 7 > bctr >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(disp_cp_xindir),.-VG_(disp_cp_xindir) >+#endif > > .fast_lookup_failed: > /* stats only */ >@@ -495,11 +555,21 @@ VG_(disp_cp_xindir): > .section ".text" > .align 2 > .globl VG_(disp_cp_xassisted) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .type VG_(disp_cp_xassisted),@function >+VG_(disp_cp_xassisted): >+#else > .section ".opd","aw" > .align 3 > VG_(disp_cp_xassisted): > .quad .VG_(disp_cp_xassisted),.TOC.@tocbase,0 > .previous >+#endif >+#if _CALL_ELF == 2 >+0: addis 2, 12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(disp_cp_xassisted), .-VG_(disp_cp_xassisted) >+#endif > .type .VG_(disp_cp_xassisted),@function > .globl .VG_(disp_cp_xassisted) > .VG_(disp_cp_xassisted): >@@ -508,29 +578,44 @@ VG_(disp_cp_xassisted): > li 7,0 > b .postamble > >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(disp_cp_xassisted),.-VG_(disp_cp_xassisted) >+#endif >+ > /* ------ Event check failed ------ */ > .section ".text" > .align 2 > .globl VG_(disp_cp_evcheck_fail) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .type VG_(disp_cp_evcheck_fail),@function >+VG_(disp_cp_evcheck_fail): >+#else > .section ".opd","aw" > .align 3 > VG_(disp_cp_evcheck_fail): > .quad .VG_(disp_cp_evcheck_fail),.TOC.@tocbase,0 > .previous >+#endif >+#if _CALL_ELF == 2 >+0: addis 2, 12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(disp_cp_evcheck_fail), .-VG_(disp_cp_evcheck_fail) >+#endif > .type .VG_(disp_cp_evcheck_fail),@function > .globl .VG_(disp_cp_evcheck_fail) > .VG_(disp_cp_evcheck_fail): > li 6,VG_TRC_INNER_COUNTERZERO > li 7,0 > b .postamble >- >- >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(disp_cp_evcheck_fail),.-VG_(disp_cp_evcheck_fail) >+#endif > .size .VG_(disp_run_translations), .-.VG_(disp_run_translations) > > /* Let the linker know we don't need an executable stack */ > .section .note.GNU-stack,"",@progbits > >-#endif // defined(VGP_ppc64_linux) >+#endif // defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > /*--------------------------------------------------------------------*/ > /*--- end ---*/ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_initimg/initimg-linux.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_initimg/initimg-linux.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_initimg/initimg-linux.c >@@ -366,7 +366,7 @@ struct auxv *find_auxv(UWord* sp) > sp++; > sp++; > >-#if defined(VGA_ppc32) || defined(VGA_ppc64) >+#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_ppc64le) > # if defined AT_IGNOREPPC > while (*sp == AT_IGNOREPPC) // skip AT_IGNOREPPC entries > sp += 2; >@@ -457,7 +457,8 @@ Addr setup_client_stack( void* init_sp, > auxsize += sizeof(*cauxv); > } > >-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) >+# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) || \ >+ defined(VGP_ppc64le_linux) > auxsize += 2 * sizeof(*cauxv); > # endif > >@@ -614,7 +615,8 @@ Addr setup_client_stack( void* init_sp, > // We do not take ULong* (as ULong 8 bytes on a 32 bits), > // => we take UWord* > >-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) >+# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) || \ >+ defined(VGP_ppc64le_linux) > auxv[0].a_type = AT_IGNOREPPC; > auxv[0].u.a_val = AT_IGNOREPPC; > auxv[1].a_type = AT_IGNOREPPC; >@@ -707,7 +709,7 @@ Addr setup_client_stack( void* init_sp, > "PPC32 icache line size %u (type %u)\n", > (UInt)auxv->u.a_val, (UInt)auxv->a_type ); > } >-# elif defined(VGP_ppc64_linux) >+# elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > /* acquire cache info */ > if (auxv->u.a_val > 0) { > VG_(machine_ppc64_set_clszB)( auxv->u.a_val ); >@@ -718,7 +720,8 @@ Addr setup_client_stack( void* init_sp, > # endif > break; > >-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) >+# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) || \ >+ defined(VGP_ppc64le_linux) > case AT_IGNOREPPC: > break; > # endif >@@ -738,7 +741,8 @@ Addr setup_client_stack( void* init_sp, > auxv->a_type = AT_IGNORE; > break; > >-# if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64_linux) >+# if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64_linux) && \ >+ !defined(VGP_ppc64le_linux) > case AT_SYSINFO_EHDR: { > /* Trash this, because we don't reproduce it */ > const NSegment* ehdrseg = VG_(am_find_nsegment)((Addr)auxv->u.a_ptr); >@@ -1024,7 +1028,7 @@ void VG_(ii_finalise_image)( IIFinaliseI > arch->vex.guest_GPR1 = iifii.initial_client_SP; > arch->vex.guest_CIA = iifii.initial_client_IP; > >-# elif defined(VGP_ppc64_linux) >+# elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > vg_assert(0 == sizeof(VexGuestPPC64State) % 16); > > /* Zero out the initial state, and set up the simulated FPU in a >@@ -1039,7 +1043,9 @@ void VG_(ii_finalise_image)( IIFinaliseI > arch->vex.guest_GPR1 = iifii.initial_client_SP; > arch->vex.guest_GPR2 = iifii.initial_client_TOC; > arch->vex.guest_CIA = iifii.initial_client_IP; >- >+#if defined(VGP_ppc64le_linux) >+ arch->vex.guest_GPR12 = iifii.initial_client_IP; >+#endif > # elif defined(VGP_arm_linux) > /* Zero out the initial state, and set up the simulated FPU in a > sane way. */ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_libcsetjmp.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_libcsetjmp.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_libcsetjmp.c >@@ -29,7 +29,6 @@ > > /* Contributed by Julian Seward <jseward@acm.org> */ > >- > #include "pub_core_basics.h" > #include "pub_core_libcsetjmp.h" /* self */ > >@@ -270,7 +269,116 @@ __asm__( > ".previous" "\n" > ); > >-#endif /* VGP_ppc64_linux */ >+#elif defined(VGP_ppc64le_linux) >+ >+__asm__( >+".section \".toc\",\"aw\"" "\n" >+ >+".section \".text\"" "\n" >+".align 2" "\n" >+".p2align 4,,15" "\n" >+".globl VG_MINIMAL_SETJMP" "\n" >+".type VG_MINIMAL_SETJMP,@function" "\n" >+"VG_MINIMAL_SETJMP:" "\n" >+" .localentry VG_MINIMAL_SETJMP, .-VG_MINIMAL_SETJMP" "\n" >+" std 0, 0(3)" "\n" >+" std 1, 8(3)" "\n" >+" std 2, 16(3)" "\n" >+" std 3, 24(3)" "\n" >+" std 4, 32(3)" "\n" >+" std 5, 40(3)" "\n" >+" std 6, 48(3)" "\n" >+" std 7, 56(3)" "\n" >+" std 8, 64(3)" "\n" >+" std 9, 72(3)" "\n" >+" std 10, 80(3)" "\n" >+" std 11, 88(3)" "\n" >+" std 12, 96(3)" "\n" >+" std 13, 104(3)" "\n" >+" std 14, 112(3)" "\n" >+" std 15, 120(3)" "\n" >+" std 16, 128(3)" "\n" >+" std 17, 136(3)" "\n" >+" std 18, 144(3)" "\n" >+" std 19, 152(3)" "\n" >+" std 20, 160(3)" "\n" >+" std 21, 168(3)" "\n" >+" std 22, 176(3)" "\n" >+" std 23, 184(3)" "\n" >+" std 24, 192(3)" "\n" >+" std 25, 200(3)" "\n" >+" std 26, 208(3)" "\n" >+" std 27, 216(3)" "\n" >+" std 28, 224(3)" "\n" >+" std 29, 232(3)" "\n" >+" std 30, 240(3)" "\n" >+" std 31, 248(3)" "\n" >+ // must use a caller-save register here as scratch, hence r4 >+" mflr 4" "\n" >+" std 4, 256(3)" "\n" >+" mfcr 4" "\n" >+" std 4, 264(3)" "\n" >+" li 3, 0" "\n" >+" blr" "\n" >+"" "\n" >+ >+ >+".globl VG_MINIMAL_LONGJMP" "\n" >+".type VG_MINIMAL_LONGJMP, @function" "\n" >+"VG_MINIMAL_LONGJMP:" "\n" >+" .localentry VG_MINIMAL_LONGJMP, .-VG_MINIMAL_LONGJMP" "\n" >+ // do r4 = 1 >+ // and park it in the restore slot for r3 (the ret reg) >+" li 4, 1" "\n" >+" std 4, 24(3)" "\n" >+ // restore everything except r3 >+ // then r3 last of all >+ // then blr >+" ld 0, 256(3)" "\n" >+" mtlr 0" "\n" >+" ld 0, 264(3)" "\n" >+" mtcr 0" "\n" >+" ld 0, 0(3)" "\n" >+" ld 1, 8(3)" "\n" >+" ld 2, 16(3)" "\n" >+ // r3 is done at the end >+" ld 4, 32(3)" "\n" >+" ld 5, 40(3)" "\n" >+" ld 6, 48(3)" "\n" >+" ld 7, 56(3)" "\n" >+" ld 8, 64(3)" "\n" >+" ld 9, 72(3)" "\n" >+" ld 10, 80(3)" "\n" >+" ld 11, 88(3)" "\n" >+" ld 12, 96(3)" "\n" >+" ld 13, 104(3)" "\n" >+" ld 14, 112(3)" "\n" >+" ld 15, 120(3)" "\n" >+" ld 16, 128(3)" "\n" >+" ld 17, 136(3)" "\n" >+" ld 18, 144(3)" "\n" >+" ld 19, 152(3)" "\n" >+" ld 20, 160(3)" "\n" >+" ld 21, 168(3)" "\n" >+" ld 22, 176(3)" "\n" >+" ld 23, 184(3)" "\n" >+" ld 24, 192(3)" "\n" >+" ld 25, 200(3)" "\n" >+" ld 26, 208(3)" "\n" >+" ld 27, 216(3)" "\n" >+" ld 28, 224(3)" "\n" >+" ld 29, 232(3)" "\n" >+" ld 30, 240(3)" "\n" >+" ld 31, 248(3)" "\n" >+" ld 3, 24(3)" "\n" >+" blr" "\n" >+"" "\n" >+ >+".previous" "\n" >+".previous" "\n" >+); >+ >+#endif /* VGP_ppc64_linux || VGP_ppc64le_linux */ > > > /* ------------ amd64-{linux,darwin} ------------ */ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_main.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_main.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_main.c >@@ -2020,7 +2020,8 @@ Int valgrind_main ( Int argc, HChar **ar > > # if defined(VGP_x86_linux) > iters = 10; >-# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) >+# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \ >+ || defined(VGP_ppc64le_linux) > iters = 10; > # elif defined(VGP_ppc32_linux) > iters = 5; >@@ -2593,7 +2594,10 @@ static void final_tidyup(ThreadId tid) > 0 == __libc_freeres_wrapper ) > return; /* can't/won't do it */ > >-# if defined(VGP_ppc64_linux) >+#if defined(VGP_ppc64_linux) >+ /* VGP_ppc64le_linux, not needed as the API has the function determine >+ * the TOC value if needed. >+ */ > r2 = VG_(get_tocptr)( __libc_freeres_wrapper ); > if (r2 == 0) { > VG_(message)(Vg_UserMsg, >@@ -2618,6 +2622,10 @@ static void final_tidyup(ThreadId tid) > VG_(set_IP)(tid, __libc_freeres_wrapper); > # if defined(VGP_ppc64_linux) > VG_(threads)[tid].arch.vex.guest_GPR2 = r2; >+# elif defined(VGP_ppc64le_linux) >+ /* setting GPR2 but not really needed, GPR12 is needed */ >+ VG_(threads)[tid].arch.vex.guest_GPR2 = __libc_freeres_wrapper; >+ VG_(threads)[tid].arch.vex.guest_GPR12 = __libc_freeres_wrapper; > # endif > /* mips-linux note: we need to set t9 */ > # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) >@@ -2859,6 +2867,49 @@ asm("\n" > "\tnop\n" > "\ttrap\n" > ); >+#elif defined(VGP_ppc64le_linux) >+asm("\n" >+ "\t.align 2\n" >+ "\t.global _start\n" >+ "\t.type _start,@function\n" >+ "_start:\n" >+ "#if _CALL_ELF == 2 \n" >+ "0: addis 2,12,.TOC.-0b@ha\n" >+ " addi 2,2,.TOC.-0b@l\n" >+ " .localentry _start, .-_start\n" >+ "#endif \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_linux, passing it the initial SP. */ >+ "\tmr 3,1\n" >+ "\tmr 1,16\n" >+ "\tlis 14, _start_in_C_linux@highest\n" >+ "\tori 14,14,_start_in_C_linux@higher\n" >+ "\tsldi 14,14,32\n" >+ "\toris 14,14,_start_in_C_linux@h\n" >+ "\tori 14,14,_start_in_C_linux@l\n" >+ //carll "\tld 14,0(14)\n" >+ "\tmtctr 14\n" >+ "\tbctrl\n" >+ "\tnop\n" >+ "\ttrap\n" >+); > #elif defined(VGP_s390x_linux) > /* > This is the canonical entry point, usually the first thing in the text >@@ -3073,7 +3124,7 @@ void _start_in_C_linux ( UWord* pArgc ) > the_iicii.sp_at_startup = (Addr)pArgc; > > # if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \ >- || defined(VGP_arm64_linux) >+ || defined(VGP_ppc64le_linux) || defined(VGP_arm64_linux) > { > /* ppc/ppc64 can be configured with different page sizes. > Determine this early. This is an ugly hack and really should >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_redir.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_redir.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_redir.c >@@ -397,7 +397,7 @@ void VG_(redir_notify_new_DebugInfo)( De > TopSpec* newts; > HChar* sym_name_pri; > HChar** sym_names_sec; >- Addr sym_addr, sym_toc; >+ Addr sym_addr, sym_toc, second_ep; > HChar demangled_sopatt[N_DEMANGLED]; > HChar demangled_fnpatt[N_DEMANGLED]; > Bool check_ppcTOCs = False; >@@ -499,7 +499,7 @@ void VG_(redir_notify_new_DebugInfo)( De > > nsyms = VG_(DebugInfo_syms_howmany)( newdi ); > for (i = 0; i < nsyms; i++) { >- VG_(DebugInfo_syms_getidx)( newdi, i, &sym_addr, &sym_toc, >+ VG_(DebugInfo_syms_getidx)( newdi, i, &sym_addr, &sym_toc, &second_ep, > NULL, &sym_name_pri, &sym_names_sec, > &isText, NULL ); > /* Set up to conveniently iterate over all names for this symbol. */ >@@ -592,7 +592,7 @@ void VG_(redir_notify_new_DebugInfo)( De > > if (check_ppcTOCs) { > for (i = 0; i < nsyms; i++) { >- VG_(DebugInfo_syms_getidx)( newdi, i, &sym_addr, &sym_toc, >+ VG_(DebugInfo_syms_getidx)( newdi, i, &sym_addr, &sym_toc, &second_ep, > NULL, &sym_name_pri, &sym_names_sec, > &isText, NULL ); > HChar* twoslots[2]; >@@ -755,7 +755,9 @@ void generate_and_add_actives ( > of trashing the caches less. */ > nsyms = VG_(DebugInfo_syms_howmany)( di ); > for (i = 0; i < nsyms; i++) { >- VG_(DebugInfo_syms_getidx)( di, i, &sym_addr, NULL, >+ Addr second_ep = 0; >+ >+ VG_(DebugInfo_syms_getidx)( di, i, &sym_addr, NULL, &second_ep, > NULL, &sym_name_pri, &sym_names_sec, > &isText, &isIFunc ); > HChar* twoslots[2]; >@@ -783,6 +785,18 @@ void generate_and_add_actives ( > act.isIFunc = isIFunc; > sp->done = True; > maybe_add_active( act ); >+ >+#if defined(VGP_ppc64le_linux) >+ /* If the function being wrapped has a secondary entry point >+ * redirect it to the global entry point. The redirection >+ * must save and setup r2 then setup r12 for the new function. >+ * On return, r2 must be restored. >+ */ >+ if (second_ep != 0) { >+ act.from_addr = second_ep; >+ maybe_add_active( act ); >+ } >+#endif > } > } /* for (sp = specs; sp; sp = sp->next) */ > >@@ -1298,6 +1312,26 @@ void VG_(redir_initialise) ( void ) > ); > } > >+# elif defined(VGP_ppc64le_linux) >+ /* If we're using memcheck, use these intercepts right from >+ the start, otherwise ld.so makes a lot of noise. */ >+ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { >+ >+ /* this is mandatory - can't sanely continue without it */ >+ add_hardwired_spec( >+ "ld64.so.2", "strlen", >+ (Addr)&VG_(ppc64_linux_REDIR_FOR_strlen), >+ complain_about_stripped_glibc_ldso >+ ); >+ >+ add_hardwired_spec( >+ "ld64.so.2", "index", >+ (Addr)&VG_(ppc64_linux_REDIR_FOR_strchr), >+ NULL /* not mandatory - so why bother at all? */ >+ /* glibc-2.5 (FC6, ppc64) seems fine without it */ >+ ); >+ } >+ > # elif defined(VGP_arm_linux) > /* If we're using memcheck, use these intercepts right from the > start, otherwise ld.so makes a lot of noise. In most ARM-linux >@@ -1565,7 +1599,7 @@ static void handle_require_text_symbols > Bool isText = False; > HChar* sym_name_pri = NULL; > HChar** sym_names_sec = NULL; >- VG_(DebugInfo_syms_getidx)( di, j, NULL, NULL, >+ VG_(DebugInfo_syms_getidx)( di, j, NULL, NULL, NULL, > NULL, &sym_name_pri, &sym_names_sec, > &isText, NULL ); > HChar* twoslots[2]; >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_sigframe/sigframe-ppc64-linux.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_sigframe/sigframe-ppc64-linux.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_sigframe/sigframe-ppc64-linux.c >@@ -31,7 +31,7 @@ > The GNU General Public License is contained in the file COPYING. > */ > >-#if defined(VGP_ppc64_linux) >+#if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > #include "pub_core_basics.h" > #include "pub_core_vki.h" >@@ -252,7 +252,11 @@ void VG_(sigframe_create)( ThreadId tid, > # undef DO > > frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP] = tst->arch.vex.guest_CIA; >+#ifdef VGP_ppc64le_linux >+ frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR] = 0xf033; /* pretty arbitrary */ >+#else > frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR] = 0xf032; /* pretty arbitrary */ >+#endif > frame->uc.uc_mcontext.gp_regs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3; > frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR] = tst->arch.vex.guest_CTR; > frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK] = tst->arch.vex.guest_LR; >@@ -302,8 +306,13 @@ void VG_(sigframe_create)( ThreadId tid, > > /* Handler is in fact a standard ppc64-linux function descriptor, > so extract the function entry point and also the toc ptr to use. */ >+#if defined(VGP_ppc64_linux) // BE > SET_SIGNAL_GPR(tid, 2, (Addr) ((ULong*)handler)[1]); > tst->arch.vex.guest_CIA = (Addr) ((ULong*)handler)[0]; >+#else // LE >+ SET_SIGNAL_GPR(tid, 12, (Addr) handler); >+ tst->arch.vex.guest_CIA = (Addr) handler; >+#endif > > priv = &frame->priv; > priv->magicPI = 0x31415927; >@@ -388,7 +397,7 @@ void VG_(sigframe_destroy)( ThreadId tid > VG_TRACK( post_deliver_signal, tid, sigNo ); > } > >-#endif // defined(VGP_ppc64_linux) >+#endif // defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > /*--------------------------------------------------------------------*/ > /*--- end ---*/ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_signals.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_signals.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_signals.c >@@ -348,7 +348,7 @@ typedef struct SigQueue { > (srP)->misc.PPC32.r_lr = (uc)->uc_regs->mc_gregs[VKI_PT_LNK]; \ > } > >-#elif defined(VGP_ppc64_linux) >+#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_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]) > /* Dubious hack: if there is an error, only consider the lowest 8 >@@ -866,6 +866,20 @@ extern void my_sigreturn(void); > " li 0, " #name "\n" \ > " sc\n" > >+#elif defined(VGP_ppc64le_linux) >+# define _MY_SIGRETURN(name) \ >+ ".align 2\n" \ >+ ".globl my_sigreturn\n" \ >+ ".type .my_sigreturn,@function\n" \ >+ "my_sigreturn:\n" \ >+ "#if _CALL_ELF == 2 \n" \ >+ "0: addis 2,12,.TOC.-0b@ha\n" \ >+ " addi 2,2,.TOC.-0b@l\n" \ >+ " .localentry my_sigreturn,.-my_sigreturn\n" \ >+ "#endif \n" \ >+ " sc\n" \ >+ " .size my_sigreturn,.-my_sigreturn\n" >+ > #elif defined(VGP_arm_linux) > # define _MY_SIGRETURN(name) \ > ".text\n" \ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_stacktrace.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_stacktrace.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_stacktrace.c >@@ -630,7 +630,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId > Addr fp_max_orig ) > { > Bool lr_is_first_RA = False; >-# if defined(VG_PLAT_USES_PPCTOC) >+# if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux) > Word redir_stack_size = 0; > Word redirs_used = 0; > # endif >@@ -685,7 +685,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId > /* fp is %r1. ip is %cia. Note, ppc uses r1 as both the stack and > frame pointers. */ > >-# if defined(VGP_ppc64_linux) >+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > redir_stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE; > redirs_used = 0; > # endif >@@ -760,7 +760,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId > else > ip = (((UWord*)fp)[lr_offset]); > >-# if defined(VG_PLAT_USES_PPCTOC) >+# if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux) > /* Nasty hack to do with function replacement/wrapping on > ppc64-linux. If LR points to our magic return stub, > then we are in a wrapped or intercepted function, in >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_syscall.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_syscall.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_syscall.c >@@ -422,6 +422,42 @@ asm( > " blr\n" > ); > >+#elif defined(VGP_ppc64le_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 bit of [1]. */ >+extern void do_syscall_WRK ( ULong* argblock ); >+asm( >+".align 2\n" >+".globl do_syscall_WRK\n" >+".type do_syscall_WRK,@function\n" >+"do_syscall_WRK:\n" >+"#if _CALL_ELF == 2" "\n" >+"0: addis 2,12,.TOC.-0b@ha\n" >+" addi 2,2,.TOC.-0b@l\n" >+" .localentry do_syscall_WRK, .-do_syscall_WRK\n" >+"#endif" "\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 */ >+" 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" >+" .size do_syscall_WRK, .-do_syscall_WRK\n" >+); >+ > #elif defined(VGP_arm_linux) > /* I think the conventions are: > args in r0 r1 r2 r3 r4 r5 >@@ -720,7 +756,7 @@ SysRes VG_(do_syscall) ( UWord sysno, UW > UInt cr0so = (UInt)(ret); > return VG_(mk_SysRes_ppc32_linux)( val, cr0so ); > >-# elif defined(VGP_ppc64_linux) >+# elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > ULong argblock[7]; > argblock[0] = sysno; > argblock[1] = a1; >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_syswrap/syscall-ppc64-linux.S >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_syswrap/syscall-ppc64-linux.S >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_syswrap/syscall-ppc64-linux.S >@@ -27,7 +27,7 @@ > The GNU General Public License is contained in the file COPYING. > */ > >-#if defined(VGP_ppc64_linux) >+#if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > #include "pub_core_basics_asm.h" > #include "pub_core_vkiscnums_asm.h" >@@ -75,12 +75,25 @@ > > .align 2 > .globl ML_(do_syscall_for_client_WRK) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+.type .ML_(do_syscall_for_client_WRK),@function >+ML_(do_syscall_for_client_WRK): >+0: addis 2,12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry ML_(do_syscall_for_client_WRK), .-ML_(do_syscall_for_client_WRK) >+#else > .section ".opd","aw" > .align 3 >-ML_(do_syscall_for_client_WRK): >+ML_(do_syscall_for_client_WRK): > .quad .ML_(do_syscall_for_client_WRK),.TOC.@tocbase,0 > .previous >-.type .ML_(do_syscall_for_client_WRK),@function >+#endif >+#if _CALL_ELF == 2 >+0: addis 2,12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry ML_(do_syscall_for_client_WRK), .-ML_(do_syscall_for_client_WRK) >+#endif >+.type .ML_(do_syscall_for_client_WRK),@function > .globl .ML_(do_syscall_for_client_WRK) > .ML_(do_syscall_for_client_WRK): > /* make a stack frame */ >@@ -144,6 +157,11 @@ ML_(do_syscall_for_client_WRK): > /* failure: return 0x8000 | error code */ > 7: ori 3,3,0x8000 /* FAILURE -- ensure return value is nonzero */ > b 5b >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size ML_(do_syscall_for_client_WRK),.-ML_(do_syscall_for_client_WRK) >+#else >+ .size ML_(do_syscall_for_client_WRK),.-.L.ML_(do_syscall_for_client_WRK) >+#endif > > .section .rodata > /* export the ranges so that >@@ -165,7 +183,7 @@ ML_(blksys_finished): .quad 5b > /* Let the linker know we don't need an executable stack */ > .section .note.GNU-stack,"",@progbits > >-#endif // defined(VGP_ppc64_linux) >+#endif // defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > /*--------------------------------------------------------------------*/ > /*--- end ---*/ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_syswrap/syswrap-main.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_syswrap/syswrap-main.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_syswrap/syswrap-main.c >@@ -441,7 +441,7 @@ void getSyscallArgsFromGuestState ( /*OU > canonical->arg7 = 0; > canonical->arg8 = 0; > >-#elif defined(VGP_ppc64_linux) >+#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; > canonical->sysno = gst->guest_GPR0; > canonical->arg1 = gst->guest_GPR3; >@@ -687,7 +687,7 @@ void putSyscallArgsIntoGuestState ( /*IN > gst->guest_GPR7 = canonical->arg5; > gst->guest_GPR8 = canonical->arg6; > >-#elif defined(VGP_ppc64_linux) >+#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; > gst->guest_GPR0 = canonical->sysno; > gst->guest_GPR3 = canonical->arg1; >@@ -818,7 +818,7 @@ void getSyscallStatusFromGuestState ( /* > canonical->sres = VG_(mk_SysRes_ppc32_linux)( gst->guest_GPR3, cr0so ); > canonical->what = SsComplete; > >-# elif defined(VGP_ppc64_linux) >+# elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; > UInt cr = LibVEX_GuestPPC64_get_CR( gst ); > UInt cr0so = (cr >> 28) & 1; >@@ -976,7 +976,7 @@ void putSyscallStatusIntoGuestState ( /* > VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, > OFFSET_ppc32_CR0_0, sizeof(UChar) ); > >-# elif defined(VGP_ppc64_linux) >+# elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; > UInt old_cr = LibVEX_GuestPPC64_get_CR(gst); > vg_assert(canonical->what == SsComplete); >@@ -1181,7 +1181,7 @@ void getSyscallArgLayout ( /*OUT*/Syscal > layout->uu_arg7 = -1; /* impossible value */ > layout->uu_arg8 = -1; /* impossible value */ > >-#elif defined(VGP_ppc64_linux) >+#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > layout->o_sysno = OFFSET_ppc64_GPR0; > layout->o_arg1 = OFFSET_ppc64_GPR3; > layout->o_arg2 = OFFSET_ppc64_GPR4; >@@ -2006,6 +2006,25 @@ void ML_(fixup_guest_state_to_restart_sy > vg_assert(p[0] == 0x44 && p[1] == 0x0 && p[2] == 0x0 && p[3] == 0x2); > } > >+#elif defined(VGP_ppc64le_linux) >+ arch->vex.guest_CIA -= 4; // sizeof(ppc32 instr) >+ >+ /* Make sure our caller is actually sane, and we're really backing >+ back over a syscall. >+ >+ sc == 44 00 00 02 >+ */ >+ { >+ UChar *p = (UChar *)arch->vex.guest_CIA; >+ >+ if (p[3] != 0x44 || p[2] != 0x0 || p[1] != 0x0 || p[0] != 0x02) >+ VG_(message)(Vg_DebugMsg, >+ "?! restarting over syscall at %#llx %02x %02x %02x %02x\n", >+ arch->vex.guest_CIA + 0ULL, p[3], p[2], p[1], p[0]); >+ >+ vg_assert(p[3] == 0x44 && p[2] == 0x0 && p[1] == 0x0 && p[0] == 0x2); >+ } >+ > #elif defined(VGP_arm_linux) > if (arch->vex.guest_R15T & 1) { > // Thumb mode. SVC is a encoded as >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_syswrap/syswrap-ppc64-linux.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_syswrap/syswrap-ppc64-linux.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_syswrap/syswrap-ppc64-linux.c >@@ -28,7 +28,7 @@ > The GNU General Public License is contained in the file COPYING. > */ > >-#if defined(VGP_ppc64_linux) >+#if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > #include "pub_core_basics.h" > #include "pub_core_vki.h" >@@ -78,6 +78,7 @@ void ML_(call_on_new_stack_0_1) ( Addr s > address, the second word is the TOC ptr (r2), and the third word is > the static chain value. */ > asm( >+#if defined(VGP_ppc64_linux) > " .align 2\n" > " .globl vgModuleLocal_call_on_new_stack_0_1\n" > " .section \".opd\",\"aw\"\n" >@@ -126,6 +127,55 @@ asm( > " mtcr 0\n\t" // CAB: Need this? > " bctr\n\t" // jump to dst > " trap\n" // should never get here >+#else >+// ppc64le_linux >+" .align 2\n" >+" .globl vgModuleLocal_call_on_new_stack_0_1\n" >+"vgModuleLocal_call_on_new_stack_0_1:\n" >+" .type .vgModuleLocal_call_on_new_stack_0_1,@function\n" >+"#if _CALL_ELF == 2 \n" >+"0: addis 2,12,.TOC.-0b@ha\n" >+" addi 2,2,.TOC.-0b@l\n" >+"#endif\n" >+".localentry vgModuleLocal_call_on_new_stack_0_1, .-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_ptr 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 >+#endif > ); > > >@@ -170,6 +220,7 @@ ULong do_syscall_clone_ppc64_linux ( Wor > Int* parent_tid, > void/*vki_modify_ldt_t*/ * ); > asm( >+#if defined(VGP_ppc64_linux) > " .align 2\n" > " .globl do_syscall_clone_ppc64_linux\n" > " .section \".opd\",\"aw\"\n" >@@ -240,6 +291,79 @@ asm( > " ld 31,56(1)\n" > " addi 1,1,64\n" > " blr\n" >+ >+#else >+" .align 2\n" >+" .globl do_syscall_clone_ppc64_linux\n" >+" .type do_syscall_clone_ppc64_linux,@function\n" >+"do_syscall_clone_ppc64_linux:\n" >+" .globl .do_syscall_clone_ppc64_linux\n" >+".do_syscall_clone_ppc64_linux:\n" >+"#if _CALL_ELF == 2 \n" >+"0: addis 2,12,.TOC.-0b@ha \n" >+" addi 2,2,.TOC.-0b@l \n" >+"#endif \n" >+" .localentry do_syscall_clone_ppc64_linux, .-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 >+" rldicr 4,4, 0,59\n" // trim sp to multiple of 16 bytes >+ // (r4 &= ~0xF) >+" 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,13\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 >+" sldi 4,4,32\n" // CR now in hi half r4 >+ >+" sldi 3,3,32\n" >+" srdi 3,3,32\n" // zero out hi half r3 >+ >+" or 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" >+#endif > ); > > #undef __NR_CLONE >@@ -552,7 +676,7 @@ PRE(sys_clone) > } > if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) { > PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int)); >- if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), >+ if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), > VKI_PROT_WRITE)) { > SET_STATUS_Failure( VKI_EFAULT ); > return; >@@ -1074,7 +1198,7 @@ SyscallTableEntry* ML_(get_linux_syscall > return NULL; > } > >-#endif // defined(VGP_ppc64_linux) >+#endif // defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > /*--------------------------------------------------------------------*/ > /*--- end ---*/ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_trampoline.S >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_trampoline.S >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_trampoline.S >@@ -1,4 +1,3 @@ >- > /*--------------------------------------------------------------------*/ > /*--- Trampoline code page stuff. m_trampoline.S ---*/ > /*--------------------------------------------------------------------*/ >@@ -416,7 +415,7 @@ VG_(trampoline_stuff_end): > > /*---------------- ppc64-linux ----------------*/ > #else >-#if defined(VGP_ppc64_linux) >+#if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > > # define UD2_16 trap ; trap ; trap; trap > # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 >@@ -444,6 +443,10 @@ VG_(ppctoc_magic_redirect_return_stub): > /* this function is written using the "dotless" ABI convention */ > .align 2 > .globl VG_(ppc64_linux_REDIR_FOR_strlen) >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .type VG_(ppc64_linux_REDIR_FOR_strlen),@function >+VG_(ppc64_linux_REDIR_FOR_strlen): >+#else > .section ".opd","aw" > .align 3 > VG_(ppc64_linux_REDIR_FOR_strlen): >@@ -454,6 +457,12 @@ VG_(ppc64_linux_REDIR_FOR_strlen): > .type VG_(ppc64_linux_REDIR_FOR_strlen), @function > > .L.VG_(ppc64_linux_REDIR_FOR_strlen): >+#endif >+#if _CALL_ELF == 2 >+0: addis 2,12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen) >+#endif > mr 9,3 > lbz 0,0(3) > li 3,0 >@@ -467,14 +476,25 @@ VG_(ppc64_linux_REDIR_FOR_strlen): > cmpwi 7,0,0 > bne 7,.L01 > blr >- .long 0 >+ >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen) >+ #else >+ .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen) >+ #endif >+ >+ .long 0 > .byte 0,0,0,0,0,0,0,0 > .L0end: > > /* this function is written using the "dotless" ABI convention */ > .align 2 > .globl VG_(ppc64_linux_REDIR_FOR_strchr) >- .section ".opd","aw" >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .type VG_(ppc64_linux_REDIR_FOR_strchr),@function >+VG_(ppc64_linux_REDIR_FOR_strchr): >+#else >+ .section ".opd","aw" > .align 3 > VG_(ppc64_linux_REDIR_FOR_strchr): > .quad .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0 >@@ -482,8 +502,13 @@ VG_(ppc64_linux_REDIR_FOR_strchr): > .size VG_(ppc64_linux_REDIR_FOR_strchr), \ > .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr) > .type VG_(ppc64_linux_REDIR_FOR_strchr),@function >- > .L.VG_(ppc64_linux_REDIR_FOR_strchr): >+#endif >+#if _CALL_ELF == 2 >+0: addis 2,12,.TOC.-0b@ha >+ addi 2,2,.TOC.-0b@l >+ .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr) >+#endif > lbz 0,0(3) > rldicl 4,4,0,56 > cmpw 7,4,0 >@@ -491,6 +516,11 @@ VG_(ppc64_linux_REDIR_FOR_strchr): > cmpdi 7,0,0 > bne 7,.L18 > b .L14 >+#if !defined VGP_ppc64_linux || _CALL_ELF == 2 >+ .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr) >+#else >+ .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr) >+ #endif > .L19: > beq 6,.L14 > .L18: >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_translate.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_translate.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_translate.c >@@ -868,7 +868,7 @@ static Bool chase_into_ok ( void* closur > if (addr != VG_(redir_do_lookup)(addr, NULL)) > goto dontchase; > >-# if defined(VG_PLAT_USES_PPCTOC) >+# if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux) > /* This needs to be at the start of its own block. Don't chase. Re > ULong_to_Ptr, be careful to ensure we only compare 32 bits on a > 32-bit target.*/ >@@ -918,7 +918,7 @@ static IRExpr* mkU32 ( UInt n ) { > return IRExpr_Const(IRConst_U32(n)); > } > >-#if defined(VG_PLAT_USES_PPCTOC) >+#if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux) > static IRExpr* mkU8 ( UChar n ) { > return IRExpr_Const(IRConst_U8(n)); > } >@@ -941,7 +941,7 @@ static void gen_PUSH ( IRSB* bb, IRExpr* > IRTemp t1; > IRExpr* one; > >-# if defined(VGP_ppc64_linux) >+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE; > Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP); > Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK); >@@ -1035,7 +1035,7 @@ static void gen_PUSH ( IRSB* bb, IRExpr* > > static IRTemp gen_POP ( IRSB* bb ) > { >-# if defined(VGP_ppc64_linux) >+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE; > Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP); > Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK); >@@ -1118,6 +1118,10 @@ static IRTemp gen_POP ( IRSB* bb ) > return res; > } > >+#endif >+ >+#if defined(VG_PLAT_USES_PPCTOC) >+ > /* Generate code to push LR and R2 onto this thread's redir stack, > then set R2 to the new value (which is the TOC pointer to be used > for the duration of the replacement function, as determined by >@@ -1141,9 +1145,13 @@ static void gen_push_and_set_LR_R2 ( IRS > # endif > } > >+#endif >+ >+#if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux) >+ > static void gen_pop_R2_LR_then_bLR ( IRSB* bb ) > { >-# if defined(VGP_ppc64_linux) >+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2); > Int offB_LR = offsetof(VexGuestPPC64State,guest_LR); > Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA); >@@ -1167,6 +1175,10 @@ static void gen_pop_R2_LR_then_bLR ( IRS > # endif > } > >+#endif >+ >+#if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux) >+ > static > Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb ) > { >@@ -1187,6 +1199,30 @@ Bool mk_preamble__ppctoc_magic_return_st > } > #endif > >+# if defined(VGP_ppc64le_linux) >+/* Generate code to push LR and R2 onto this thread's redir stack. >+ Need to save R2 in case we redirect to a global entry point. The >+ value of R2 is not preserved when entering the global entry point. >+ Need to make sure R2 gets restored on return. Set LR to the magic >+ return stub, so we get to intercept the return and restore R2 and >+ L2 to the values saved here. >+ >+ The existing infrastruture for the TOC enabled architectures is >+ being exploited here. So, we need to enable a number of the >+ code sections used by VG_PLAT_USES_PPCTOC. >+ */ >+ >+static void gen_push_R2_and_set_LR ( IRSB* bb ) >+{ >+ Addr64 bogus_RA = (Addr64)&VG_(ppctoc_magic_redirect_return_stub); >+ Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2); >+ Int offB_LR = offsetof(VexGuestPPC64State,guest_LR); >+ gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) ); >+ gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) ); >+ addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) ); >+} >+# endif >+ > /* --------------- END helpers for with-TOC platforms --------------- */ > > >@@ -1232,7 +1268,7 @@ Bool mk_preamble__set_NRADDR_to_zero ( v > Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25); > addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr))); > # endif >-# if defined(VG_PLAT_USES_PPCTOC) >+# if defined(VGP_ppc64_linux) > { VgCallbackClosure* closure = (VgCallbackClosure*)closureV; > addStmtToIRSB( > bb, >@@ -1244,6 +1280,20 @@ Bool mk_preamble__set_NRADDR_to_zero ( v > gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) ); > } > # endif >+ >+#if defined(VGP_ppc64le_linux) >+ VgCallbackClosure* closure = (VgCallbackClosure*)closureV; >+ Int offB_GPR12 = offsetof(VexGuestArchState, guest_GPR12); >+ addStmtToIRSB(bb, IRStmt_Put(offB_GPR12, mkU64(closure->readdr))); >+ addStmtToIRSB( >+ bb, >+ IRStmt_Put( >+ offsetof(VexGuestArchState,guest_NRADDR_GPR2), >+ VG_WORDSIZE==8 ? mkU64(0) : mkU32(0) >+ ) >+ ); >+ gen_push_R2_and_set_LR ( bb ); >+#endif > return False; > } > >@@ -1277,7 +1327,7 @@ Bool mk_preamble__set_NRADDR_to_nraddr ( > Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25); > addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr))); > # endif >-# if defined(VGP_ppc64_linux) >+# if defined(VG_PLAT_USES_PPCTOC) && !defined(VGP_ppc64le_linux) > addStmtToIRSB( > bb, > IRStmt_Put( >@@ -1288,6 +1338,22 @@ Bool mk_preamble__set_NRADDR_to_nraddr ( > ); > gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) ); > # endif >+#if defined(VGP_ppc64le_linux) >+ /* This saves the r2 before leaving the function. We need to move >+ * guest_NRADDR_GPR2 back to R2 on return. >+ */ >+ Int offB_GPR12 = offsetof(VexGuestArchState, guest_GPR12); >+ addStmtToIRSB( >+ bb, >+ IRStmt_Put( >+ offsetof(VexGuestArchState,guest_NRADDR_GPR2), >+ IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2), >+ VG_WORDSIZE==8 ? Ity_I64 : Ity_I32) >+ ) >+ ); >+ addStmtToIRSB(bb, IRStmt_Put(offB_GPR12, mkU64(closure->readdr))); >+ gen_push_R2_and_set_LR ( bb ); >+#endif > return False; > } > >@@ -1475,7 +1541,8 @@ Bool VG_(translate) ( ThreadId tid, > if (kind == T_Redir_Wrap) > preamble_fn = mk_preamble__set_NRADDR_to_nraddr; > >-# if defined(VG_PLAT_USES_PPCTOC) >+ /* LE we setup the LR */ >+# if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux) > if (ULong_to_Ptr(nraddr) > == (void*)&VG_(ppctoc_magic_redirect_return_stub)) { > /* If entering the special return stub, this means a wrapped or >@@ -1518,6 +1585,11 @@ Bool VG_(translate) ( ThreadId tid, > vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True; > vex_abiinfo.host_ppc_calls_use_fndescrs = True; > # endif >+# if defined(VGP_ppc64le_linux) >+ vex_abiinfo.guest_ppc_zap_RZ_at_blr = True; >+ vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True; >+ vex_abiinfo.host_ppc_calls_use_fndescrs = False; >+# endif > > /* Set up closure args. */ > closure.tid = tid; >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_ume/elf.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_ume/elf.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_ume/elf.c >@@ -310,6 +310,14 @@ Int VG_(load_ELF)(Int fd, const HChar* n > void *entry; > ESZ(Addr) ebase = 0; > >+#if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) >+ /* The difference between where the interpreter got mapped and >+ where it asked to be mapped. Needed for computing the ppc64 ELF >+ entry point and initial tocptr (R2) value. >+ */ >+ ESZ(Word) interp_offset = 0; >+#endif >+ > # if defined(HAVE_PIE) > ebase = info->exe_base; > # endif >@@ -495,7 +503,10 @@ Int VG_(load_ELF)(Int fd, const HChar* n > VG_(close)(interp->fd); > > entry = (void *)(advised - interp_addr + interp->e.e_entry); >+ >+#if defined(VGP_ppc64_linux) || defined(VGP_ppc64le_linux) > info->interp_offset = advised - interp_addr; >+#endif > > VG_(free)(interp->p); > VG_(free)(interp); >@@ -514,6 +525,11 @@ Int VG_(load_ELF)(Int fd, const HChar* n > info->init_toc = ((ULong*)entry)[1]; > info->init_ip += info->interp_offset; > info->init_toc += info->interp_offset; >+#elif defined(VGP_ppc64le_linux) >+ /* On PPC64 LE the API doesn't use a func ptr */ >+ info->init_ip = (Addr)entry; >+ info->init_toc = 0; /* meaningless on this platform */ >+ (void) interp_offset; /* stop gcc complaining it is unused */ > #else > info->init_ip = (Addr)entry; > info->init_toc = 0; /* meaningless on this platform */ >Index: valgrind-3.9.0-svn20140513r13961/coregrind/m_ume/macho.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/m_ume/macho.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/m_ume/macho.c >@@ -701,6 +701,8 @@ load_fat_file(int fd, vki_off_t offset, > good_arch = CPU_TYPE_POWERPC; > #elif defined(VGA_ppc64) > good_arch = CPU_TYPE_POWERPC64; >+#elif defined(VGA_ppc64le) >+ good_arch = CPU_TYPE_POWERPC64LE; > #elif defined(VGA_x86) > good_arch = CPU_TYPE_I386; > #elif defined(VGA_amd64) >Index: valgrind-3.9.0-svn20140513r13961/coregrind/pub_core_machine.h >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/pub_core_machine.h >+++ valgrind-3.9.0-svn20140513r13961/coregrind/pub_core_machine.h >@@ -61,6 +61,11 @@ > # define VG_ELF_MACHINE EM_PPC64 > # define VG_ELF_CLASS ELFCLASS64 > # define VG_PLAT_USES_PPCTOC 1 >+#elif defined(VGP_ppc64le_linux) >+# define VG_ELF_DATA2XXX ELFDATA2LSB >+# define VG_ELF_MACHINE EM_PPC64 >+# define VG_ELF_CLASS ELFCLASS64 >+# undef VG_PLAT_USES_PPCTOC > #elif defined(VGP_arm_linux) > # define VG_ELF_DATA2XXX ELFDATA2LSB > # define VG_ELF_MACHINE EM_ARM >@@ -119,7 +124,7 @@ > # 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) >+#elif defined(VGA_ppc64) || defined(VGA_ppc64le) > # define VG_INSTR_PTR guest_CIA > # define VG_STACK_PTR guest_GPR1 > # define VG_FRAME_PTR guest_GPR1 // No frame ptr for PPC >@@ -233,7 +238,7 @@ extern Bool VG_(machine_get_cache_info)( > extern void VG_(machine_ppc32_set_clszB)( Int ); > #endif > >-#if defined(VGA_ppc64) >+#if defined(VGA_ppc64) || defined(VGA_ppc64le) > extern void VG_(machine_ppc64_set_clszB)( Int ); > #endif > >@@ -265,7 +270,7 @@ extern UInt VG_(machine_ppc32_has_VMX); > /* 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) >+#if defined(VGA_ppc64) || defined(VGA_ppc64le) > extern ULong VG_(machine_ppc64_has_VMX); > #endif > >Index: valgrind-3.9.0-svn20140513r13961/coregrind/vgdb-invoker-ptrace.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/coregrind/vgdb-invoker-ptrace.c >+++ valgrind-3.9.0-svn20140513r13961/coregrind/vgdb-invoker-ptrace.c >@@ -738,7 +738,7 @@ Bool invoker_invoke_gdbserver (pid_t pid > sp = user_mod.regs.uregs[13]; > #elif defined(VGA_ppc32) > sp = user_mod.regs.gpr[1]; >-#elif defined(VGA_ppc64) >+#elif defined(VGA_ppc64) || defined(VGA_ppc64le) > sp = user_mod.regs.gpr[1]; > #elif defined(VGA_s390x) > sp = user_mod.regs.gprs[15]; >@@ -802,7 +802,7 @@ Bool invoker_invoke_gdbserver (pid_t pid > I_die_here : not x86 or amd64 in x86/amd64 section/ > #endif > >-#elif defined(VGA_ppc32) || defined(VGA_ppc64) >+#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_ppc64le) > user_mod.regs.nip = shared32->invoke_gdbserver; > user_mod.regs.trap = -1L; > /* put check arg in register 3 */ >@@ -898,6 +898,16 @@ Bool invoker_invoke_gdbserver (pid_t pid > user_mod.regs.trap = -1L; > /* put check arg in register 3 */ > user_mod.regs.gpr[3] = check; >+ /* put bad_return return address in Link Register */ >+ user_mod.regs.link = bad_return; >+#elif defined(VGA_ppc64le) >+ /* LE does not use the function pointer structure used in BE */ >+ user_mod.regs.nip = shared64->invoke_gdbserver; >+ user_mod.regs.gpr[1] = sp - 512; >+ user_mod.regs.gpr[12] = user_mod.regs.nip; >+ user_mod.regs.trap = -1L; >+ /* put check arg in register 3 */ >+ user_mod.regs.gpr[3] = check; > /* put bad_return return address in Link Register */ > user_mod.regs.link = bad_return; > #elif defined(VGA_s390x) >Index: valgrind-3.9.0-svn20140513r13961/helgrind/hg_main.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/helgrind/hg_main.c >+++ valgrind-3.9.0-svn20140513r13961/helgrind/hg_main.c >@@ -4465,6 +4465,7 @@ static Bool is_in_dynamic_linker_shared_ > if (VG_STREQ(soname, VG_U_LD_LINUX_SO_2)) return True; > if (VG_STREQ(soname, VG_U_LD_LINUX_X86_64_SO_2)) return True; > if (VG_STREQ(soname, VG_U_LD64_SO_1)) return True; >+ if (VG_STREQ(soname, VG_U_LD64_SO_2)) return True; > if (VG_STREQ(soname, VG_U_LD_SO_1)) return True; > # elif defined(VGO_darwin) > if (VG_STREQ(soname, VG_U_DYLD)) return True; >Index: valgrind-3.9.0-svn20140513r13961/include/pub_tool_basics.h >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/include/pub_tool_basics.h >+++ valgrind-3.9.0-svn20140513r13961/include/pub_tool_basics.h >@@ -270,7 +270,7 @@ static inline Bool sr_EQ ( SysRes sr1, S > > #if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \ > || ((defined(VGA_mips32) || defined(VGA_mips64)) && defined (_MIPSEL)) \ >- || defined(VGA_arm64) || defined(VGA_ppc32le) >+ || defined(VGA_arm64) || defined(VGA_ppc64le) > # define VG_LITTLEENDIAN 1 > #elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \ > || ((defined(VGA_mips32) || defined(VGA_mips64)) && defined (_MIPSEB)) >Index: valgrind-3.9.0-svn20140513r13961/include/pub_tool_debuginfo.h >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/include/pub_tool_debuginfo.h >+++ valgrind-3.9.0-svn20140513r13961/include/pub_tool_debuginfo.h >@@ -219,6 +219,7 @@ void VG_(DebugInfo_syms_getidx) ( const > Int idx, > /*OUT*/Addr* avma, > /*OUT*/Addr* tocptr, >+ /*OUT*/Addr* second_ep, > /*OUT*/UInt* size, > /*OUT*/HChar** pri_name, > /*OUT*/HChar*** sec_names, >Index: valgrind-3.9.0-svn20140513r13961/include/pub_tool_redir.h >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/include/pub_tool_redir.h >+++ valgrind-3.9.0-svn20140513r13961/include/pub_tool_redir.h >@@ -284,6 +284,7 @@ > > #define VG_Z_LD64_SO_1 ld64ZdsoZd1 // ld64.so.1 > #define VG_U_LD64_SO_1 "ld64.so.1" >+#define VG_U_LD64_SO_2 "ld64.so.2" // PPC LE loader > > #define VG_Z_LD_SO_1 ldZdsoZd1 // ld.so.1 > #define VG_U_LD_SO_1 "ld.so.1" >Index: valgrind-3.9.0-svn20140513r13961/include/valgrind.h >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/include/valgrind.h >+++ valgrind-3.9.0-svn20140513r13961/include/valgrind.h >@@ -116,6 +116,7 @@ > #undef PLAT_amd64_linux > #undef PLAT_ppc32_linux > #undef PLAT_ppc64_linux >+#undef PLAT_ppc64le_linux > #undef PLAT_arm_linux > #undef PLAT_arm64_linux > #undef PLAT_s390x_linux >@@ -138,8 +139,10 @@ > # define PLAT_amd64_linux 1 > #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) > # define PLAT_ppc32_linux 1 >-#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) >+#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2 > # define PLAT_ppc64_linux 1 >+#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2 >+# define PLAT_ppc64le_linux 1 > #elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__) > # define PLAT_arm_linux 1 > #elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__) >@@ -587,6 +590,83 @@ typedef > > #endif /* PLAT_ppc64_linux */ > >+#if defined(PLAT_ppc64le_linux) >+ >+typedef >+ struct { >+ unsigned long long int nraddr; /* where's the code? */ >+ unsigned long long int r2; /* what tocptr do we need? */ >+ } >+ OrigFn; >+ >+#define __SPECIAL_INSTRUCTION_PREAMBLE \ >+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ >+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t" >+ >+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ >+ _zzq_default, _zzq_request, \ >+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ >+ \ >+ __extension__ \ >+ ({ unsigned long long int _zzq_args[6]; \ >+ unsigned long long int _zzq_result; \ >+ unsigned long long int* _zzq_ptr; \ >+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \ >+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ >+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ >+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ >+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ >+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ >+ _zzq_ptr = _zzq_args; \ >+ __asm__ volatile("mr 3,%1\n\t" /*default*/ \ >+ "mr 4,%2\n\t" /*ptr*/ \ >+ __SPECIAL_INSTRUCTION_PREAMBLE \ >+ /* %R3 = client_request ( %R4 ) */ \ >+ "or 1,1,1\n\t" \ >+ "mr %0,3" /*result*/ \ >+ : "=b" (_zzq_result) \ >+ : "b" (_zzq_default), "b" (_zzq_ptr) \ >+ : "cc", "memory", "r3", "r4"); \ >+ _zzq_result; \ >+ }) >+ >+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ >+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ >+ unsigned long long int __addr; \ >+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ >+ /* %R3 = guest_NRADDR */ \ >+ "or 2,2,2\n\t" \ >+ "mr %0,3" \ >+ : "=b" (__addr) \ >+ : \ >+ : "cc", "memory", "r3" \ >+ ); \ >+ _zzq_orig->nraddr = __addr; \ >+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ >+ /* %R3 = guest_NRADDR_GPR2 */ \ >+ "or 4,4,4\n\t" \ >+ "mr %0,3" \ >+ : "=b" (__addr) \ >+ : \ >+ : "cc", "memory", "r3" \ >+ ); \ >+ _zzq_orig->r2 = __addr; \ >+ } >+ >+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ __SPECIAL_INSTRUCTION_PREAMBLE \ >+ /* branch-and-link-to-noredir *%R12 */ \ >+ "or 3,3,3\n\t" >+ >+#define VALGRIND_VEX_INJECT_IR() \ >+ do { \ >+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ >+ "or 5,5,5\n\t" \ >+ ); \ >+ } while (0) >+ >+#endif /* PLAT_ppc64le_linux */ >+ > /* ------------------------- arm-linux ------------------------- */ > > #if defined(PLAT_arm_linux) >@@ -3080,6 +3160,563 @@ typedef > > #endif /* PLAT_ppc64_linux */ > >+ >+/* ------------------------- ppc64le-linux ----------------------- */ >+#if defined(PLAT_ppc64le_linux) >+ >+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ >+ >+/* These regs are trashed by the hidden call. */ >+#define __CALLER_SAVED_REGS \ >+ "lr", "ctr", "xer", \ >+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ >+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ >+ "r11", "r12", "r13" >+ >+/* Macros to save and align the stack before making a function >+ call and restore it afterwards as gcc may not keep the stack >+ pointer aligned if it doesn't realise calls are being made >+ to other functions. */ >+ >+#define VALGRIND_ALIGN_STACK \ >+ "mr 28,1\n\t" \ >+ "rldicr 1,1,0,59\n\t" >+#define VALGRIND_RESTORE_STACK \ >+ "mr 1,28\n\t" >+ >+/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned >+ long) == 8. */ >+ >+#define CALL_FN_W_v(lval, orig) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+0]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_W(lval, orig, arg1) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+1]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+2]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+3]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+4]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+5]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+6]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ _argvec[2+6] = (unsigned long)arg6; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ >+ arg7) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+7]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ _argvec[2+6] = (unsigned long)arg6; \ >+ _argvec[2+7] = (unsigned long)arg7; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \ >+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ >+ arg7,arg8) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+8]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ _argvec[2+6] = (unsigned long)arg6; \ >+ _argvec[2+7] = (unsigned long)arg7; \ >+ _argvec[2+8] = (unsigned long)arg8; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \ >+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \ >+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ >+ arg7,arg8,arg9) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+9]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ _argvec[2+6] = (unsigned long)arg6; \ >+ _argvec[2+7] = (unsigned long)arg7; \ >+ _argvec[2+8] = (unsigned long)arg8; \ >+ _argvec[2+9] = (unsigned long)arg9; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "addi 1,1,-128\n\t" /* expand stack frame */ \ >+ /* arg9 */ \ >+ "ld 3,72(12)\n\t" \ >+ "std 3,96(1)\n\t" \ >+ /* args1-8 */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \ >+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \ >+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ >+ arg7,arg8,arg9,arg10) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+10]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ _argvec[2+6] = (unsigned long)arg6; \ >+ _argvec[2+7] = (unsigned long)arg7; \ >+ _argvec[2+8] = (unsigned long)arg8; \ >+ _argvec[2+9] = (unsigned long)arg9; \ >+ _argvec[2+10] = (unsigned long)arg10; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "addi 1,1,-128\n\t" /* expand stack frame */ \ >+ /* arg10 */ \ >+ "ld 3,80(12)\n\t" \ >+ "std 3,104(1)\n\t" \ >+ /* arg9 */ \ >+ "ld 3,72(12)\n\t" \ >+ "std 3,96(1)\n\t" \ >+ /* args1-8 */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \ >+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \ >+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ >+ arg7,arg8,arg9,arg10,arg11) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+11]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ _argvec[2+6] = (unsigned long)arg6; \ >+ _argvec[2+7] = (unsigned long)arg7; \ >+ _argvec[2+8] = (unsigned long)arg8; \ >+ _argvec[2+9] = (unsigned long)arg9; \ >+ _argvec[2+10] = (unsigned long)arg10; \ >+ _argvec[2+11] = (unsigned long)arg11; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "addi 1,1,-144\n\t" /* expand stack frame */ \ >+ /* arg11 */ \ >+ "ld 3,88(12)\n\t" \ >+ "std 3,112(1)\n\t" \ >+ /* arg10 */ \ >+ "ld 3,80(12)\n\t" \ >+ "std 3,104(1)\n\t" \ >+ /* arg9 */ \ >+ "ld 3,72(12)\n\t" \ >+ "std 3,96(1)\n\t" \ >+ /* args1-8 */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \ >+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \ >+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ >+ arg7,arg8,arg9,arg10,arg11,arg12) \ >+ do { \ >+ volatile OrigFn _orig = (orig); \ >+ volatile unsigned long _argvec[3+12]; \ >+ volatile unsigned long _res; \ >+ /* _argvec[0] holds current r2 across the call */ \ >+ _argvec[1] = (unsigned long)_orig.r2; \ >+ _argvec[2] = (unsigned long)_orig.nraddr; \ >+ _argvec[2+1] = (unsigned long)arg1; \ >+ _argvec[2+2] = (unsigned long)arg2; \ >+ _argvec[2+3] = (unsigned long)arg3; \ >+ _argvec[2+4] = (unsigned long)arg4; \ >+ _argvec[2+5] = (unsigned long)arg5; \ >+ _argvec[2+6] = (unsigned long)arg6; \ >+ _argvec[2+7] = (unsigned long)arg7; \ >+ _argvec[2+8] = (unsigned long)arg8; \ >+ _argvec[2+9] = (unsigned long)arg9; \ >+ _argvec[2+10] = (unsigned long)arg10; \ >+ _argvec[2+11] = (unsigned long)arg11; \ >+ _argvec[2+12] = (unsigned long)arg12; \ >+ __asm__ volatile( \ >+ VALGRIND_ALIGN_STACK \ >+ "mr 12,%1\n\t" \ >+ "std 2,-16(12)\n\t" /* save tocptr */ \ >+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \ >+ "addi 1,1,-144\n\t" /* expand stack frame */ \ >+ /* arg12 */ \ >+ "ld 3,96(12)\n\t" \ >+ "std 3,120(1)\n\t" \ >+ /* arg11 */ \ >+ "ld 3,88(12)\n\t" \ >+ "std 3,112(1)\n\t" \ >+ /* arg10 */ \ >+ "ld 3,80(12)\n\t" \ >+ "std 3,104(1)\n\t" \ >+ /* arg9 */ \ >+ "ld 3,72(12)\n\t" \ >+ "std 3,96(1)\n\t" \ >+ /* args1-8 */ \ >+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \ >+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \ >+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \ >+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \ >+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \ >+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \ >+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \ >+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \ >+ "ld 12, 0(12)\n\t" /* target->r12 */ \ >+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \ >+ "mr 12,%1\n\t" \ >+ "mr %0,3\n\t" \ >+ "ld 2,-16(12)\n\t" /* restore tocptr */ \ >+ VALGRIND_RESTORE_STACK \ >+ : /*out*/ "=r" (_res) \ >+ : /*in*/ "r" (&_argvec[2]) \ >+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ >+ ); \ >+ lval = (__typeof__(lval)) _res; \ >+ } while (0) >+ >+#endif /* PLAT_ppc64le_linux */ >+ > /* ------------------------- arm-linux ------------------------- */ > > #if defined(PLAT_arm_linux) >Index: valgrind-3.9.0-svn20140513r13961/include/vki/vki-ppc64-linux.h >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/include/vki/vki-ppc64-linux.h >+++ valgrind-3.9.0-svn20140513r13961/include/vki/vki-ppc64-linux.h >@@ -32,8 +32,11 @@ > #define __VKI_PPC64_LINUX_H > > // ppc64 is big-endian. >+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) > #define VKI_BIG_ENDIAN 1 >- >+#elif defined(VGP_ppc64le_linux) >+#define VKI_LITTLE_ENDIAN 1 >+#endif > //---------------------------------------------------------------------- > // From linux-2.6.13/include/asm-ppc64/types.h > //---------------------------------------------------------------------- >Index: valgrind-3.9.0-svn20140513r13961/memcheck/mc_machine.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/memcheck/mc_machine.c >+++ valgrind-3.9.0-svn20140513r13961/memcheck/mc_machine.c >@@ -173,7 +173,11 @@ static Int get_otrack_shadow_offset_wrk > return GOF(GPRn); > by testing ox instead of o, and setting ox back 4 bytes when sz == 4. > */ >+#if defined(VGA_ppc64le) >+ Int ox = o; >+#else > Int ox = sz == 8 ? o : (o - 4); >+#endif > if (ox == GOF(GPR0)) return ox; > if (ox == GOF(GPR1)) return ox; > if (ox == GOF(GPR2)) return ox; >Index: valgrind-3.9.0-svn20140513r13961/tests/arch_test.c >=================================================================== >--- valgrind-3.9.0-svn20140513r13961.orig/tests/arch_test.c >+++ valgrind-3.9.0-svn20140513r13961/tests/arch_test.c >@@ -27,6 +27,7 @@ char* all_archs[] = { > "amd64", > "ppc32", > "ppc64", >+ "ppc64le", > "arm", > "s390x", > "mips32", >@@ -54,6 +55,9 @@ static Bool go(char* arch) > if ( 0 == strcmp( arch, "ppc32" ) ) return True; > #endif > >+#elif defined(VGP_ppc64le_linux) >+ if ( 0 == strcmp( arch, "ppc64" ) ) return True; >+ > #elif defined(VGP_s390x_linux) > if ( 0 == strcmp( arch, "s390x" ) ) return True; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1105030
:
902458
|
902459
| 902460 |
902461
|
902565