valgrind.h revision c8259b85b701d25d72aabe9dc0a8154517f96913
181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* -*- c -*-
281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   ----------------------------------------------------------------
381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   Notice that the following BSD-style license applies to this one
581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   file (valgrind.h) only.  The rest of Valgrind is licensed under the
681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   terms of the GNU General Public License, version 2, unless
781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   otherwise indicated.  See the COPYING file in the source
881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   distribution for details.
981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
1081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   ----------------------------------------------------------------
1181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
1281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   This file is part of Valgrind, a dynamic binary instrumentation
1381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   framework.
1481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
1581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   Copyright (C) 2000-2009 Julian Seward.  All rights reserved.
1681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
1781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   Redistribution and use in source and binary forms, with or without
1881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   modification, are permitted provided that the following conditions
1981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   are met:
2081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
2181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   1. Redistributions of source code must retain the above copyright
2281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      notice, this list of conditions and the following disclaimer.
2381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
2481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   2. The origin of this software must not be misrepresented; you must
2581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      not claim that you wrote the original software.  If you use this
2681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      software in a product, an acknowledgment in the product
2781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      documentation would be appreciated but is not required.
2881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
2981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   3. Altered source versions must be plainly marked as such, and must
3081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      not be misrepresented as being the original software.
3181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
3281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   4. The name of the author may not be used to endorse or promote
3381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      products derived from this software without specific prior written
3481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      permission.
3581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
3681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
3781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
4081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
4381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
4481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
4881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   ----------------------------------------------------------------
4981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
5081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   Notice that the above BSD-style license applies to this one file
5181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   (valgrind.h) only.  The entire rest of Valgrind is licensed under
5281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   the terms of the GNU General Public License, version 2.  See the
5381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   COPYING file in the source distribution for details.
5481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
5581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   ----------------------------------------------------------------
5681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray*/
5781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
5881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
5981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* This file is for inclusion into client (your!) code.
6081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
6181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   You can use these macros to manipulate and query Valgrind's
6281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   execution inside your own programs.
6381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
6481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   The resulting executables will still run without Valgrind, just a
6581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   little bit more slowly than they otherwise would, but otherwise
6681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   unchanged.  When not running on valgrind, each client request
6781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   consumes very few (eg. 7) instructions, so the resulting performance
6881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   loss is negligible unless you plan to execute client requests
6981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   millions of times per second.  Nevertheless, if that is still a
7081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   problem, you can compile with the NVALGRIND symbol defined (gcc
7181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   -DNVALGRIND) so that client requests are not even compiled in.  */
7281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
7381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#ifndef __VALGRIND_H
7481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __VALGRIND_H
7581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
7681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#include <stdarg.h>
7781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
7881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Nb: this file might be included in a file compiled with -ansi.  So
7981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   we can't use C++ style "//" comments nor the "asm" keyword (instead
8081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   use "__asm__"). */
8181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
8281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Derive some tags indicating what the target platform is.  Note
8381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   that in this file we're using the compiler's CPP symbols for
8481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   identifying architectures, which are different to the ones we use
8581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   within the rest of Valgrind.  Note, __powerpc__ is active for both
8681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   32 and 64-bit PPC, whereas __powerpc64__ is only active for the
8781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   latter (on Linux, that is). */
8881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_x86_linux
8981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_amd64_linux
9081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc32_linux
9181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc64_linux
9281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc32_aix5
9381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc64_aix5
9481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
9581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if !defined(_AIX) && defined(__i386__)
9681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  define PLAT_x86_linux 1
9781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif !defined(_AIX) && defined(__x86_64__)
9881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  define PLAT_amd64_linux 1
9981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
10081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  define PLAT_ppc32_linux 1
10181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
10281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  define PLAT_ppc64_linux 1
10381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif defined(_AIX) && defined(__64BIT__)
10481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  define PLAT_ppc64_aix5 1
10581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif defined(_AIX) && !defined(__64BIT__)
10681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  define PLAT_ppc32_aix5 1
10781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif
10881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
10981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
11081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* If we're not compiling for our target platform, don't generate
11181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   any inline asms.  */
11281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
11381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
11481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
11581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  if !defined(NVALGRIND)
11681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#    define NVALGRIND 1
11781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#  endif
11881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif
11981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
12081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
12181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */
12281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS.  There is nothing */
12381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* in here of use to end-users -- skip to the next section.           */
12481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */
12581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
12681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(NVALGRIND)
12781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
12881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Define NVALGRIND to completely remove the Valgrind magic sequence
12981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   from the compiled code (analogous to NDEBUG's effects on
13081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   assert()) */
13181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST(                               \
13281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_rlval, _zzq_default, _zzq_request,                   \
13381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
13481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   {                                                              \
13581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      (_zzq_rlval) = (_zzq_default);                              \
13681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   }
13781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
13881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#else  /* ! NVALGRIND */
13981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
14081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* The following defines the magic code sequences which the JITter
14181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   spots and handles magically.  Don't look too closely at them as
14281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   they will rot your brain.
14381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
14481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   The assembly code sequences for all architectures is in this one
14581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   file.  This is because this file must be stand-alone, and we don't
14681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   want to have multiple files.
14781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
14881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
14981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   value gets put in the return slot, so that everything works when
15081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   this is executed not under Valgrind.  Args are passed in a memory
15181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   block, and so there's no intrinsic limit to the number that could
15281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   be passed, but it's currently five.
15381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
15481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   The macro args are:
15581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _zzq_rlval    result lvalue
15681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _zzq_default  default value (result returned when running on real CPU)
15781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _zzq_request  request code
15881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _zzq_arg1..5  request params
15981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
16081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   The other two macros are used to support function wrapping, and are
16181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   a lot simpler.  VALGRIND_GET_NR_CONTEXT returns the value of the
16281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   guest's NRADDR pseudo-register and whatever other information is
16381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   needed to safely run the call original from the wrapper: on
16481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   ppc64-linux, the R2 value at the divert point is also needed.  This
16581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   information is abstracted into a user-visible type, OrigFn.
16681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
16781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
16881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   guest, but guarantees that the branch instruction will not be
16981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
17081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   branch-and-link-to-r11.  VALGRIND_CALL_NOREDIR is just text, not a
17181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   complete inline asm, since it needs to be combined with more magic
17281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   inline asm stuff to be useful.
17381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray*/
17481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
17581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------- x86-linux ------------------------- */
17681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
17781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_x86_linux)
17881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
17981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef
18081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   struct {
18181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned int nraddr; /* where's the code? */
18281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   }
18381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   OrigFn;
18481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
18581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
18681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "roll $3,  %%edi ; roll $13, %%edi\n\t"      \
18781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "roll $29, %%edi ; roll $19, %%edi\n\t"
18881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
18981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST(                               \
19081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_rlval, _zzq_default, _zzq_request,                   \
19181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
19281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile unsigned int _zzq_args[6];                           \
19381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    volatile unsigned int _zzq_result;                            \
19481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
19581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
19681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
19781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
19881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
19981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
20081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
20181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %EDX = client_request ( %EAX ) */         \
20281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "xchgl %%ebx,%%ebx"                          \
20381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=d" (_zzq_result)                         \
20481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
20581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory"                             \
20681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
20781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_rlval = _zzq_result;                                     \
20881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
20981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
21081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
21181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
21281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    volatile unsigned int __addr;                                 \
21381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
21481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %EAX = guest_NRADDR */                    \
21581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "xchgl %%ecx,%%ecx"                          \
21681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=a" (__addr)                              \
21781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
21881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory"                             \
21981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
22081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->nraddr = __addr;                                   \
22181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
22281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
22381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_CALL_NOREDIR_EAX                                 \
22481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
22581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* call-noredir *%EAX */                     \
22681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "xchgl %%edx,%%edx\n\t"
22781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_x86_linux */
22881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
22981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ amd64-linux ------------------------ */
23081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
23181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_amd64_linux)
23281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
23381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef
23481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   struct {
23581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned long long int nraddr; /* where's the code? */
23681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   }
23781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   OrigFn;
23881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
23981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
24081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rolq $3,  %%rdi ; rolq $13, %%rdi\n\t"      \
24181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
24281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
24381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST(                               \
24481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_rlval, _zzq_default, _zzq_request,                   \
24581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
24681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile unsigned long long int _zzq_args[6];                 \
24781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    volatile unsigned long long int _zzq_result;                  \
24881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[0] = (unsigned long long int)(_zzq_request);        \
24981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[1] = (unsigned long long int)(_zzq_arg1);           \
25081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[2] = (unsigned long long int)(_zzq_arg2);           \
25181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[3] = (unsigned long long int)(_zzq_arg3);           \
25281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[4] = (unsigned long long int)(_zzq_arg4);           \
25381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[5] = (unsigned long long int)(_zzq_arg5);           \
25481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
25581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %RDX = client_request ( %RAX ) */         \
25681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "xchgq %%rbx,%%rbx"                          \
25781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=d" (_zzq_result)                         \
25881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
25981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory"                             \
26081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
26181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_rlval = _zzq_result;                                     \
26281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
26381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
26481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
26581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
26681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    volatile unsigned long long int __addr;                       \
26781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
26881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %RAX = guest_NRADDR */                    \
26981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "xchgq %%rcx,%%rcx"                          \
27081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=a" (__addr)                              \
27181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
27281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory"                             \
27381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
27481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->nraddr = __addr;                                   \
27581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
27681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
27781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_CALL_NOREDIR_RAX                                 \
27881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
27981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* call-noredir *%RAX */                     \
28081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "xchgq %%rdx,%%rdx\n\t"
28181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_amd64_linux */
28281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
28381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc32-linux ------------------------ */
28481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
28581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc32_linux)
28681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
28781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef
28881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   struct {
28981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned int nraddr; /* where's the code? */
29081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   }
29181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   OrigFn;
29281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
29381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
29481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rlwinm 0,0,3,0,0  ; rlwinm 0,0,13,0,0\n\t"  \
29581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
29681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
29781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST(                               \
29881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_rlval, _zzq_default, _zzq_request,                   \
29981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
30081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                                                                  \
30181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  {          unsigned int  _zzq_args[6];                          \
30281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray             unsigned int  _zzq_result;                           \
30381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray             unsigned int* _zzq_ptr;                              \
30481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
30581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
30681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
30781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
30881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
30981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
31081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_ptr = _zzq_args;                                         \
31181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
31281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr 4,%2\n\t" /*ptr*/                        \
31381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
31481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = client_request ( %R4 ) */           \
31581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 1,1,1\n\t"                               \
31681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"     /*result*/                     \
31781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (_zzq_result)                         \
31881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "b" (_zzq_default), "b" (_zzq_ptr)         \
31981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory", "r3", "r4");               \
32081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_rlval = _zzq_result;                                     \
32181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
32281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
32381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
32481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
32581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    unsigned int __addr;                                          \
32681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
32781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = guest_NRADDR */                     \
32881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 2,2,2\n\t"                               \
32981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"                                    \
33081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (__addr)                              \
33181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
33281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory", "r3"                       \
33381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
33481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->nraddr = __addr;                                   \
33581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
33681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
33781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
33881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
33981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* branch-and-link-to-noredir *%R11 */       \
34081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 3,3,3\n\t"
34181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc32_linux */
34281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
34381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc64-linux ------------------------ */
34481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
34581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc64_linux)
34681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
34781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef
34881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   struct {
34981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned long long int nraddr; /* where's the code? */
35081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned long long int r2;  /* what tocptr do we need? */
35181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   }
35281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   OrigFn;
35381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
35481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
35581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
35681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
35781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
35881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST(                               \
35981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_rlval, _zzq_default, _zzq_request,                   \
36081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
36181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                                                                  \
36281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  {          unsigned long long int  _zzq_args[6];                \
36381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned long long int  _zzq_result __asm__("r3");   \
36481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned long long int* _zzq_ptr __asm__("r4");      \
36581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[0] = (unsigned long long int)(_zzq_request);        \
36681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[1] = (unsigned long long int)(_zzq_arg1);           \
36781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[2] = (unsigned long long int)(_zzq_arg2);           \
36881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[3] = (unsigned long long int)(_zzq_arg3);           \
36981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[4] = (unsigned long long int)(_zzq_arg4);           \
37081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[5] = (unsigned long long int)(_zzq_arg5);           \
37181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_ptr = _zzq_args;                                         \
37281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
37381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = client_request ( %R4 ) */           \
37481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 1,1,1"                                   \
37581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=r" (_zzq_result)                         \
37681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "0" (_zzq_default), "r" (_zzq_ptr)         \
37781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory");                           \
37881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_rlval = _zzq_result;                                     \
37981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
38081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
38181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
38281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
38381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned long long int __addr __asm__("r3");         \
38481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
38581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = guest_NRADDR */                     \
38681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 2,2,2"                                   \
38781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=r" (__addr)                              \
38881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
38981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory"                             \
39081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
39181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->nraddr = __addr;                                   \
39281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
39381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = guest_NRADDR_GPR2 */                \
39481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 4,4,4"                                   \
39581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=r" (__addr)                              \
39681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
39781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "cc", "memory"                             \
39881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
39981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->r2 = __addr;                                       \
40081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
40181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
40281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
40381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
40481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* branch-and-link-to-noredir *%R11 */       \
40581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 3,3,3\n\t"
40681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
40781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc64_linux */
40881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
40981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc32-aix5 ------------------------- */
41081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
41181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc32_aix5)
41281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
41381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef
41481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   struct {
41581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned int nraddr; /* where's the code? */
41681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned int r2;  /* what tocptr do we need? */
41781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   }
41881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   OrigFn;
41981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
42081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
42181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rlwinm 0,0,3,0,0  ; rlwinm 0,0,13,0,0\n\t"  \
42281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
42381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
42481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST(                               \
42581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_rlval, _zzq_default, _zzq_request,                   \
42681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
42781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                                                                  \
42881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  {          unsigned int  _zzq_args[7];                          \
42981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned int  _zzq_result;                           \
43081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned int* _zzq_ptr;                              \
43181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
43281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
43381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
43481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
43581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
43681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
43781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[6] = (unsigned int)(_zzq_default);                  \
43881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_ptr = _zzq_args;                                         \
43981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile("mr 4,%1\n\t"                                \
44081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "lwz 3, 24(4)\n\t"                           \
44181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
44281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = client_request ( %R4 ) */           \
44381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 1,1,1\n\t"                               \
44481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"                                    \
44581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (_zzq_result)                         \
44681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "b" (_zzq_ptr)                             \
44781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "r3", "r4", "cc", "memory");               \
44881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_rlval = _zzq_result;                                     \
44981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
45081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
45181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
45281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
45381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned int __addr;                                 \
45481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
45581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = guest_NRADDR */                     \
45681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 2,2,2\n\t"                               \
45781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"                                    \
45881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (__addr)                              \
45981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
46081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "r3", "cc", "memory"                       \
46181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
46281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->nraddr = __addr;                                   \
46381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
46481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = guest_NRADDR_GPR2 */                \
46581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 4,4,4\n\t"                               \
46681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"                                    \
46781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (__addr)                              \
46881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
46981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "r3", "cc", "memory"                       \
47081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
47181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->r2 = __addr;                                       \
47281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
47381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
47481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
47581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
47681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* branch-and-link-to-noredir *%R11 */       \
47781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 3,3,3\n\t"
47881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
47981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc32_aix5 */
48081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
48181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc64-aix5 ------------------------- */
48281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
48381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc64_aix5)
48481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
48581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef
48681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   struct {
48781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned long long int nraddr; /* where's the code? */
48881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      unsigned long long int r2;  /* what tocptr do we need? */
48981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   }
49081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   OrigFn;
49181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
49281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
49381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
49481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
49581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
49681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST(                               \
49781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_rlval, _zzq_default, _zzq_request,                   \
49881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
49981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                                                                  \
50081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  {          unsigned long long int  _zzq_args[7];                \
50181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned long long int  _zzq_result;                 \
50281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned long long int* _zzq_ptr;                    \
50381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[0] = (unsigned int long long)(_zzq_request);        \
50481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[1] = (unsigned int long long)(_zzq_arg1);           \
50581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[2] = (unsigned int long long)(_zzq_arg2);           \
50681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[3] = (unsigned int long long)(_zzq_arg3);           \
50781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[4] = (unsigned int long long)(_zzq_arg4);           \
50881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[5] = (unsigned int long long)(_zzq_arg5);           \
50981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_args[6] = (unsigned int long long)(_zzq_default);        \
51081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_ptr = _zzq_args;                                         \
51181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile("mr 4,%1\n\t"                                \
51281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "ld 3, 48(4)\n\t"                            \
51381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
51481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = client_request ( %R4 ) */           \
51581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 1,1,1\n\t"                               \
51681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"                                    \
51781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (_zzq_result)                         \
51881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "b" (_zzq_ptr)                             \
51981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "r3", "r4", "cc", "memory");               \
52081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_rlval = _zzq_result;                                     \
52181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
52281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
52381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
52481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
52581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    register unsigned long long int __addr;                       \
52681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
52781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = guest_NRADDR */                     \
52881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 2,2,2\n\t"                               \
52981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"                                    \
53081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (__addr)                              \
53181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
53281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "r3", "cc", "memory"                       \
53381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
53481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->nraddr = __addr;                                   \
53581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
53681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* %R3 = guest_NRADDR_GPR2 */                \
53781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 4,4,4\n\t"                               \
53881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "mr %0,3"                                    \
53981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "=b" (__addr)                              \
54081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     :                                            \
54181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     : "r3", "cc", "memory"                       \
54281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                    );                                            \
54381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray    _zzq_orig->r2 = __addr;                                       \
54481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray  }
54581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
54681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
54781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     __SPECIAL_INSTRUCTION_PREAMBLE               \
54881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     /* branch-and-link-to-noredir *%R11 */       \
54981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                     "or 3,3,3\n\t"
55081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
55181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc64_aix5 */
55281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
55381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Insert assembly code for other platforms here... */
55481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
55581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* NVALGRIND */
55681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
55781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
55881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */
55981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* PLATFORM SPECIFICS for FUNCTION WRAPPING.  This is all very        */
56081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ugly.  It's the least-worst tradeoff I can think of.               */
56181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */
56281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
56381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* This section defines magic (a.k.a appalling-hack) macros for doing
56481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   guaranteed-no-redirection macros, so as to get from function
56581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   wrappers to the functions they are wrapping.  The whole point is to
56681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   construct standard call sequences, but to do the call itself with a
56781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   special no-redirect call pseudo-instruction that the JIT
56881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   understands and handles specially.  This section is long and
56981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   repetitious, and I can't see a way to make it shorter.
57081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
57181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   The naming scheme is as follows:
57281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
57381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
57481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
57581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   'W' stands for "word" and 'v' for "void".  Hence there are
57681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
57781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   and for each, the possibility of returning a word-typed result, or
57881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   no result.
57981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray*/
58081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
58181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Use these to write the name of your wrapper.  NOTE: duplicates
58281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
58381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
58481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname)                    \
58581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   _vgwZU_##soname##_##fnname
58681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
58781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname)                    \
58881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   _vgwZZ_##soname##_##fnname
58981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
59081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Use this macro from within a wrapper function to collect the
59181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   context (address and possibly other info) of the original function.
59281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   Once you have that you can then use it in one of the CALL_FN_
59381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   macros.  The type of the argument _lval is OrigFn. */
59481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_ORIG_FN(_lval)  VALGRIND_GET_NR_CONTEXT(_lval)
59581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
59681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Derivatives of the main macros below, for calling functions
59781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   returning void. */
59881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
59981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_v(fnptr)                                        \
60081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do { volatile unsigned long _junk;                             \
60181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        CALL_FN_W_v(_junk,fnptr); } while (0)
60281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
60381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_W(fnptr, arg1)                                  \
60481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do { volatile unsigned long _junk;                             \
60581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
60681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
60781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_WW(fnptr, arg1,arg2)                            \
60881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do { volatile unsigned long _junk;                             \
60981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
61081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
61181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3)                      \
61281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do { volatile unsigned long _junk;                             \
61381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray        CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
61481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
61581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------- x86-linux ------------------------- */
61681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
61781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_x86_linux)
61881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
61981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* These regs are trashed by the hidden call.  No need to mention eax
62081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   as gcc can already see that, plus causes gcc to bomb. */
62181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
62281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
62381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
62481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   long) == 4. */
62581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
62681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_v(lval, orig)                                   \
62781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
62881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
62981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[1];                          \
63081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
63181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
63281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
63381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
63481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         VALGRIND_CALL_NOREDIR_EAX                                \
63581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*out*/   "=a" (_res)                                  \
63681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*in*/    "a" (&_argvec[0])                            \
63781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
63881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      );                                                          \
63981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      lval = (__typeof__(lval)) _res;                             \
64081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   } while (0)
64181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
64281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_W(lval, orig, arg1)                             \
64381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
64481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
64581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[2];                          \
64681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
64781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
64881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[1] = (unsigned long)(arg1);                         \
64981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
65081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 4(%%eax)\n\t"                                     \
65181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
65281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         VALGRIND_CALL_NOREDIR_EAX                                \
65381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "addl $4, %%esp\n"                                       \
65481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*out*/   "=a" (_res)                                  \
65581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*in*/    "a" (&_argvec[0])                            \
65681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
65781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      );                                                          \
65881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      lval = (__typeof__(lval)) _res;                             \
65981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   } while (0)
66081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
66181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
66281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
66381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
66481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[3];                          \
66581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
66681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
66781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[1] = (unsigned long)(arg1);                         \
66881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[2] = (unsigned long)(arg2);                         \
66981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
67081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 8(%%eax)\n\t"                                     \
67181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 4(%%eax)\n\t"                                     \
67281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
67381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         VALGRIND_CALL_NOREDIR_EAX                                \
67481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "addl $8, %%esp\n"                                       \
67581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*out*/   "=a" (_res)                                  \
67681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*in*/    "a" (&_argvec[0])                            \
67781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
67881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      );                                                          \
67981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      lval = (__typeof__(lval)) _res;                             \
68081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   } while (0)
68181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
68281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
68381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
68481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
68581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[4];                          \
68681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
68781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
68881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[1] = (unsigned long)(arg1);                         \
68981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[2] = (unsigned long)(arg2);                         \
69081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[3] = (unsigned long)(arg3);                         \
69181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
69281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 12(%%eax)\n\t"                                    \
69381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 8(%%eax)\n\t"                                     \
69481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 4(%%eax)\n\t"                                     \
69581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
69681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         VALGRIND_CALL_NOREDIR_EAX                                \
69781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "addl $12, %%esp\n"                                      \
69881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*out*/   "=a" (_res)                                  \
69981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*in*/    "a" (&_argvec[0])                            \
70081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
70181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      );                                                          \
70281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      lval = (__typeof__(lval)) _res;                             \
70381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   } while (0)
70481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
70581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
70681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
70781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
70881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[5];                          \
70981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
71081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
71181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[1] = (unsigned long)(arg1);                         \
71281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[2] = (unsigned long)(arg2);                         \
71381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[3] = (unsigned long)(arg3);                         \
71481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[4] = (unsigned long)(arg4);                         \
71581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
71681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 16(%%eax)\n\t"                                    \
71781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 12(%%eax)\n\t"                                    \
71881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 8(%%eax)\n\t"                                     \
71981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 4(%%eax)\n\t"                                     \
72081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
72181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         VALGRIND_CALL_NOREDIR_EAX                                \
72281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "addl $16, %%esp\n"                                      \
72381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*out*/   "=a" (_res)                                  \
72481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*in*/    "a" (&_argvec[0])                            \
72581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
72681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      );                                                          \
72781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      lval = (__typeof__(lval)) _res;                             \
72881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   } while (0)
72981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
73081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
73181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
73281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
73381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[6];                          \
73481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
73581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
73681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[1] = (unsigned long)(arg1);                         \
73781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[2] = (unsigned long)(arg2);                         \
73881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[3] = (unsigned long)(arg3);                         \
73981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[4] = (unsigned long)(arg4);                         \
74081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[5] = (unsigned long)(arg5);                         \
74181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
74281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 20(%%eax)\n\t"                                    \
74381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 16(%%eax)\n\t"                                    \
74481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 12(%%eax)\n\t"                                    \
74581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 8(%%eax)\n\t"                                     \
74681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 4(%%eax)\n\t"                                     \
74781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
74881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         VALGRIND_CALL_NOREDIR_EAX                                \
74981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "addl $20, %%esp\n"                                      \
75081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*out*/   "=a" (_res)                                  \
75181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*in*/    "a" (&_argvec[0])                            \
75281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
75381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      );                                                          \
75481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      lval = (__typeof__(lval)) _res;                             \
75581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   } while (0)
75681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
75781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
75881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
75981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
76081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[7];                          \
76181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
76281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
76381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[1] = (unsigned long)(arg1);                         \
76481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[2] = (unsigned long)(arg2);                         \
76581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[3] = (unsigned long)(arg3);                         \
76681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[4] = (unsigned long)(arg4);                         \
76781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[5] = (unsigned long)(arg5);                         \
76881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[6] = (unsigned long)(arg6);                         \
76981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
77081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 24(%%eax)\n\t"                                    \
77181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 20(%%eax)\n\t"                                    \
77281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 16(%%eax)\n\t"                                    \
77381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 12(%%eax)\n\t"                                    \
77481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 8(%%eax)\n\t"                                     \
77581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 4(%%eax)\n\t"                                     \
77681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
77781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         VALGRIND_CALL_NOREDIR_EAX                                \
77881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "addl $24, %%esp\n"                                      \
77981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*out*/   "=a" (_res)                                  \
78081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*in*/    "a" (&_argvec[0])                            \
78181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
78281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      );                                                          \
78381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      lval = (__typeof__(lval)) _res;                             \
78481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   } while (0)
78581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray
78681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
78781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray                                 arg7)                            \
78881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray   do {                                                           \
78981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile OrigFn        _orig = (orig);                      \
79081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _argvec[8];                          \
79181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      volatile unsigned long _res;                                \
79281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[0] = (unsigned long)_orig.nraddr;                   \
79381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[1] = (unsigned long)(arg1);                         \
79481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[2] = (unsigned long)(arg2);                         \
79581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[3] = (unsigned long)(arg3);                         \
79681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[4] = (unsigned long)(arg4);                         \
79781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[5] = (unsigned long)(arg5);                         \
79881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[6] = (unsigned long)(arg6);                         \
79981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      _argvec[7] = (unsigned long)(arg7);                         \
80081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray      __asm__ volatile(                                           \
80181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 28(%%eax)\n\t"                                    \
80281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 24(%%eax)\n\t"                                    \
80381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 20(%%eax)\n\t"                                    \
80481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 16(%%eax)\n\t"                                    \
80581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 12(%%eax)\n\t"                                    \
80681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 8(%%eax)\n\t"                                     \
80781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray         "pushl 4(%%eax)\n\t"                                     \
808         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
809         VALGRIND_CALL_NOREDIR_EAX                                \
810         "addl $28, %%esp\n"                                      \
811         : /*out*/   "=a" (_res)                                  \
812         : /*in*/    "a" (&_argvec[0])                            \
813         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
814      );                                                          \
815      lval = (__typeof__(lval)) _res;                             \
816   } while (0)
817
818#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
819                                 arg7,arg8)                       \
820   do {                                                           \
821      volatile OrigFn        _orig = (orig);                      \
822      volatile unsigned long _argvec[9];                          \
823      volatile unsigned long _res;                                \
824      _argvec[0] = (unsigned long)_orig.nraddr;                   \
825      _argvec[1] = (unsigned long)(arg1);                         \
826      _argvec[2] = (unsigned long)(arg2);                         \
827      _argvec[3] = (unsigned long)(arg3);                         \
828      _argvec[4] = (unsigned long)(arg4);                         \
829      _argvec[5] = (unsigned long)(arg5);                         \
830      _argvec[6] = (unsigned long)(arg6);                         \
831      _argvec[7] = (unsigned long)(arg7);                         \
832      _argvec[8] = (unsigned long)(arg8);                         \
833      __asm__ volatile(                                           \
834         "pushl 32(%%eax)\n\t"                                    \
835         "pushl 28(%%eax)\n\t"                                    \
836         "pushl 24(%%eax)\n\t"                                    \
837         "pushl 20(%%eax)\n\t"                                    \
838         "pushl 16(%%eax)\n\t"                                    \
839         "pushl 12(%%eax)\n\t"                                    \
840         "pushl 8(%%eax)\n\t"                                     \
841         "pushl 4(%%eax)\n\t"                                     \
842         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
843         VALGRIND_CALL_NOREDIR_EAX                                \
844         "addl $32, %%esp\n"                                      \
845         : /*out*/   "=a" (_res)                                  \
846         : /*in*/    "a" (&_argvec[0])                            \
847         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
848      );                                                          \
849      lval = (__typeof__(lval)) _res;                             \
850   } while (0)
851
852#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
853                                 arg7,arg8,arg9)                  \
854   do {                                                           \
855      volatile OrigFn        _orig = (orig);                      \
856      volatile unsigned long _argvec[10];                         \
857      volatile unsigned long _res;                                \
858      _argvec[0] = (unsigned long)_orig.nraddr;                   \
859      _argvec[1] = (unsigned long)(arg1);                         \
860      _argvec[2] = (unsigned long)(arg2);                         \
861      _argvec[3] = (unsigned long)(arg3);                         \
862      _argvec[4] = (unsigned long)(arg4);                         \
863      _argvec[5] = (unsigned long)(arg5);                         \
864      _argvec[6] = (unsigned long)(arg6);                         \
865      _argvec[7] = (unsigned long)(arg7);                         \
866      _argvec[8] = (unsigned long)(arg8);                         \
867      _argvec[9] = (unsigned long)(arg9);                         \
868      __asm__ volatile(                                           \
869         "pushl 36(%%eax)\n\t"                                    \
870         "pushl 32(%%eax)\n\t"                                    \
871         "pushl 28(%%eax)\n\t"                                    \
872         "pushl 24(%%eax)\n\t"                                    \
873         "pushl 20(%%eax)\n\t"                                    \
874         "pushl 16(%%eax)\n\t"                                    \
875         "pushl 12(%%eax)\n\t"                                    \
876         "pushl 8(%%eax)\n\t"                                     \
877         "pushl 4(%%eax)\n\t"                                     \
878         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
879         VALGRIND_CALL_NOREDIR_EAX                                \
880         "addl $36, %%esp\n"                                      \
881         : /*out*/   "=a" (_res)                                  \
882         : /*in*/    "a" (&_argvec[0])                            \
883         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
884      );                                                          \
885      lval = (__typeof__(lval)) _res;                             \
886   } while (0)
887
888#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
889                                  arg7,arg8,arg9,arg10)           \
890   do {                                                           \
891      volatile OrigFn        _orig = (orig);                      \
892      volatile unsigned long _argvec[11];                         \
893      volatile unsigned long _res;                                \
894      _argvec[0] = (unsigned long)_orig.nraddr;                   \
895      _argvec[1] = (unsigned long)(arg1);                         \
896      _argvec[2] = (unsigned long)(arg2);                         \
897      _argvec[3] = (unsigned long)(arg3);                         \
898      _argvec[4] = (unsigned long)(arg4);                         \
899      _argvec[5] = (unsigned long)(arg5);                         \
900      _argvec[6] = (unsigned long)(arg6);                         \
901      _argvec[7] = (unsigned long)(arg7);                         \
902      _argvec[8] = (unsigned long)(arg8);                         \
903      _argvec[9] = (unsigned long)(arg9);                         \
904      _argvec[10] = (unsigned long)(arg10);                       \
905      __asm__ volatile(                                           \
906         "pushl 40(%%eax)\n\t"                                    \
907         "pushl 36(%%eax)\n\t"                                    \
908         "pushl 32(%%eax)\n\t"                                    \
909         "pushl 28(%%eax)\n\t"                                    \
910         "pushl 24(%%eax)\n\t"                                    \
911         "pushl 20(%%eax)\n\t"                                    \
912         "pushl 16(%%eax)\n\t"                                    \
913         "pushl 12(%%eax)\n\t"                                    \
914         "pushl 8(%%eax)\n\t"                                     \
915         "pushl 4(%%eax)\n\t"                                     \
916         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
917         VALGRIND_CALL_NOREDIR_EAX                                \
918         "addl $40, %%esp\n"                                      \
919         : /*out*/   "=a" (_res)                                  \
920         : /*in*/    "a" (&_argvec[0])                            \
921         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
922      );                                                          \
923      lval = (__typeof__(lval)) _res;                             \
924   } while (0)
925
926#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
927                                  arg6,arg7,arg8,arg9,arg10,      \
928                                  arg11)                          \
929   do {                                                           \
930      volatile OrigFn        _orig = (orig);                      \
931      volatile unsigned long _argvec[12];                         \
932      volatile unsigned long _res;                                \
933      _argvec[0] = (unsigned long)_orig.nraddr;                   \
934      _argvec[1] = (unsigned long)(arg1);                         \
935      _argvec[2] = (unsigned long)(arg2);                         \
936      _argvec[3] = (unsigned long)(arg3);                         \
937      _argvec[4] = (unsigned long)(arg4);                         \
938      _argvec[5] = (unsigned long)(arg5);                         \
939      _argvec[6] = (unsigned long)(arg6);                         \
940      _argvec[7] = (unsigned long)(arg7);                         \
941      _argvec[8] = (unsigned long)(arg8);                         \
942      _argvec[9] = (unsigned long)(arg9);                         \
943      _argvec[10] = (unsigned long)(arg10);                       \
944      _argvec[11] = (unsigned long)(arg11);                       \
945      __asm__ volatile(                                           \
946         "pushl 44(%%eax)\n\t"                                    \
947         "pushl 40(%%eax)\n\t"                                    \
948         "pushl 36(%%eax)\n\t"                                    \
949         "pushl 32(%%eax)\n\t"                                    \
950         "pushl 28(%%eax)\n\t"                                    \
951         "pushl 24(%%eax)\n\t"                                    \
952         "pushl 20(%%eax)\n\t"                                    \
953         "pushl 16(%%eax)\n\t"                                    \
954         "pushl 12(%%eax)\n\t"                                    \
955         "pushl 8(%%eax)\n\t"                                     \
956         "pushl 4(%%eax)\n\t"                                     \
957         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
958         VALGRIND_CALL_NOREDIR_EAX                                \
959         "addl $44, %%esp\n"                                      \
960         : /*out*/   "=a" (_res)                                  \
961         : /*in*/    "a" (&_argvec[0])                            \
962         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
963      );                                                          \
964      lval = (__typeof__(lval)) _res;                             \
965   } while (0)
966
967#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
968                                  arg6,arg7,arg8,arg9,arg10,      \
969                                  arg11,arg12)                    \
970   do {                                                           \
971      volatile OrigFn        _orig = (orig);                      \
972      volatile unsigned long _argvec[13];                         \
973      volatile unsigned long _res;                                \
974      _argvec[0] = (unsigned long)_orig.nraddr;                   \
975      _argvec[1] = (unsigned long)(arg1);                         \
976      _argvec[2] = (unsigned long)(arg2);                         \
977      _argvec[3] = (unsigned long)(arg3);                         \
978      _argvec[4] = (unsigned long)(arg4);                         \
979      _argvec[5] = (unsigned long)(arg5);                         \
980      _argvec[6] = (unsigned long)(arg6);                         \
981      _argvec[7] = (unsigned long)(arg7);                         \
982      _argvec[8] = (unsigned long)(arg8);                         \
983      _argvec[9] = (unsigned long)(arg9);                         \
984      _argvec[10] = (unsigned long)(arg10);                       \
985      _argvec[11] = (unsigned long)(arg11);                       \
986      _argvec[12] = (unsigned long)(arg12);                       \
987      __asm__ volatile(                                           \
988         "pushl 48(%%eax)\n\t"                                    \
989         "pushl 44(%%eax)\n\t"                                    \
990         "pushl 40(%%eax)\n\t"                                    \
991         "pushl 36(%%eax)\n\t"                                    \
992         "pushl 32(%%eax)\n\t"                                    \
993         "pushl 28(%%eax)\n\t"                                    \
994         "pushl 24(%%eax)\n\t"                                    \
995         "pushl 20(%%eax)\n\t"                                    \
996         "pushl 16(%%eax)\n\t"                                    \
997         "pushl 12(%%eax)\n\t"                                    \
998         "pushl 8(%%eax)\n\t"                                     \
999         "pushl 4(%%eax)\n\t"                                     \
1000         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1001         VALGRIND_CALL_NOREDIR_EAX                                \
1002         "addl $48, %%esp\n"                                      \
1003         : /*out*/   "=a" (_res)                                  \
1004         : /*in*/    "a" (&_argvec[0])                            \
1005         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1006      );                                                          \
1007      lval = (__typeof__(lval)) _res;                             \
1008   } while (0)
1009
1010#endif /* PLAT_x86_linux */
1011
1012/* ------------------------ amd64-linux ------------------------ */
1013
1014#if defined(PLAT_amd64_linux)
1015
1016/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1017
1018/* These regs are trashed by the hidden call. */
1019#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi",       \
1020                            "rdi", "r8", "r9", "r10", "r11"
1021
1022/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1023   long) == 8. */
1024
1025/* NB 9 Sept 07.  There is a nasty kludge here in all these CALL_FN_
1026   macros.  In order not to trash the stack redzone, we need to drop
1027   %rsp by 128 before the hidden call, and restore afterwards.  The
1028   nastyness is that it is only by luck that the stack still appears
1029   to be unwindable during the hidden call - since then the behaviour
1030   of any routine using this macro does not match what the CFI data
1031   says.  Sigh.
1032
1033   Why is this important?  Imagine that a wrapper has a stack
1034   allocated local, and passes to the hidden call, a pointer to it.
1035   Because gcc does not know about the hidden call, it may allocate
1036   that local in the redzone.  Unfortunately the hidden call may then
1037   trash it before it comes to use it.  So we must step clear of the
1038   redzone, for the duration of the hidden call, to make it safe.
1039
1040   Probably the same problem afflicts the other redzone-style ABIs too
1041   (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1042   self describing (none of this CFI nonsense) so at least messing
1043   with the stack pointer doesn't give a danger of non-unwindable
1044   stack. */
1045
1046#define CALL_FN_W_v(lval, orig)                                   \
1047   do {                                                           \
1048      volatile OrigFn        _orig = (orig);                      \
1049      volatile unsigned long _argvec[1];                          \
1050      volatile unsigned long _res;                                \
1051      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1052      __asm__ volatile(                                           \
1053         "subq $128,%%rsp\n\t"                                    \
1054         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1055         VALGRIND_CALL_NOREDIR_RAX                                \
1056         "addq $128,%%rsp\n\t"                                    \
1057         : /*out*/   "=a" (_res)                                  \
1058         : /*in*/    "a" (&_argvec[0])                            \
1059         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1060      );                                                          \
1061      lval = (__typeof__(lval)) _res;                             \
1062   } while (0)
1063
1064#define CALL_FN_W_W(lval, orig, arg1)                             \
1065   do {                                                           \
1066      volatile OrigFn        _orig = (orig);                      \
1067      volatile unsigned long _argvec[2];                          \
1068      volatile unsigned long _res;                                \
1069      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1070      _argvec[1] = (unsigned long)(arg1);                         \
1071      __asm__ volatile(                                           \
1072         "subq $128,%%rsp\n\t"                                    \
1073         "movq 8(%%rax), %%rdi\n\t"                               \
1074         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1075         VALGRIND_CALL_NOREDIR_RAX                                \
1076         "addq $128,%%rsp\n\t"                                    \
1077         : /*out*/   "=a" (_res)                                  \
1078         : /*in*/    "a" (&_argvec[0])                            \
1079         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1080      );                                                          \
1081      lval = (__typeof__(lval)) _res;                             \
1082   } while (0)
1083
1084#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
1085   do {                                                           \
1086      volatile OrigFn        _orig = (orig);                      \
1087      volatile unsigned long _argvec[3];                          \
1088      volatile unsigned long _res;                                \
1089      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1090      _argvec[1] = (unsigned long)(arg1);                         \
1091      _argvec[2] = (unsigned long)(arg2);                         \
1092      __asm__ volatile(                                           \
1093         "subq $128,%%rsp\n\t"                                    \
1094         "movq 16(%%rax), %%rsi\n\t"                              \
1095         "movq 8(%%rax), %%rdi\n\t"                               \
1096         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1097         VALGRIND_CALL_NOREDIR_RAX                                \
1098         "addq $128,%%rsp\n\t"                                    \
1099         : /*out*/   "=a" (_res)                                  \
1100         : /*in*/    "a" (&_argvec[0])                            \
1101         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1102      );                                                          \
1103      lval = (__typeof__(lval)) _res;                             \
1104   } while (0)
1105
1106#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
1107   do {                                                           \
1108      volatile OrigFn        _orig = (orig);                      \
1109      volatile unsigned long _argvec[4];                          \
1110      volatile unsigned long _res;                                \
1111      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1112      _argvec[1] = (unsigned long)(arg1);                         \
1113      _argvec[2] = (unsigned long)(arg2);                         \
1114      _argvec[3] = (unsigned long)(arg3);                         \
1115      __asm__ volatile(                                           \
1116         "subq $128,%%rsp\n\t"                                    \
1117         "movq 24(%%rax), %%rdx\n\t"                              \
1118         "movq 16(%%rax), %%rsi\n\t"                              \
1119         "movq 8(%%rax), %%rdi\n\t"                               \
1120         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1121         VALGRIND_CALL_NOREDIR_RAX                                \
1122         "addq $128,%%rsp\n\t"                                    \
1123         : /*out*/   "=a" (_res)                                  \
1124         : /*in*/    "a" (&_argvec[0])                            \
1125         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1126      );                                                          \
1127      lval = (__typeof__(lval)) _res;                             \
1128   } while (0)
1129
1130#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
1131   do {                                                           \
1132      volatile OrigFn        _orig = (orig);                      \
1133      volatile unsigned long _argvec[5];                          \
1134      volatile unsigned long _res;                                \
1135      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1136      _argvec[1] = (unsigned long)(arg1);                         \
1137      _argvec[2] = (unsigned long)(arg2);                         \
1138      _argvec[3] = (unsigned long)(arg3);                         \
1139      _argvec[4] = (unsigned long)(arg4);                         \
1140      __asm__ volatile(                                           \
1141         "subq $128,%%rsp\n\t"                                    \
1142         "movq 32(%%rax), %%rcx\n\t"                              \
1143         "movq 24(%%rax), %%rdx\n\t"                              \
1144         "movq 16(%%rax), %%rsi\n\t"                              \
1145         "movq 8(%%rax), %%rdi\n\t"                               \
1146         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1147         VALGRIND_CALL_NOREDIR_RAX                                \
1148         "addq $128,%%rsp\n\t"                                    \
1149         : /*out*/   "=a" (_res)                                  \
1150         : /*in*/    "a" (&_argvec[0])                            \
1151         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1152      );                                                          \
1153      lval = (__typeof__(lval)) _res;                             \
1154   } while (0)
1155
1156#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
1157   do {                                                           \
1158      volatile OrigFn        _orig = (orig);                      \
1159      volatile unsigned long _argvec[6];                          \
1160      volatile unsigned long _res;                                \
1161      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1162      _argvec[1] = (unsigned long)(arg1);                         \
1163      _argvec[2] = (unsigned long)(arg2);                         \
1164      _argvec[3] = (unsigned long)(arg3);                         \
1165      _argvec[4] = (unsigned long)(arg4);                         \
1166      _argvec[5] = (unsigned long)(arg5);                         \
1167      __asm__ volatile(                                           \
1168         "subq $128,%%rsp\n\t"                                    \
1169         "movq 40(%%rax), %%r8\n\t"                               \
1170         "movq 32(%%rax), %%rcx\n\t"                              \
1171         "movq 24(%%rax), %%rdx\n\t"                              \
1172         "movq 16(%%rax), %%rsi\n\t"                              \
1173         "movq 8(%%rax), %%rdi\n\t"                               \
1174         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1175         VALGRIND_CALL_NOREDIR_RAX                                \
1176         "addq $128,%%rsp\n\t"                                    \
1177         : /*out*/   "=a" (_res)                                  \
1178         : /*in*/    "a" (&_argvec[0])                            \
1179         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1180      );                                                          \
1181      lval = (__typeof__(lval)) _res;                             \
1182   } while (0)
1183
1184#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
1185   do {                                                           \
1186      volatile OrigFn        _orig = (orig);                      \
1187      volatile unsigned long _argvec[7];                          \
1188      volatile unsigned long _res;                                \
1189      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1190      _argvec[1] = (unsigned long)(arg1);                         \
1191      _argvec[2] = (unsigned long)(arg2);                         \
1192      _argvec[3] = (unsigned long)(arg3);                         \
1193      _argvec[4] = (unsigned long)(arg4);                         \
1194      _argvec[5] = (unsigned long)(arg5);                         \
1195      _argvec[6] = (unsigned long)(arg6);                         \
1196      __asm__ volatile(                                           \
1197         "subq $128,%%rsp\n\t"                                    \
1198         "movq 48(%%rax), %%r9\n\t"                               \
1199         "movq 40(%%rax), %%r8\n\t"                               \
1200         "movq 32(%%rax), %%rcx\n\t"                              \
1201         "movq 24(%%rax), %%rdx\n\t"                              \
1202         "movq 16(%%rax), %%rsi\n\t"                              \
1203         "movq 8(%%rax), %%rdi\n\t"                               \
1204         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1205         "addq $128,%%rsp\n\t"                                    \
1206         VALGRIND_CALL_NOREDIR_RAX                                \
1207         : /*out*/   "=a" (_res)                                  \
1208         : /*in*/    "a" (&_argvec[0])                            \
1209         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1210      );                                                          \
1211      lval = (__typeof__(lval)) _res;                             \
1212   } while (0)
1213
1214#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1215                                 arg7)                            \
1216   do {                                                           \
1217      volatile OrigFn        _orig = (orig);                      \
1218      volatile unsigned long _argvec[8];                          \
1219      volatile unsigned long _res;                                \
1220      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1221      _argvec[1] = (unsigned long)(arg1);                         \
1222      _argvec[2] = (unsigned long)(arg2);                         \
1223      _argvec[3] = (unsigned long)(arg3);                         \
1224      _argvec[4] = (unsigned long)(arg4);                         \
1225      _argvec[5] = (unsigned long)(arg5);                         \
1226      _argvec[6] = (unsigned long)(arg6);                         \
1227      _argvec[7] = (unsigned long)(arg7);                         \
1228      __asm__ volatile(                                           \
1229         "subq $128,%%rsp\n\t"                                    \
1230         "pushq 56(%%rax)\n\t"                                    \
1231         "movq 48(%%rax), %%r9\n\t"                               \
1232         "movq 40(%%rax), %%r8\n\t"                               \
1233         "movq 32(%%rax), %%rcx\n\t"                              \
1234         "movq 24(%%rax), %%rdx\n\t"                              \
1235         "movq 16(%%rax), %%rsi\n\t"                              \
1236         "movq 8(%%rax), %%rdi\n\t"                               \
1237         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1238         VALGRIND_CALL_NOREDIR_RAX                                \
1239         "addq $8, %%rsp\n"                                       \
1240         "addq $128,%%rsp\n\t"                                    \
1241         : /*out*/   "=a" (_res)                                  \
1242         : /*in*/    "a" (&_argvec[0])                            \
1243         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1244      );                                                          \
1245      lval = (__typeof__(lval)) _res;                             \
1246   } while (0)
1247
1248#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1249                                 arg7,arg8)                       \
1250   do {                                                           \
1251      volatile OrigFn        _orig = (orig);                      \
1252      volatile unsigned long _argvec[9];                          \
1253      volatile unsigned long _res;                                \
1254      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1255      _argvec[1] = (unsigned long)(arg1);                         \
1256      _argvec[2] = (unsigned long)(arg2);                         \
1257      _argvec[3] = (unsigned long)(arg3);                         \
1258      _argvec[4] = (unsigned long)(arg4);                         \
1259      _argvec[5] = (unsigned long)(arg5);                         \
1260      _argvec[6] = (unsigned long)(arg6);                         \
1261      _argvec[7] = (unsigned long)(arg7);                         \
1262      _argvec[8] = (unsigned long)(arg8);                         \
1263      __asm__ volatile(                                           \
1264         "subq $128,%%rsp\n\t"                                    \
1265         "pushq 64(%%rax)\n\t"                                    \
1266         "pushq 56(%%rax)\n\t"                                    \
1267         "movq 48(%%rax), %%r9\n\t"                               \
1268         "movq 40(%%rax), %%r8\n\t"                               \
1269         "movq 32(%%rax), %%rcx\n\t"                              \
1270         "movq 24(%%rax), %%rdx\n\t"                              \
1271         "movq 16(%%rax), %%rsi\n\t"                              \
1272         "movq 8(%%rax), %%rdi\n\t"                               \
1273         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1274         VALGRIND_CALL_NOREDIR_RAX                                \
1275         "addq $16, %%rsp\n"                                      \
1276         "addq $128,%%rsp\n\t"                                    \
1277         : /*out*/   "=a" (_res)                                  \
1278         : /*in*/    "a" (&_argvec[0])                            \
1279         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1280      );                                                          \
1281      lval = (__typeof__(lval)) _res;                             \
1282   } while (0)
1283
1284#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1285                                 arg7,arg8,arg9)                  \
1286   do {                                                           \
1287      volatile OrigFn        _orig = (orig);                      \
1288      volatile unsigned long _argvec[10];                         \
1289      volatile unsigned long _res;                                \
1290      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1291      _argvec[1] = (unsigned long)(arg1);                         \
1292      _argvec[2] = (unsigned long)(arg2);                         \
1293      _argvec[3] = (unsigned long)(arg3);                         \
1294      _argvec[4] = (unsigned long)(arg4);                         \
1295      _argvec[5] = (unsigned long)(arg5);                         \
1296      _argvec[6] = (unsigned long)(arg6);                         \
1297      _argvec[7] = (unsigned long)(arg7);                         \
1298      _argvec[8] = (unsigned long)(arg8);                         \
1299      _argvec[9] = (unsigned long)(arg9);                         \
1300      __asm__ volatile(                                           \
1301         "subq $128,%%rsp\n\t"                                    \
1302         "pushq 72(%%rax)\n\t"                                    \
1303         "pushq 64(%%rax)\n\t"                                    \
1304         "pushq 56(%%rax)\n\t"                                    \
1305         "movq 48(%%rax), %%r9\n\t"                               \
1306         "movq 40(%%rax), %%r8\n\t"                               \
1307         "movq 32(%%rax), %%rcx\n\t"                              \
1308         "movq 24(%%rax), %%rdx\n\t"                              \
1309         "movq 16(%%rax), %%rsi\n\t"                              \
1310         "movq 8(%%rax), %%rdi\n\t"                               \
1311         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1312         VALGRIND_CALL_NOREDIR_RAX                                \
1313         "addq $24, %%rsp\n"                                      \
1314         "addq $128,%%rsp\n\t"                                    \
1315         : /*out*/   "=a" (_res)                                  \
1316         : /*in*/    "a" (&_argvec[0])                            \
1317         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1318      );                                                          \
1319      lval = (__typeof__(lval)) _res;                             \
1320   } while (0)
1321
1322#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1323                                  arg7,arg8,arg9,arg10)           \
1324   do {                                                           \
1325      volatile OrigFn        _orig = (orig);                      \
1326      volatile unsigned long _argvec[11];                         \
1327      volatile unsigned long _res;                                \
1328      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1329      _argvec[1] = (unsigned long)(arg1);                         \
1330      _argvec[2] = (unsigned long)(arg2);                         \
1331      _argvec[3] = (unsigned long)(arg3);                         \
1332      _argvec[4] = (unsigned long)(arg4);                         \
1333      _argvec[5] = (unsigned long)(arg5);                         \
1334      _argvec[6] = (unsigned long)(arg6);                         \
1335      _argvec[7] = (unsigned long)(arg7);                         \
1336      _argvec[8] = (unsigned long)(arg8);                         \
1337      _argvec[9] = (unsigned long)(arg9);                         \
1338      _argvec[10] = (unsigned long)(arg10);                       \
1339      __asm__ volatile(                                           \
1340         "subq $128,%%rsp\n\t"                                    \
1341         "pushq 80(%%rax)\n\t"                                    \
1342         "pushq 72(%%rax)\n\t"                                    \
1343         "pushq 64(%%rax)\n\t"                                    \
1344         "pushq 56(%%rax)\n\t"                                    \
1345         "movq 48(%%rax), %%r9\n\t"                               \
1346         "movq 40(%%rax), %%r8\n\t"                               \
1347         "movq 32(%%rax), %%rcx\n\t"                              \
1348         "movq 24(%%rax), %%rdx\n\t"                              \
1349         "movq 16(%%rax), %%rsi\n\t"                              \
1350         "movq 8(%%rax), %%rdi\n\t"                               \
1351         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1352         VALGRIND_CALL_NOREDIR_RAX                                \
1353         "addq $32, %%rsp\n"                                      \
1354         "addq $128,%%rsp\n\t"                                    \
1355         : /*out*/   "=a" (_res)                                  \
1356         : /*in*/    "a" (&_argvec[0])                            \
1357         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1358      );                                                          \
1359      lval = (__typeof__(lval)) _res;                             \
1360   } while (0)
1361
1362#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1363                                  arg7,arg8,arg9,arg10,arg11)     \
1364   do {                                                           \
1365      volatile OrigFn        _orig = (orig);                      \
1366      volatile unsigned long _argvec[12];                         \
1367      volatile unsigned long _res;                                \
1368      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1369      _argvec[1] = (unsigned long)(arg1);                         \
1370      _argvec[2] = (unsigned long)(arg2);                         \
1371      _argvec[3] = (unsigned long)(arg3);                         \
1372      _argvec[4] = (unsigned long)(arg4);                         \
1373      _argvec[5] = (unsigned long)(arg5);                         \
1374      _argvec[6] = (unsigned long)(arg6);                         \
1375      _argvec[7] = (unsigned long)(arg7);                         \
1376      _argvec[8] = (unsigned long)(arg8);                         \
1377      _argvec[9] = (unsigned long)(arg9);                         \
1378      _argvec[10] = (unsigned long)(arg10);                       \
1379      _argvec[11] = (unsigned long)(arg11);                       \
1380      __asm__ volatile(                                           \
1381         "subq $128,%%rsp\n\t"                                    \
1382         "pushq 88(%%rax)\n\t"                                    \
1383         "pushq 80(%%rax)\n\t"                                    \
1384         "pushq 72(%%rax)\n\t"                                    \
1385         "pushq 64(%%rax)\n\t"                                    \
1386         "pushq 56(%%rax)\n\t"                                    \
1387         "movq 48(%%rax), %%r9\n\t"                               \
1388         "movq 40(%%rax), %%r8\n\t"                               \
1389         "movq 32(%%rax), %%rcx\n\t"                              \
1390         "movq 24(%%rax), %%rdx\n\t"                              \
1391         "movq 16(%%rax), %%rsi\n\t"                              \
1392         "movq 8(%%rax), %%rdi\n\t"                               \
1393         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1394         VALGRIND_CALL_NOREDIR_RAX                                \
1395         "addq $40, %%rsp\n"                                      \
1396         "addq $128,%%rsp\n\t"                                    \
1397         : /*out*/   "=a" (_res)                                  \
1398         : /*in*/    "a" (&_argvec[0])                            \
1399         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1400      );                                                          \
1401      lval = (__typeof__(lval)) _res;                             \
1402   } while (0)
1403
1404#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1405                                arg7,arg8,arg9,arg10,arg11,arg12) \
1406   do {                                                           \
1407      volatile OrigFn        _orig = (orig);                      \
1408      volatile unsigned long _argvec[13];                         \
1409      volatile unsigned long _res;                                \
1410      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1411      _argvec[1] = (unsigned long)(arg1);                         \
1412      _argvec[2] = (unsigned long)(arg2);                         \
1413      _argvec[3] = (unsigned long)(arg3);                         \
1414      _argvec[4] = (unsigned long)(arg4);                         \
1415      _argvec[5] = (unsigned long)(arg5);                         \
1416      _argvec[6] = (unsigned long)(arg6);                         \
1417      _argvec[7] = (unsigned long)(arg7);                         \
1418      _argvec[8] = (unsigned long)(arg8);                         \
1419      _argvec[9] = (unsigned long)(arg9);                         \
1420      _argvec[10] = (unsigned long)(arg10);                       \
1421      _argvec[11] = (unsigned long)(arg11);                       \
1422      _argvec[12] = (unsigned long)(arg12);                       \
1423      __asm__ volatile(                                           \
1424         "subq $128,%%rsp\n\t"                                    \
1425         "pushq 96(%%rax)\n\t"                                    \
1426         "pushq 88(%%rax)\n\t"                                    \
1427         "pushq 80(%%rax)\n\t"                                    \
1428         "pushq 72(%%rax)\n\t"                                    \
1429         "pushq 64(%%rax)\n\t"                                    \
1430         "pushq 56(%%rax)\n\t"                                    \
1431         "movq 48(%%rax), %%r9\n\t"                               \
1432         "movq 40(%%rax), %%r8\n\t"                               \
1433         "movq 32(%%rax), %%rcx\n\t"                              \
1434         "movq 24(%%rax), %%rdx\n\t"                              \
1435         "movq 16(%%rax), %%rsi\n\t"                              \
1436         "movq 8(%%rax), %%rdi\n\t"                               \
1437         "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
1438         VALGRIND_CALL_NOREDIR_RAX                                \
1439         "addq $48, %%rsp\n"                                      \
1440         "addq $128,%%rsp\n\t"                                    \
1441         : /*out*/   "=a" (_res)                                  \
1442         : /*in*/    "a" (&_argvec[0])                            \
1443         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1444      );                                                          \
1445      lval = (__typeof__(lval)) _res;                             \
1446   } while (0)
1447
1448#endif /* PLAT_amd64_linux */
1449
1450/* ------------------------ ppc32-linux ------------------------ */
1451
1452#if defined(PLAT_ppc32_linux)
1453
1454/* This is useful for finding out about the on-stack stuff:
1455
1456   extern int f9  ( int,int,int,int,int,int,int,int,int );
1457   extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1458   extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1459   extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1460
1461   int g9 ( void ) {
1462      return f9(11,22,33,44,55,66,77,88,99);
1463   }
1464   int g10 ( void ) {
1465      return f10(11,22,33,44,55,66,77,88,99,110);
1466   }
1467   int g11 ( void ) {
1468      return f11(11,22,33,44,55,66,77,88,99,110,121);
1469   }
1470   int g12 ( void ) {
1471      return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1472   }
1473*/
1474
1475/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1476
1477/* These regs are trashed by the hidden call. */
1478#define __CALLER_SAVED_REGS                                       \
1479   "lr", "ctr", "xer",                                            \
1480   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
1481   "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
1482   "r11", "r12", "r13"
1483
1484/* These CALL_FN_ macros assume that on ppc32-linux,
1485   sizeof(unsigned long) == 4. */
1486
1487#define CALL_FN_W_v(lval, orig)                                   \
1488   do {                                                           \
1489      volatile OrigFn        _orig = (orig);                      \
1490      volatile unsigned long _argvec[1];                          \
1491      volatile unsigned long _res;                                \
1492      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1493      __asm__ volatile(                                           \
1494         "mr 11,%1\n\t"                                           \
1495         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1496         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1497         "mr %0,3"                                                \
1498         : /*out*/   "=r" (_res)                                  \
1499         : /*in*/    "r" (&_argvec[0])                            \
1500         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1501      );                                                          \
1502      lval = (__typeof__(lval)) _res;                             \
1503   } while (0)
1504
1505#define CALL_FN_W_W(lval, orig, arg1)                             \
1506   do {                                                           \
1507      volatile OrigFn        _orig = (orig);                      \
1508      volatile unsigned long _argvec[2];                          \
1509      volatile unsigned long _res;                                \
1510      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1511      _argvec[1] = (unsigned long)arg1;                           \
1512      __asm__ volatile(                                           \
1513         "mr 11,%1\n\t"                                           \
1514         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1515         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1516         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1517         "mr %0,3"                                                \
1518         : /*out*/   "=r" (_res)                                  \
1519         : /*in*/    "r" (&_argvec[0])                            \
1520         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1521      );                                                          \
1522      lval = (__typeof__(lval)) _res;                             \
1523   } while (0)
1524
1525#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
1526   do {                                                           \
1527      volatile OrigFn        _orig = (orig);                      \
1528      volatile unsigned long _argvec[3];                          \
1529      volatile unsigned long _res;                                \
1530      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1531      _argvec[1] = (unsigned long)arg1;                           \
1532      _argvec[2] = (unsigned long)arg2;                           \
1533      __asm__ volatile(                                           \
1534         "mr 11,%1\n\t"                                           \
1535         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1536         "lwz 4,8(11)\n\t"                                        \
1537         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1538         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1539         "mr %0,3"                                                \
1540         : /*out*/   "=r" (_res)                                  \
1541         : /*in*/    "r" (&_argvec[0])                            \
1542         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1543      );                                                          \
1544      lval = (__typeof__(lval)) _res;                             \
1545   } while (0)
1546
1547#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
1548   do {                                                           \
1549      volatile OrigFn        _orig = (orig);                      \
1550      volatile unsigned long _argvec[4];                          \
1551      volatile unsigned long _res;                                \
1552      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1553      _argvec[1] = (unsigned long)arg1;                           \
1554      _argvec[2] = (unsigned long)arg2;                           \
1555      _argvec[3] = (unsigned long)arg3;                           \
1556      __asm__ volatile(                                           \
1557         "mr 11,%1\n\t"                                           \
1558         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1559         "lwz 4,8(11)\n\t"                                        \
1560         "lwz 5,12(11)\n\t"                                       \
1561         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1562         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1563         "mr %0,3"                                                \
1564         : /*out*/   "=r" (_res)                                  \
1565         : /*in*/    "r" (&_argvec[0])                            \
1566         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1567      );                                                          \
1568      lval = (__typeof__(lval)) _res;                             \
1569   } while (0)
1570
1571#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
1572   do {                                                           \
1573      volatile OrigFn        _orig = (orig);                      \
1574      volatile unsigned long _argvec[5];                          \
1575      volatile unsigned long _res;                                \
1576      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1577      _argvec[1] = (unsigned long)arg1;                           \
1578      _argvec[2] = (unsigned long)arg2;                           \
1579      _argvec[3] = (unsigned long)arg3;                           \
1580      _argvec[4] = (unsigned long)arg4;                           \
1581      __asm__ volatile(                                           \
1582         "mr 11,%1\n\t"                                           \
1583         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1584         "lwz 4,8(11)\n\t"                                        \
1585         "lwz 5,12(11)\n\t"                                       \
1586         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1587         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1588         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1589         "mr %0,3"                                                \
1590         : /*out*/   "=r" (_res)                                  \
1591         : /*in*/    "r" (&_argvec[0])                            \
1592         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1593      );                                                          \
1594      lval = (__typeof__(lval)) _res;                             \
1595   } while (0)
1596
1597#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
1598   do {                                                           \
1599      volatile OrigFn        _orig = (orig);                      \
1600      volatile unsigned long _argvec[6];                          \
1601      volatile unsigned long _res;                                \
1602      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1603      _argvec[1] = (unsigned long)arg1;                           \
1604      _argvec[2] = (unsigned long)arg2;                           \
1605      _argvec[3] = (unsigned long)arg3;                           \
1606      _argvec[4] = (unsigned long)arg4;                           \
1607      _argvec[5] = (unsigned long)arg5;                           \
1608      __asm__ volatile(                                           \
1609         "mr 11,%1\n\t"                                           \
1610         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1611         "lwz 4,8(11)\n\t"                                        \
1612         "lwz 5,12(11)\n\t"                                       \
1613         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1614         "lwz 7,20(11)\n\t"                                       \
1615         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1616         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1617         "mr %0,3"                                                \
1618         : /*out*/   "=r" (_res)                                  \
1619         : /*in*/    "r" (&_argvec[0])                            \
1620         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1621      );                                                          \
1622      lval = (__typeof__(lval)) _res;                             \
1623   } while (0)
1624
1625#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
1626   do {                                                           \
1627      volatile OrigFn        _orig = (orig);                      \
1628      volatile unsigned long _argvec[7];                          \
1629      volatile unsigned long _res;                                \
1630      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1631      _argvec[1] = (unsigned long)arg1;                           \
1632      _argvec[2] = (unsigned long)arg2;                           \
1633      _argvec[3] = (unsigned long)arg3;                           \
1634      _argvec[4] = (unsigned long)arg4;                           \
1635      _argvec[5] = (unsigned long)arg5;                           \
1636      _argvec[6] = (unsigned long)arg6;                           \
1637      __asm__ volatile(                                           \
1638         "mr 11,%1\n\t"                                           \
1639         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1640         "lwz 4,8(11)\n\t"                                        \
1641         "lwz 5,12(11)\n\t"                                       \
1642         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1643         "lwz 7,20(11)\n\t"                                       \
1644         "lwz 8,24(11)\n\t"                                       \
1645         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1646         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1647         "mr %0,3"                                                \
1648         : /*out*/   "=r" (_res)                                  \
1649         : /*in*/    "r" (&_argvec[0])                            \
1650         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1651      );                                                          \
1652      lval = (__typeof__(lval)) _res;                             \
1653   } while (0)
1654
1655#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1656                                 arg7)                            \
1657   do {                                                           \
1658      volatile OrigFn        _orig = (orig);                      \
1659      volatile unsigned long _argvec[8];                          \
1660      volatile unsigned long _res;                                \
1661      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1662      _argvec[1] = (unsigned long)arg1;                           \
1663      _argvec[2] = (unsigned long)arg2;                           \
1664      _argvec[3] = (unsigned long)arg3;                           \
1665      _argvec[4] = (unsigned long)arg4;                           \
1666      _argvec[5] = (unsigned long)arg5;                           \
1667      _argvec[6] = (unsigned long)arg6;                           \
1668      _argvec[7] = (unsigned long)arg7;                           \
1669      __asm__ volatile(                                           \
1670         "mr 11,%1\n\t"                                           \
1671         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1672         "lwz 4,8(11)\n\t"                                        \
1673         "lwz 5,12(11)\n\t"                                       \
1674         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1675         "lwz 7,20(11)\n\t"                                       \
1676         "lwz 8,24(11)\n\t"                                       \
1677         "lwz 9,28(11)\n\t"                                       \
1678         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1679         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1680         "mr %0,3"                                                \
1681         : /*out*/   "=r" (_res)                                  \
1682         : /*in*/    "r" (&_argvec[0])                            \
1683         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1684      );                                                          \
1685      lval = (__typeof__(lval)) _res;                             \
1686   } while (0)
1687
1688#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1689                                 arg7,arg8)                       \
1690   do {                                                           \
1691      volatile OrigFn        _orig = (orig);                      \
1692      volatile unsigned long _argvec[9];                          \
1693      volatile unsigned long _res;                                \
1694      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1695      _argvec[1] = (unsigned long)arg1;                           \
1696      _argvec[2] = (unsigned long)arg2;                           \
1697      _argvec[3] = (unsigned long)arg3;                           \
1698      _argvec[4] = (unsigned long)arg4;                           \
1699      _argvec[5] = (unsigned long)arg5;                           \
1700      _argvec[6] = (unsigned long)arg6;                           \
1701      _argvec[7] = (unsigned long)arg7;                           \
1702      _argvec[8] = (unsigned long)arg8;                           \
1703      __asm__ volatile(                                           \
1704         "mr 11,%1\n\t"                                           \
1705         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1706         "lwz 4,8(11)\n\t"                                        \
1707         "lwz 5,12(11)\n\t"                                       \
1708         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1709         "lwz 7,20(11)\n\t"                                       \
1710         "lwz 8,24(11)\n\t"                                       \
1711         "lwz 9,28(11)\n\t"                                       \
1712         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
1713         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1714         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1715         "mr %0,3"                                                \
1716         : /*out*/   "=r" (_res)                                  \
1717         : /*in*/    "r" (&_argvec[0])                            \
1718         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1719      );                                                          \
1720      lval = (__typeof__(lval)) _res;                             \
1721   } while (0)
1722
1723#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1724                                 arg7,arg8,arg9)                  \
1725   do {                                                           \
1726      volatile OrigFn        _orig = (orig);                      \
1727      volatile unsigned long _argvec[10];                         \
1728      volatile unsigned long _res;                                \
1729      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1730      _argvec[1] = (unsigned long)arg1;                           \
1731      _argvec[2] = (unsigned long)arg2;                           \
1732      _argvec[3] = (unsigned long)arg3;                           \
1733      _argvec[4] = (unsigned long)arg4;                           \
1734      _argvec[5] = (unsigned long)arg5;                           \
1735      _argvec[6] = (unsigned long)arg6;                           \
1736      _argvec[7] = (unsigned long)arg7;                           \
1737      _argvec[8] = (unsigned long)arg8;                           \
1738      _argvec[9] = (unsigned long)arg9;                           \
1739      __asm__ volatile(                                           \
1740         "mr 11,%1\n\t"                                           \
1741         "addi 1,1,-16\n\t"                                       \
1742         /* arg9 */                                               \
1743         "lwz 3,36(11)\n\t"                                       \
1744         "stw 3,8(1)\n\t"                                         \
1745         /* args1-8 */                                            \
1746         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1747         "lwz 4,8(11)\n\t"                                        \
1748         "lwz 5,12(11)\n\t"                                       \
1749         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1750         "lwz 7,20(11)\n\t"                                       \
1751         "lwz 8,24(11)\n\t"                                       \
1752         "lwz 9,28(11)\n\t"                                       \
1753         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
1754         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1755         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1756         "addi 1,1,16\n\t"                                        \
1757         "mr %0,3"                                                \
1758         : /*out*/   "=r" (_res)                                  \
1759         : /*in*/    "r" (&_argvec[0])                            \
1760         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1761      );                                                          \
1762      lval = (__typeof__(lval)) _res;                             \
1763   } while (0)
1764
1765#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1766                                  arg7,arg8,arg9,arg10)           \
1767   do {                                                           \
1768      volatile OrigFn        _orig = (orig);                      \
1769      volatile unsigned long _argvec[11];                         \
1770      volatile unsigned long _res;                                \
1771      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1772      _argvec[1] = (unsigned long)arg1;                           \
1773      _argvec[2] = (unsigned long)arg2;                           \
1774      _argvec[3] = (unsigned long)arg3;                           \
1775      _argvec[4] = (unsigned long)arg4;                           \
1776      _argvec[5] = (unsigned long)arg5;                           \
1777      _argvec[6] = (unsigned long)arg6;                           \
1778      _argvec[7] = (unsigned long)arg7;                           \
1779      _argvec[8] = (unsigned long)arg8;                           \
1780      _argvec[9] = (unsigned long)arg9;                           \
1781      _argvec[10] = (unsigned long)arg10;                         \
1782      __asm__ volatile(                                           \
1783         "mr 11,%1\n\t"                                           \
1784         "addi 1,1,-16\n\t"                                       \
1785         /* arg10 */                                              \
1786         "lwz 3,40(11)\n\t"                                       \
1787         "stw 3,12(1)\n\t"                                        \
1788         /* arg9 */                                               \
1789         "lwz 3,36(11)\n\t"                                       \
1790         "stw 3,8(1)\n\t"                                         \
1791         /* args1-8 */                                            \
1792         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1793         "lwz 4,8(11)\n\t"                                        \
1794         "lwz 5,12(11)\n\t"                                       \
1795         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1796         "lwz 7,20(11)\n\t"                                       \
1797         "lwz 8,24(11)\n\t"                                       \
1798         "lwz 9,28(11)\n\t"                                       \
1799         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
1800         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1801         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1802         "addi 1,1,16\n\t"                                        \
1803         "mr %0,3"                                                \
1804         : /*out*/   "=r" (_res)                                  \
1805         : /*in*/    "r" (&_argvec[0])                            \
1806         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1807      );                                                          \
1808      lval = (__typeof__(lval)) _res;                             \
1809   } while (0)
1810
1811#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1812                                  arg7,arg8,arg9,arg10,arg11)     \
1813   do {                                                           \
1814      volatile OrigFn        _orig = (orig);                      \
1815      volatile unsigned long _argvec[12];                         \
1816      volatile unsigned long _res;                                \
1817      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1818      _argvec[1] = (unsigned long)arg1;                           \
1819      _argvec[2] = (unsigned long)arg2;                           \
1820      _argvec[3] = (unsigned long)arg3;                           \
1821      _argvec[4] = (unsigned long)arg4;                           \
1822      _argvec[5] = (unsigned long)arg5;                           \
1823      _argvec[6] = (unsigned long)arg6;                           \
1824      _argvec[7] = (unsigned long)arg7;                           \
1825      _argvec[8] = (unsigned long)arg8;                           \
1826      _argvec[9] = (unsigned long)arg9;                           \
1827      _argvec[10] = (unsigned long)arg10;                         \
1828      _argvec[11] = (unsigned long)arg11;                         \
1829      __asm__ volatile(                                           \
1830         "mr 11,%1\n\t"                                           \
1831         "addi 1,1,-32\n\t"                                       \
1832         /* arg11 */                                              \
1833         "lwz 3,44(11)\n\t"                                       \
1834         "stw 3,16(1)\n\t"                                        \
1835         /* arg10 */                                              \
1836         "lwz 3,40(11)\n\t"                                       \
1837         "stw 3,12(1)\n\t"                                        \
1838         /* arg9 */                                               \
1839         "lwz 3,36(11)\n\t"                                       \
1840         "stw 3,8(1)\n\t"                                         \
1841         /* args1-8 */                                            \
1842         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1843         "lwz 4,8(11)\n\t"                                        \
1844         "lwz 5,12(11)\n\t"                                       \
1845         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1846         "lwz 7,20(11)\n\t"                                       \
1847         "lwz 8,24(11)\n\t"                                       \
1848         "lwz 9,28(11)\n\t"                                       \
1849         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
1850         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1851         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1852         "addi 1,1,32\n\t"                                        \
1853         "mr %0,3"                                                \
1854         : /*out*/   "=r" (_res)                                  \
1855         : /*in*/    "r" (&_argvec[0])                            \
1856         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1857      );                                                          \
1858      lval = (__typeof__(lval)) _res;                             \
1859   } while (0)
1860
1861#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1862                                arg7,arg8,arg9,arg10,arg11,arg12) \
1863   do {                                                           \
1864      volatile OrigFn        _orig = (orig);                      \
1865      volatile unsigned long _argvec[13];                         \
1866      volatile unsigned long _res;                                \
1867      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1868      _argvec[1] = (unsigned long)arg1;                           \
1869      _argvec[2] = (unsigned long)arg2;                           \
1870      _argvec[3] = (unsigned long)arg3;                           \
1871      _argvec[4] = (unsigned long)arg4;                           \
1872      _argvec[5] = (unsigned long)arg5;                           \
1873      _argvec[6] = (unsigned long)arg6;                           \
1874      _argvec[7] = (unsigned long)arg7;                           \
1875      _argvec[8] = (unsigned long)arg8;                           \
1876      _argvec[9] = (unsigned long)arg9;                           \
1877      _argvec[10] = (unsigned long)arg10;                         \
1878      _argvec[11] = (unsigned long)arg11;                         \
1879      _argvec[12] = (unsigned long)arg12;                         \
1880      __asm__ volatile(                                           \
1881         "mr 11,%1\n\t"                                           \
1882         "addi 1,1,-32\n\t"                                       \
1883         /* arg12 */                                              \
1884         "lwz 3,48(11)\n\t"                                       \
1885         "stw 3,20(1)\n\t"                                        \
1886         /* arg11 */                                              \
1887         "lwz 3,44(11)\n\t"                                       \
1888         "stw 3,16(1)\n\t"                                        \
1889         /* arg10 */                                              \
1890         "lwz 3,40(11)\n\t"                                       \
1891         "stw 3,12(1)\n\t"                                        \
1892         /* arg9 */                                               \
1893         "lwz 3,36(11)\n\t"                                       \
1894         "stw 3,8(1)\n\t"                                         \
1895         /* args1-8 */                                            \
1896         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
1897         "lwz 4,8(11)\n\t"                                        \
1898         "lwz 5,12(11)\n\t"                                       \
1899         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
1900         "lwz 7,20(11)\n\t"                                       \
1901         "lwz 8,24(11)\n\t"                                       \
1902         "lwz 9,28(11)\n\t"                                       \
1903         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
1904         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
1905         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1906         "addi 1,1,32\n\t"                                        \
1907         "mr %0,3"                                                \
1908         : /*out*/   "=r" (_res)                                  \
1909         : /*in*/    "r" (&_argvec[0])                            \
1910         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1911      );                                                          \
1912      lval = (__typeof__(lval)) _res;                             \
1913   } while (0)
1914
1915#endif /* PLAT_ppc32_linux */
1916
1917/* ------------------------ ppc64-linux ------------------------ */
1918
1919#if defined(PLAT_ppc64_linux)
1920
1921/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1922
1923/* These regs are trashed by the hidden call. */
1924#define __CALLER_SAVED_REGS                                       \
1925   "lr", "ctr", "xer",                                            \
1926   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
1927   "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
1928   "r11", "r12", "r13"
1929
1930/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1931   long) == 8. */
1932
1933#define CALL_FN_W_v(lval, orig)                                   \
1934   do {                                                           \
1935      volatile OrigFn        _orig = (orig);                      \
1936      volatile unsigned long _argvec[3+0];                        \
1937      volatile unsigned long _res;                                \
1938      /* _argvec[0] holds current r2 across the call */           \
1939      _argvec[1] = (unsigned long)_orig.r2;                       \
1940      _argvec[2] = (unsigned long)_orig.nraddr;                   \
1941      __asm__ volatile(                                           \
1942         "mr 11,%1\n\t"                                           \
1943         "std 2,-16(11)\n\t"  /* save tocptr */                   \
1944         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
1945         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
1946         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1947         "mr 11,%1\n\t"                                           \
1948         "mr %0,3\n\t"                                            \
1949         "ld 2,-16(11)" /* restore tocptr */                      \
1950         : /*out*/   "=r" (_res)                                  \
1951         : /*in*/    "r" (&_argvec[2])                            \
1952         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1953      );                                                          \
1954      lval = (__typeof__(lval)) _res;                             \
1955   } while (0)
1956
1957#define CALL_FN_W_W(lval, orig, arg1)                             \
1958   do {                                                           \
1959      volatile OrigFn        _orig = (orig);                      \
1960      volatile unsigned long _argvec[3+1];                        \
1961      volatile unsigned long _res;                                \
1962      /* _argvec[0] holds current r2 across the call */           \
1963      _argvec[1]   = (unsigned long)_orig.r2;                     \
1964      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
1965      _argvec[2+1] = (unsigned long)arg1;                         \
1966      __asm__ volatile(                                           \
1967         "mr 11,%1\n\t"                                           \
1968         "std 2,-16(11)\n\t"  /* save tocptr */                   \
1969         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
1970         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
1971         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
1972         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
1973         "mr 11,%1\n\t"                                           \
1974         "mr %0,3\n\t"                                            \
1975         "ld 2,-16(11)" /* restore tocptr */                      \
1976         : /*out*/   "=r" (_res)                                  \
1977         : /*in*/    "r" (&_argvec[2])                            \
1978         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
1979      );                                                          \
1980      lval = (__typeof__(lval)) _res;                             \
1981   } while (0)
1982
1983#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
1984   do {                                                           \
1985      volatile OrigFn        _orig = (orig);                      \
1986      volatile unsigned long _argvec[3+2];                        \
1987      volatile unsigned long _res;                                \
1988      /* _argvec[0] holds current r2 across the call */           \
1989      _argvec[1]   = (unsigned long)_orig.r2;                     \
1990      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
1991      _argvec[2+1] = (unsigned long)arg1;                         \
1992      _argvec[2+2] = (unsigned long)arg2;                         \
1993      __asm__ volatile(                                           \
1994         "mr 11,%1\n\t"                                           \
1995         "std 2,-16(11)\n\t"  /* save tocptr */                   \
1996         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
1997         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
1998         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
1999         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2000         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2001         "mr 11,%1\n\t"                                           \
2002         "mr %0,3\n\t"                                            \
2003         "ld 2,-16(11)" /* restore tocptr */                      \
2004         : /*out*/   "=r" (_res)                                  \
2005         : /*in*/    "r" (&_argvec[2])                            \
2006         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2007      );                                                          \
2008      lval = (__typeof__(lval)) _res;                             \
2009   } while (0)
2010
2011#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2012   do {                                                           \
2013      volatile OrigFn        _orig = (orig);                      \
2014      volatile unsigned long _argvec[3+3];                        \
2015      volatile unsigned long _res;                                \
2016      /* _argvec[0] holds current r2 across the call */           \
2017      _argvec[1]   = (unsigned long)_orig.r2;                     \
2018      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2019      _argvec[2+1] = (unsigned long)arg1;                         \
2020      _argvec[2+2] = (unsigned long)arg2;                         \
2021      _argvec[2+3] = (unsigned long)arg3;                         \
2022      __asm__ volatile(                                           \
2023         "mr 11,%1\n\t"                                           \
2024         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2025         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2026         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2027         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2028         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2029         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2030         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2031         "mr 11,%1\n\t"                                           \
2032         "mr %0,3\n\t"                                            \
2033         "ld 2,-16(11)" /* restore tocptr */                      \
2034         : /*out*/   "=r" (_res)                                  \
2035         : /*in*/    "r" (&_argvec[2])                            \
2036         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2037      );                                                          \
2038      lval = (__typeof__(lval)) _res;                             \
2039   } while (0)
2040
2041#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2042   do {                                                           \
2043      volatile OrigFn        _orig = (orig);                      \
2044      volatile unsigned long _argvec[3+4];                        \
2045      volatile unsigned long _res;                                \
2046      /* _argvec[0] holds current r2 across the call */           \
2047      _argvec[1]   = (unsigned long)_orig.r2;                     \
2048      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2049      _argvec[2+1] = (unsigned long)arg1;                         \
2050      _argvec[2+2] = (unsigned long)arg2;                         \
2051      _argvec[2+3] = (unsigned long)arg3;                         \
2052      _argvec[2+4] = (unsigned long)arg4;                         \
2053      __asm__ volatile(                                           \
2054         "mr 11,%1\n\t"                                           \
2055         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2056         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2057         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2058         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2059         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2060         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2061         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2062         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2063         "mr 11,%1\n\t"                                           \
2064         "mr %0,3\n\t"                                            \
2065         "ld 2,-16(11)" /* restore tocptr */                      \
2066         : /*out*/   "=r" (_res)                                  \
2067         : /*in*/    "r" (&_argvec[2])                            \
2068         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2069      );                                                          \
2070      lval = (__typeof__(lval)) _res;                             \
2071   } while (0)
2072
2073#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2074   do {                                                           \
2075      volatile OrigFn        _orig = (orig);                      \
2076      volatile unsigned long _argvec[3+5];                        \
2077      volatile unsigned long _res;                                \
2078      /* _argvec[0] holds current r2 across the call */           \
2079      _argvec[1]   = (unsigned long)_orig.r2;                     \
2080      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2081      _argvec[2+1] = (unsigned long)arg1;                         \
2082      _argvec[2+2] = (unsigned long)arg2;                         \
2083      _argvec[2+3] = (unsigned long)arg3;                         \
2084      _argvec[2+4] = (unsigned long)arg4;                         \
2085      _argvec[2+5] = (unsigned long)arg5;                         \
2086      __asm__ volatile(                                           \
2087         "mr 11,%1\n\t"                                           \
2088         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2089         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2090         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2091         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2092         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2093         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2094         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2095         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2096         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2097         "mr 11,%1\n\t"                                           \
2098         "mr %0,3\n\t"                                            \
2099         "ld 2,-16(11)" /* restore tocptr */                      \
2100         : /*out*/   "=r" (_res)                                  \
2101         : /*in*/    "r" (&_argvec[2])                            \
2102         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2103      );                                                          \
2104      lval = (__typeof__(lval)) _res;                             \
2105   } while (0)
2106
2107#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2108   do {                                                           \
2109      volatile OrigFn        _orig = (orig);                      \
2110      volatile unsigned long _argvec[3+6];                        \
2111      volatile unsigned long _res;                                \
2112      /* _argvec[0] holds current r2 across the call */           \
2113      _argvec[1]   = (unsigned long)_orig.r2;                     \
2114      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2115      _argvec[2+1] = (unsigned long)arg1;                         \
2116      _argvec[2+2] = (unsigned long)arg2;                         \
2117      _argvec[2+3] = (unsigned long)arg3;                         \
2118      _argvec[2+4] = (unsigned long)arg4;                         \
2119      _argvec[2+5] = (unsigned long)arg5;                         \
2120      _argvec[2+6] = (unsigned long)arg6;                         \
2121      __asm__ volatile(                                           \
2122         "mr 11,%1\n\t"                                           \
2123         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2124         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2125         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2126         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2127         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2128         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2129         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2130         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2131         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2132         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2133         "mr 11,%1\n\t"                                           \
2134         "mr %0,3\n\t"                                            \
2135         "ld 2,-16(11)" /* restore tocptr */                      \
2136         : /*out*/   "=r" (_res)                                  \
2137         : /*in*/    "r" (&_argvec[2])                            \
2138         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2139      );                                                          \
2140      lval = (__typeof__(lval)) _res;                             \
2141   } while (0)
2142
2143#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2144                                 arg7)                            \
2145   do {                                                           \
2146      volatile OrigFn        _orig = (orig);                      \
2147      volatile unsigned long _argvec[3+7];                        \
2148      volatile unsigned long _res;                                \
2149      /* _argvec[0] holds current r2 across the call */           \
2150      _argvec[1]   = (unsigned long)_orig.r2;                     \
2151      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2152      _argvec[2+1] = (unsigned long)arg1;                         \
2153      _argvec[2+2] = (unsigned long)arg2;                         \
2154      _argvec[2+3] = (unsigned long)arg3;                         \
2155      _argvec[2+4] = (unsigned long)arg4;                         \
2156      _argvec[2+5] = (unsigned long)arg5;                         \
2157      _argvec[2+6] = (unsigned long)arg6;                         \
2158      _argvec[2+7] = (unsigned long)arg7;                         \
2159      __asm__ volatile(                                           \
2160         "mr 11,%1\n\t"                                           \
2161         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2162         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2163         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2164         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2165         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2166         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2167         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2168         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2169         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2170         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2171         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2172         "mr 11,%1\n\t"                                           \
2173         "mr %0,3\n\t"                                            \
2174         "ld 2,-16(11)" /* restore tocptr */                      \
2175         : /*out*/   "=r" (_res)                                  \
2176         : /*in*/    "r" (&_argvec[2])                            \
2177         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2178      );                                                          \
2179      lval = (__typeof__(lval)) _res;                             \
2180   } while (0)
2181
2182#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2183                                 arg7,arg8)                       \
2184   do {                                                           \
2185      volatile OrigFn        _orig = (orig);                      \
2186      volatile unsigned long _argvec[3+8];                        \
2187      volatile unsigned long _res;                                \
2188      /* _argvec[0] holds current r2 across the call */           \
2189      _argvec[1]   = (unsigned long)_orig.r2;                     \
2190      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2191      _argvec[2+1] = (unsigned long)arg1;                         \
2192      _argvec[2+2] = (unsigned long)arg2;                         \
2193      _argvec[2+3] = (unsigned long)arg3;                         \
2194      _argvec[2+4] = (unsigned long)arg4;                         \
2195      _argvec[2+5] = (unsigned long)arg5;                         \
2196      _argvec[2+6] = (unsigned long)arg6;                         \
2197      _argvec[2+7] = (unsigned long)arg7;                         \
2198      _argvec[2+8] = (unsigned long)arg8;                         \
2199      __asm__ volatile(                                           \
2200         "mr 11,%1\n\t"                                           \
2201         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2202         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2203         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2204         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2205         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2206         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2207         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2208         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2209         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2210         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2211         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2212         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2213         "mr 11,%1\n\t"                                           \
2214         "mr %0,3\n\t"                                            \
2215         "ld 2,-16(11)" /* restore tocptr */                      \
2216         : /*out*/   "=r" (_res)                                  \
2217         : /*in*/    "r" (&_argvec[2])                            \
2218         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2219      );                                                          \
2220      lval = (__typeof__(lval)) _res;                             \
2221   } while (0)
2222
2223#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2224                                 arg7,arg8,arg9)                  \
2225   do {                                                           \
2226      volatile OrigFn        _orig = (orig);                      \
2227      volatile unsigned long _argvec[3+9];                        \
2228      volatile unsigned long _res;                                \
2229      /* _argvec[0] holds current r2 across the call */           \
2230      _argvec[1]   = (unsigned long)_orig.r2;                     \
2231      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2232      _argvec[2+1] = (unsigned long)arg1;                         \
2233      _argvec[2+2] = (unsigned long)arg2;                         \
2234      _argvec[2+3] = (unsigned long)arg3;                         \
2235      _argvec[2+4] = (unsigned long)arg4;                         \
2236      _argvec[2+5] = (unsigned long)arg5;                         \
2237      _argvec[2+6] = (unsigned long)arg6;                         \
2238      _argvec[2+7] = (unsigned long)arg7;                         \
2239      _argvec[2+8] = (unsigned long)arg8;                         \
2240      _argvec[2+9] = (unsigned long)arg9;                         \
2241      __asm__ volatile(                                           \
2242         "mr 11,%1\n\t"                                           \
2243         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2244         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2245         "addi 1,1,-128\n\t"  /* expand stack frame */            \
2246         /* arg9 */                                               \
2247         "ld  3,72(11)\n\t"                                       \
2248         "std 3,112(1)\n\t"                                       \
2249         /* args1-8 */                                            \
2250         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2251         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2252         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2253         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2254         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2255         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2256         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2257         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2258         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2259         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2260         "mr 11,%1\n\t"                                           \
2261         "mr %0,3\n\t"                                            \
2262         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2263         "addi 1,1,128"     /* restore frame */                   \
2264         : /*out*/   "=r" (_res)                                  \
2265         : /*in*/    "r" (&_argvec[2])                            \
2266         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2267      );                                                          \
2268      lval = (__typeof__(lval)) _res;                             \
2269   } while (0)
2270
2271#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2272                                  arg7,arg8,arg9,arg10)           \
2273   do {                                                           \
2274      volatile OrigFn        _orig = (orig);                      \
2275      volatile unsigned long _argvec[3+10];                       \
2276      volatile unsigned long _res;                                \
2277      /* _argvec[0] holds current r2 across the call */           \
2278      _argvec[1]   = (unsigned long)_orig.r2;                     \
2279      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2280      _argvec[2+1] = (unsigned long)arg1;                         \
2281      _argvec[2+2] = (unsigned long)arg2;                         \
2282      _argvec[2+3] = (unsigned long)arg3;                         \
2283      _argvec[2+4] = (unsigned long)arg4;                         \
2284      _argvec[2+5] = (unsigned long)arg5;                         \
2285      _argvec[2+6] = (unsigned long)arg6;                         \
2286      _argvec[2+7] = (unsigned long)arg7;                         \
2287      _argvec[2+8] = (unsigned long)arg8;                         \
2288      _argvec[2+9] = (unsigned long)arg9;                         \
2289      _argvec[2+10] = (unsigned long)arg10;                       \
2290      __asm__ volatile(                                           \
2291         "mr 11,%1\n\t"                                           \
2292         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2293         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2294         "addi 1,1,-128\n\t"  /* expand stack frame */            \
2295         /* arg10 */                                              \
2296         "ld  3,80(11)\n\t"                                       \
2297         "std 3,120(1)\n\t"                                       \
2298         /* arg9 */                                               \
2299         "ld  3,72(11)\n\t"                                       \
2300         "std 3,112(1)\n\t"                                       \
2301         /* args1-8 */                                            \
2302         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2303         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2304         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2305         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2306         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2307         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2308         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2309         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2310         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2311         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2312         "mr 11,%1\n\t"                                           \
2313         "mr %0,3\n\t"                                            \
2314         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2315         "addi 1,1,128"     /* restore frame */                   \
2316         : /*out*/   "=r" (_res)                                  \
2317         : /*in*/    "r" (&_argvec[2])                            \
2318         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2319      );                                                          \
2320      lval = (__typeof__(lval)) _res;                             \
2321   } while (0)
2322
2323#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2324                                  arg7,arg8,arg9,arg10,arg11)     \
2325   do {                                                           \
2326      volatile OrigFn        _orig = (orig);                      \
2327      volatile unsigned long _argvec[3+11];                       \
2328      volatile unsigned long _res;                                \
2329      /* _argvec[0] holds current r2 across the call */           \
2330      _argvec[1]   = (unsigned long)_orig.r2;                     \
2331      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2332      _argvec[2+1] = (unsigned long)arg1;                         \
2333      _argvec[2+2] = (unsigned long)arg2;                         \
2334      _argvec[2+3] = (unsigned long)arg3;                         \
2335      _argvec[2+4] = (unsigned long)arg4;                         \
2336      _argvec[2+5] = (unsigned long)arg5;                         \
2337      _argvec[2+6] = (unsigned long)arg6;                         \
2338      _argvec[2+7] = (unsigned long)arg7;                         \
2339      _argvec[2+8] = (unsigned long)arg8;                         \
2340      _argvec[2+9] = (unsigned long)arg9;                         \
2341      _argvec[2+10] = (unsigned long)arg10;                       \
2342      _argvec[2+11] = (unsigned long)arg11;                       \
2343      __asm__ volatile(                                           \
2344         "mr 11,%1\n\t"                                           \
2345         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2346         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2347         "addi 1,1,-144\n\t"  /* expand stack frame */            \
2348         /* arg11 */                                              \
2349         "ld  3,88(11)\n\t"                                       \
2350         "std 3,128(1)\n\t"                                       \
2351         /* arg10 */                                              \
2352         "ld  3,80(11)\n\t"                                       \
2353         "std 3,120(1)\n\t"                                       \
2354         /* arg9 */                                               \
2355         "ld  3,72(11)\n\t"                                       \
2356         "std 3,112(1)\n\t"                                       \
2357         /* args1-8 */                                            \
2358         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2359         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2360         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2361         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2362         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2363         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2364         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2365         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2366         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2367         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2368         "mr 11,%1\n\t"                                           \
2369         "mr %0,3\n\t"                                            \
2370         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2371         "addi 1,1,144"     /* restore frame */                   \
2372         : /*out*/   "=r" (_res)                                  \
2373         : /*in*/    "r" (&_argvec[2])                            \
2374         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2375      );                                                          \
2376      lval = (__typeof__(lval)) _res;                             \
2377   } while (0)
2378
2379#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2380                                arg7,arg8,arg9,arg10,arg11,arg12) \
2381   do {                                                           \
2382      volatile OrigFn        _orig = (orig);                      \
2383      volatile unsigned long _argvec[3+12];                       \
2384      volatile unsigned long _res;                                \
2385      /* _argvec[0] holds current r2 across the call */           \
2386      _argvec[1]   = (unsigned long)_orig.r2;                     \
2387      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2388      _argvec[2+1] = (unsigned long)arg1;                         \
2389      _argvec[2+2] = (unsigned long)arg2;                         \
2390      _argvec[2+3] = (unsigned long)arg3;                         \
2391      _argvec[2+4] = (unsigned long)arg4;                         \
2392      _argvec[2+5] = (unsigned long)arg5;                         \
2393      _argvec[2+6] = (unsigned long)arg6;                         \
2394      _argvec[2+7] = (unsigned long)arg7;                         \
2395      _argvec[2+8] = (unsigned long)arg8;                         \
2396      _argvec[2+9] = (unsigned long)arg9;                         \
2397      _argvec[2+10] = (unsigned long)arg10;                       \
2398      _argvec[2+11] = (unsigned long)arg11;                       \
2399      _argvec[2+12] = (unsigned long)arg12;                       \
2400      __asm__ volatile(                                           \
2401         "mr 11,%1\n\t"                                           \
2402         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2403         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2404         "addi 1,1,-144\n\t"  /* expand stack frame */            \
2405         /* arg12 */                                              \
2406         "ld  3,96(11)\n\t"                                       \
2407         "std 3,136(1)\n\t"                                       \
2408         /* arg11 */                                              \
2409         "ld  3,88(11)\n\t"                                       \
2410         "std 3,128(1)\n\t"                                       \
2411         /* arg10 */                                              \
2412         "ld  3,80(11)\n\t"                                       \
2413         "std 3,120(1)\n\t"                                       \
2414         /* arg9 */                                               \
2415         "ld  3,72(11)\n\t"                                       \
2416         "std 3,112(1)\n\t"                                       \
2417         /* args1-8 */                                            \
2418         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2419         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2420         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2421         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2422         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2423         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2424         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2425         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2426         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2427         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2428         "mr 11,%1\n\t"                                           \
2429         "mr %0,3\n\t"                                            \
2430         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2431         "addi 1,1,144"     /* restore frame */                   \
2432         : /*out*/   "=r" (_res)                                  \
2433         : /*in*/    "r" (&_argvec[2])                            \
2434         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2435      );                                                          \
2436      lval = (__typeof__(lval)) _res;                             \
2437   } while (0)
2438
2439#endif /* PLAT_ppc64_linux */
2440
2441/* ------------------------ ppc32-aix5 ------------------------- */
2442
2443#if defined(PLAT_ppc32_aix5)
2444
2445/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2446
2447/* These regs are trashed by the hidden call. */
2448#define __CALLER_SAVED_REGS                                       \
2449   "lr", "ctr", "xer",                                            \
2450   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
2451   "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
2452   "r11", "r12", "r13"
2453
2454/* Expand the stack frame, copying enough info that unwinding
2455   still works.  Trashes r3. */
2456
2457#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr)                      \
2458         "addi 1,1,-" #_n_fr "\n\t"                               \
2459         "lwz  3," #_n_fr "(1)\n\t"                               \
2460         "stw  3,0(1)\n\t"
2461
2462#define VG_CONTRACT_FRAME_BY(_n_fr)                               \
2463         "addi 1,1," #_n_fr "\n\t"
2464
2465/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2466   long) == 4. */
2467
2468#define CALL_FN_W_v(lval, orig)                                   \
2469   do {                                                           \
2470      volatile OrigFn        _orig = (orig);                      \
2471      volatile unsigned long _argvec[3+0];                        \
2472      volatile unsigned long _res;                                \
2473      /* _argvec[0] holds current r2 across the call */           \
2474      _argvec[1] = (unsigned long)_orig.r2;                       \
2475      _argvec[2] = (unsigned long)_orig.nraddr;                   \
2476      __asm__ volatile(                                           \
2477         "mr 11,%1\n\t"                                           \
2478         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2479         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2480         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2481         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2482         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2483         "mr 11,%1\n\t"                                           \
2484         "mr %0,3\n\t"                                            \
2485         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2486         VG_CONTRACT_FRAME_BY(512)                                \
2487         : /*out*/   "=r" (_res)                                  \
2488         : /*in*/    "r" (&_argvec[2])                            \
2489         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2490      );                                                          \
2491      lval = (__typeof__(lval)) _res;                             \
2492   } while (0)
2493
2494#define CALL_FN_W_W(lval, orig, arg1)                             \
2495   do {                                                           \
2496      volatile OrigFn        _orig = (orig);                      \
2497      volatile unsigned long _argvec[3+1];                        \
2498      volatile unsigned long _res;                                \
2499      /* _argvec[0] holds current r2 across the call */           \
2500      _argvec[1]   = (unsigned long)_orig.r2;                     \
2501      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2502      _argvec[2+1] = (unsigned long)arg1;                         \
2503      __asm__ volatile(                                           \
2504         "mr 11,%1\n\t"                                           \
2505         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2506         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2507         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2508         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2509         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2510         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2511         "mr 11,%1\n\t"                                           \
2512         "mr %0,3\n\t"                                            \
2513         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2514         VG_CONTRACT_FRAME_BY(512)                                \
2515         : /*out*/   "=r" (_res)                                  \
2516         : /*in*/    "r" (&_argvec[2])                            \
2517         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2518      );                                                          \
2519      lval = (__typeof__(lval)) _res;                             \
2520   } while (0)
2521
2522#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
2523   do {                                                           \
2524      volatile OrigFn        _orig = (orig);                      \
2525      volatile unsigned long _argvec[3+2];                        \
2526      volatile unsigned long _res;                                \
2527      /* _argvec[0] holds current r2 across the call */           \
2528      _argvec[1]   = (unsigned long)_orig.r2;                     \
2529      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2530      _argvec[2+1] = (unsigned long)arg1;                         \
2531      _argvec[2+2] = (unsigned long)arg2;                         \
2532      __asm__ volatile(                                           \
2533         "mr 11,%1\n\t"                                           \
2534         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2535         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2536         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2537         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2538         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2539         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2540         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2541         "mr 11,%1\n\t"                                           \
2542         "mr %0,3\n\t"                                            \
2543         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2544         VG_CONTRACT_FRAME_BY(512)                                \
2545         : /*out*/   "=r" (_res)                                  \
2546         : /*in*/    "r" (&_argvec[2])                            \
2547         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2548      );                                                          \
2549      lval = (__typeof__(lval)) _res;                             \
2550   } while (0)
2551
2552#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2553   do {                                                           \
2554      volatile OrigFn        _orig = (orig);                      \
2555      volatile unsigned long _argvec[3+3];                        \
2556      volatile unsigned long _res;                                \
2557      /* _argvec[0] holds current r2 across the call */           \
2558      _argvec[1]   = (unsigned long)_orig.r2;                     \
2559      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2560      _argvec[2+1] = (unsigned long)arg1;                         \
2561      _argvec[2+2] = (unsigned long)arg2;                         \
2562      _argvec[2+3] = (unsigned long)arg3;                         \
2563      __asm__ volatile(                                           \
2564         "mr 11,%1\n\t"                                           \
2565         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2566         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2567         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2568         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2569         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2570         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2571         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2572         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2573         "mr 11,%1\n\t"                                           \
2574         "mr %0,3\n\t"                                            \
2575         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2576         VG_CONTRACT_FRAME_BY(512)                                \
2577         : /*out*/   "=r" (_res)                                  \
2578         : /*in*/    "r" (&_argvec[2])                            \
2579         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2580      );                                                          \
2581      lval = (__typeof__(lval)) _res;                             \
2582   } while (0)
2583
2584#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2585   do {                                                           \
2586      volatile OrigFn        _orig = (orig);                      \
2587      volatile unsigned long _argvec[3+4];                        \
2588      volatile unsigned long _res;                                \
2589      /* _argvec[0] holds current r2 across the call */           \
2590      _argvec[1]   = (unsigned long)_orig.r2;                     \
2591      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2592      _argvec[2+1] = (unsigned long)arg1;                         \
2593      _argvec[2+2] = (unsigned long)arg2;                         \
2594      _argvec[2+3] = (unsigned long)arg3;                         \
2595      _argvec[2+4] = (unsigned long)arg4;                         \
2596      __asm__ volatile(                                           \
2597         "mr 11,%1\n\t"                                           \
2598         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2599         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2600         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2601         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2602         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2603         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2604         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2605         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2606         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2607         "mr 11,%1\n\t"                                           \
2608         "mr %0,3\n\t"                                            \
2609         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2610         VG_CONTRACT_FRAME_BY(512)                                \
2611         : /*out*/   "=r" (_res)                                  \
2612         : /*in*/    "r" (&_argvec[2])                            \
2613         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2614      );                                                          \
2615      lval = (__typeof__(lval)) _res;                             \
2616   } while (0)
2617
2618#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2619   do {                                                           \
2620      volatile OrigFn        _orig = (orig);                      \
2621      volatile unsigned long _argvec[3+5];                        \
2622      volatile unsigned long _res;                                \
2623      /* _argvec[0] holds current r2 across the call */           \
2624      _argvec[1]   = (unsigned long)_orig.r2;                     \
2625      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2626      _argvec[2+1] = (unsigned long)arg1;                         \
2627      _argvec[2+2] = (unsigned long)arg2;                         \
2628      _argvec[2+3] = (unsigned long)arg3;                         \
2629      _argvec[2+4] = (unsigned long)arg4;                         \
2630      _argvec[2+5] = (unsigned long)arg5;                         \
2631      __asm__ volatile(                                           \
2632         "mr 11,%1\n\t"                                           \
2633         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2634         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2635         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2636         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2637         "lwz  4, 8(11)\n\t" /* arg2->r4 */                       \
2638         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2639         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2640         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2641         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2642         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2643         "mr 11,%1\n\t"                                           \
2644         "mr %0,3\n\t"                                            \
2645         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2646         VG_CONTRACT_FRAME_BY(512)                                \
2647         : /*out*/   "=r" (_res)                                  \
2648         : /*in*/    "r" (&_argvec[2])                            \
2649         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2650      );                                                          \
2651      lval = (__typeof__(lval)) _res;                             \
2652   } while (0)
2653
2654#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2655   do {                                                           \
2656      volatile OrigFn        _orig = (orig);                      \
2657      volatile unsigned long _argvec[3+6];                        \
2658      volatile unsigned long _res;                                \
2659      /* _argvec[0] holds current r2 across the call */           \
2660      _argvec[1]   = (unsigned long)_orig.r2;                     \
2661      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2662      _argvec[2+1] = (unsigned long)arg1;                         \
2663      _argvec[2+2] = (unsigned long)arg2;                         \
2664      _argvec[2+3] = (unsigned long)arg3;                         \
2665      _argvec[2+4] = (unsigned long)arg4;                         \
2666      _argvec[2+5] = (unsigned long)arg5;                         \
2667      _argvec[2+6] = (unsigned long)arg6;                         \
2668      __asm__ volatile(                                           \
2669         "mr 11,%1\n\t"                                           \
2670         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2671         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2672         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2673         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2674         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2675         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2676         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2677         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2678         "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
2679         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2680         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2681         "mr 11,%1\n\t"                                           \
2682         "mr %0,3\n\t"                                            \
2683         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2684         VG_CONTRACT_FRAME_BY(512)                                \
2685         : /*out*/   "=r" (_res)                                  \
2686         : /*in*/    "r" (&_argvec[2])                            \
2687         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2688      );                                                          \
2689      lval = (__typeof__(lval)) _res;                             \
2690   } while (0)
2691
2692#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2693                                 arg7)                            \
2694   do {                                                           \
2695      volatile OrigFn        _orig = (orig);                      \
2696      volatile unsigned long _argvec[3+7];                        \
2697      volatile unsigned long _res;                                \
2698      /* _argvec[0] holds current r2 across the call */           \
2699      _argvec[1]   = (unsigned long)_orig.r2;                     \
2700      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2701      _argvec[2+1] = (unsigned long)arg1;                         \
2702      _argvec[2+2] = (unsigned long)arg2;                         \
2703      _argvec[2+3] = (unsigned long)arg3;                         \
2704      _argvec[2+4] = (unsigned long)arg4;                         \
2705      _argvec[2+5] = (unsigned long)arg5;                         \
2706      _argvec[2+6] = (unsigned long)arg6;                         \
2707      _argvec[2+7] = (unsigned long)arg7;                         \
2708      __asm__ volatile(                                           \
2709         "mr 11,%1\n\t"                                           \
2710         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2711         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2712         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2713         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2714         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2715         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2716         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2717         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2718         "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
2719         "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
2720         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2721         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2722         "mr 11,%1\n\t"                                           \
2723         "mr %0,3\n\t"                                            \
2724         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2725         VG_CONTRACT_FRAME_BY(512)                                \
2726         : /*out*/   "=r" (_res)                                  \
2727         : /*in*/    "r" (&_argvec[2])                            \
2728         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2729      );                                                          \
2730      lval = (__typeof__(lval)) _res;                             \
2731   } while (0)
2732
2733#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2734                                 arg7,arg8)                       \
2735   do {                                                           \
2736      volatile OrigFn        _orig = (orig);                      \
2737      volatile unsigned long _argvec[3+8];                        \
2738      volatile unsigned long _res;                                \
2739      /* _argvec[0] holds current r2 across the call */           \
2740      _argvec[1]   = (unsigned long)_orig.r2;                     \
2741      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2742      _argvec[2+1] = (unsigned long)arg1;                         \
2743      _argvec[2+2] = (unsigned long)arg2;                         \
2744      _argvec[2+3] = (unsigned long)arg3;                         \
2745      _argvec[2+4] = (unsigned long)arg4;                         \
2746      _argvec[2+5] = (unsigned long)arg5;                         \
2747      _argvec[2+6] = (unsigned long)arg6;                         \
2748      _argvec[2+7] = (unsigned long)arg7;                         \
2749      _argvec[2+8] = (unsigned long)arg8;                         \
2750      __asm__ volatile(                                           \
2751         "mr 11,%1\n\t"                                           \
2752         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2753         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2754         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2755         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2756         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2757         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2758         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2759         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2760         "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
2761         "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
2762         "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
2763         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2764         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2765         "mr 11,%1\n\t"                                           \
2766         "mr %0,3\n\t"                                            \
2767         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2768         VG_CONTRACT_FRAME_BY(512)                                \
2769         : /*out*/   "=r" (_res)                                  \
2770         : /*in*/    "r" (&_argvec[2])                            \
2771         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2772      );                                                          \
2773      lval = (__typeof__(lval)) _res;                             \
2774   } while (0)
2775
2776#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2777                                 arg7,arg8,arg9)                  \
2778   do {                                                           \
2779      volatile OrigFn        _orig = (orig);                      \
2780      volatile unsigned long _argvec[3+9];                        \
2781      volatile unsigned long _res;                                \
2782      /* _argvec[0] holds current r2 across the call */           \
2783      _argvec[1]   = (unsigned long)_orig.r2;                     \
2784      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2785      _argvec[2+1] = (unsigned long)arg1;                         \
2786      _argvec[2+2] = (unsigned long)arg2;                         \
2787      _argvec[2+3] = (unsigned long)arg3;                         \
2788      _argvec[2+4] = (unsigned long)arg4;                         \
2789      _argvec[2+5] = (unsigned long)arg5;                         \
2790      _argvec[2+6] = (unsigned long)arg6;                         \
2791      _argvec[2+7] = (unsigned long)arg7;                         \
2792      _argvec[2+8] = (unsigned long)arg8;                         \
2793      _argvec[2+9] = (unsigned long)arg9;                         \
2794      __asm__ volatile(                                           \
2795         "mr 11,%1\n\t"                                           \
2796         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2797         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2798         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2799         VG_EXPAND_FRAME_BY_trashes_r3(64)                        \
2800         /* arg9 */                                               \
2801         "lwz 3,36(11)\n\t"                                       \
2802         "stw 3,56(1)\n\t"                                        \
2803         /* args1-8 */                                            \
2804         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2805         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2806         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2807         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2808         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2809         "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
2810         "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
2811         "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
2812         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2813         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2814         "mr 11,%1\n\t"                                           \
2815         "mr %0,3\n\t"                                            \
2816         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2817         VG_CONTRACT_FRAME_BY(64)                                 \
2818         VG_CONTRACT_FRAME_BY(512)                                \
2819         : /*out*/   "=r" (_res)                                  \
2820         : /*in*/    "r" (&_argvec[2])                            \
2821         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2822      );                                                          \
2823      lval = (__typeof__(lval)) _res;                             \
2824   } while (0)
2825
2826#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2827                                  arg7,arg8,arg9,arg10)           \
2828   do {                                                           \
2829      volatile OrigFn        _orig = (orig);                      \
2830      volatile unsigned long _argvec[3+10];                       \
2831      volatile unsigned long _res;                                \
2832      /* _argvec[0] holds current r2 across the call */           \
2833      _argvec[1]   = (unsigned long)_orig.r2;                     \
2834      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2835      _argvec[2+1] = (unsigned long)arg1;                         \
2836      _argvec[2+2] = (unsigned long)arg2;                         \
2837      _argvec[2+3] = (unsigned long)arg3;                         \
2838      _argvec[2+4] = (unsigned long)arg4;                         \
2839      _argvec[2+5] = (unsigned long)arg5;                         \
2840      _argvec[2+6] = (unsigned long)arg6;                         \
2841      _argvec[2+7] = (unsigned long)arg7;                         \
2842      _argvec[2+8] = (unsigned long)arg8;                         \
2843      _argvec[2+9] = (unsigned long)arg9;                         \
2844      _argvec[2+10] = (unsigned long)arg10;                       \
2845      __asm__ volatile(                                           \
2846         "mr 11,%1\n\t"                                           \
2847         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2848         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2849         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2850         VG_EXPAND_FRAME_BY_trashes_r3(64)                        \
2851         /* arg10 */                                              \
2852         "lwz 3,40(11)\n\t"                                       \
2853         "stw 3,60(1)\n\t"                                        \
2854         /* arg9 */                                               \
2855         "lwz 3,36(11)\n\t"                                       \
2856         "stw 3,56(1)\n\t"                                        \
2857         /* args1-8 */                                            \
2858         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2859         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2860         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2861         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2862         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2863         "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
2864         "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
2865         "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
2866         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2867         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2868         "mr 11,%1\n\t"                                           \
2869         "mr %0,3\n\t"                                            \
2870         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2871         VG_CONTRACT_FRAME_BY(64)                                 \
2872         VG_CONTRACT_FRAME_BY(512)                                \
2873         : /*out*/   "=r" (_res)                                  \
2874         : /*in*/    "r" (&_argvec[2])                            \
2875         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2876      );                                                          \
2877      lval = (__typeof__(lval)) _res;                             \
2878   } while (0)
2879
2880#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2881                                  arg7,arg8,arg9,arg10,arg11)     \
2882   do {                                                           \
2883      volatile OrigFn        _orig = (orig);                      \
2884      volatile unsigned long _argvec[3+11];                       \
2885      volatile unsigned long _res;                                \
2886      /* _argvec[0] holds current r2 across the call */           \
2887      _argvec[1]   = (unsigned long)_orig.r2;                     \
2888      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2889      _argvec[2+1] = (unsigned long)arg1;                         \
2890      _argvec[2+2] = (unsigned long)arg2;                         \
2891      _argvec[2+3] = (unsigned long)arg3;                         \
2892      _argvec[2+4] = (unsigned long)arg4;                         \
2893      _argvec[2+5] = (unsigned long)arg5;                         \
2894      _argvec[2+6] = (unsigned long)arg6;                         \
2895      _argvec[2+7] = (unsigned long)arg7;                         \
2896      _argvec[2+8] = (unsigned long)arg8;                         \
2897      _argvec[2+9] = (unsigned long)arg9;                         \
2898      _argvec[2+10] = (unsigned long)arg10;                       \
2899      _argvec[2+11] = (unsigned long)arg11;                       \
2900      __asm__ volatile(                                           \
2901         "mr 11,%1\n\t"                                           \
2902         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2903         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2904         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2905         VG_EXPAND_FRAME_BY_trashes_r3(72)                        \
2906         /* arg11 */                                              \
2907         "lwz 3,44(11)\n\t"                                       \
2908         "stw 3,64(1)\n\t"                                        \
2909         /* arg10 */                                              \
2910         "lwz 3,40(11)\n\t"                                       \
2911         "stw 3,60(1)\n\t"                                        \
2912         /* arg9 */                                               \
2913         "lwz 3,36(11)\n\t"                                       \
2914         "stw 3,56(1)\n\t"                                        \
2915         /* args1-8 */                                            \
2916         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2917         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2918         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2919         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2920         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2921         "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
2922         "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
2923         "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
2924         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2925         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2926         "mr 11,%1\n\t"                                           \
2927         "mr %0,3\n\t"                                            \
2928         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2929         VG_CONTRACT_FRAME_BY(72)                                 \
2930         VG_CONTRACT_FRAME_BY(512)                                \
2931         : /*out*/   "=r" (_res)                                  \
2932         : /*in*/    "r" (&_argvec[2])                            \
2933         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2934      );                                                          \
2935      lval = (__typeof__(lval)) _res;                             \
2936   } while (0)
2937
2938#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2939                                arg7,arg8,arg9,arg10,arg11,arg12) \
2940   do {                                                           \
2941      volatile OrigFn        _orig = (orig);                      \
2942      volatile unsigned long _argvec[3+12];                       \
2943      volatile unsigned long _res;                                \
2944      /* _argvec[0] holds current r2 across the call */           \
2945      _argvec[1]   = (unsigned long)_orig.r2;                     \
2946      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2947      _argvec[2+1] = (unsigned long)arg1;                         \
2948      _argvec[2+2] = (unsigned long)arg2;                         \
2949      _argvec[2+3] = (unsigned long)arg3;                         \
2950      _argvec[2+4] = (unsigned long)arg4;                         \
2951      _argvec[2+5] = (unsigned long)arg5;                         \
2952      _argvec[2+6] = (unsigned long)arg6;                         \
2953      _argvec[2+7] = (unsigned long)arg7;                         \
2954      _argvec[2+8] = (unsigned long)arg8;                         \
2955      _argvec[2+9] = (unsigned long)arg9;                         \
2956      _argvec[2+10] = (unsigned long)arg10;                       \
2957      _argvec[2+11] = (unsigned long)arg11;                       \
2958      _argvec[2+12] = (unsigned long)arg12;                       \
2959      __asm__ volatile(                                           \
2960         "mr 11,%1\n\t"                                           \
2961         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
2962         "stw  2,-8(11)\n\t"  /* save tocptr */                   \
2963         "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
2964         VG_EXPAND_FRAME_BY_trashes_r3(72)                        \
2965         /* arg12 */                                              \
2966         "lwz 3,48(11)\n\t"                                       \
2967         "stw 3,68(1)\n\t"                                        \
2968         /* arg11 */                                              \
2969         "lwz 3,44(11)\n\t"                                       \
2970         "stw 3,64(1)\n\t"                                        \
2971         /* arg10 */                                              \
2972         "lwz 3,40(11)\n\t"                                       \
2973         "stw 3,60(1)\n\t"                                        \
2974         /* arg9 */                                               \
2975         "lwz 3,36(11)\n\t"                                       \
2976         "stw 3,56(1)\n\t"                                        \
2977         /* args1-8 */                                            \
2978         "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
2979         "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
2980         "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
2981         "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
2982         "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
2983         "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
2984         "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
2985         "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
2986         "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
2987         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2988         "mr 11,%1\n\t"                                           \
2989         "mr %0,3\n\t"                                            \
2990         "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
2991         VG_CONTRACT_FRAME_BY(72)                                 \
2992         VG_CONTRACT_FRAME_BY(512)                                \
2993         : /*out*/   "=r" (_res)                                  \
2994         : /*in*/    "r" (&_argvec[2])                            \
2995         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
2996      );                                                          \
2997      lval = (__typeof__(lval)) _res;                             \
2998   } while (0)
2999
3000#endif /* PLAT_ppc32_aix5 */
3001
3002/* ------------------------ ppc64-aix5 ------------------------- */
3003
3004#if defined(PLAT_ppc64_aix5)
3005
3006/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3007
3008/* These regs are trashed by the hidden call. */
3009#define __CALLER_SAVED_REGS                                       \
3010   "lr", "ctr", "xer",                                            \
3011   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
3012   "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
3013   "r11", "r12", "r13"
3014
3015/* Expand the stack frame, copying enough info that unwinding
3016   still works.  Trashes r3. */
3017
3018#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr)                      \
3019         "addi 1,1,-" #_n_fr "\n\t"                               \
3020         "ld   3," #_n_fr "(1)\n\t"                               \
3021         "std  3,0(1)\n\t"
3022
3023#define VG_CONTRACT_FRAME_BY(_n_fr)                               \
3024         "addi 1,1," #_n_fr "\n\t"
3025
3026/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3027   long) == 8. */
3028
3029#define CALL_FN_W_v(lval, orig)                                   \
3030   do {                                                           \
3031      volatile OrigFn        _orig = (orig);                      \
3032      volatile unsigned long _argvec[3+0];                        \
3033      volatile unsigned long _res;                                \
3034      /* _argvec[0] holds current r2 across the call */           \
3035      _argvec[1] = (unsigned long)_orig.r2;                       \
3036      _argvec[2] = (unsigned long)_orig.nraddr;                   \
3037      __asm__ volatile(                                           \
3038         "mr 11,%1\n\t"                                           \
3039         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3040         "std  2,-16(11)\n\t" /* save tocptr */                   \
3041         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3042         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3043         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3044         "mr 11,%1\n\t"                                           \
3045         "mr %0,3\n\t"                                            \
3046         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3047         VG_CONTRACT_FRAME_BY(512)                                \
3048         : /*out*/   "=r" (_res)                                  \
3049         : /*in*/    "r" (&_argvec[2])                            \
3050         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3051      );                                                          \
3052      lval = (__typeof__(lval)) _res;                             \
3053   } while (0)
3054
3055#define CALL_FN_W_W(lval, orig, arg1)                             \
3056   do {                                                           \
3057      volatile OrigFn        _orig = (orig);                      \
3058      volatile unsigned long _argvec[3+1];                        \
3059      volatile unsigned long _res;                                \
3060      /* _argvec[0] holds current r2 across the call */           \
3061      _argvec[1]   = (unsigned long)_orig.r2;                     \
3062      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3063      _argvec[2+1] = (unsigned long)arg1;                         \
3064      __asm__ volatile(                                           \
3065         "mr 11,%1\n\t"                                           \
3066         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3067         "std  2,-16(11)\n\t" /* save tocptr */                   \
3068         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3069         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3070         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3071         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3072         "mr 11,%1\n\t"                                           \
3073         "mr %0,3\n\t"                                            \
3074         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3075         VG_CONTRACT_FRAME_BY(512)                                \
3076         : /*out*/   "=r" (_res)                                  \
3077         : /*in*/    "r" (&_argvec[2])                            \
3078         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3079      );                                                          \
3080      lval = (__typeof__(lval)) _res;                             \
3081   } while (0)
3082
3083#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
3084   do {                                                           \
3085      volatile OrigFn        _orig = (orig);                      \
3086      volatile unsigned long _argvec[3+2];                        \
3087      volatile unsigned long _res;                                \
3088      /* _argvec[0] holds current r2 across the call */           \
3089      _argvec[1]   = (unsigned long)_orig.r2;                     \
3090      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3091      _argvec[2+1] = (unsigned long)arg1;                         \
3092      _argvec[2+2] = (unsigned long)arg2;                         \
3093      __asm__ volatile(                                           \
3094         "mr 11,%1\n\t"                                           \
3095         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3096         "std  2,-16(11)\n\t" /* save tocptr */                   \
3097         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3098         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3099         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3100         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3101         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3102         "mr 11,%1\n\t"                                           \
3103         "mr %0,3\n\t"                                            \
3104         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3105         VG_CONTRACT_FRAME_BY(512)                                \
3106         : /*out*/   "=r" (_res)                                  \
3107         : /*in*/    "r" (&_argvec[2])                            \
3108         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3109      );                                                          \
3110      lval = (__typeof__(lval)) _res;                             \
3111   } while (0)
3112
3113#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
3114   do {                                                           \
3115      volatile OrigFn        _orig = (orig);                      \
3116      volatile unsigned long _argvec[3+3];                        \
3117      volatile unsigned long _res;                                \
3118      /* _argvec[0] holds current r2 across the call */           \
3119      _argvec[1]   = (unsigned long)_orig.r2;                     \
3120      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3121      _argvec[2+1] = (unsigned long)arg1;                         \
3122      _argvec[2+2] = (unsigned long)arg2;                         \
3123      _argvec[2+3] = (unsigned long)arg3;                         \
3124      __asm__ volatile(                                           \
3125         "mr 11,%1\n\t"                                           \
3126         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3127         "std  2,-16(11)\n\t" /* save tocptr */                   \
3128         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3129         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3130         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3131         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3132         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3133         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3134         "mr 11,%1\n\t"                                           \
3135         "mr %0,3\n\t"                                            \
3136         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3137         VG_CONTRACT_FRAME_BY(512)                                \
3138         : /*out*/   "=r" (_res)                                  \
3139         : /*in*/    "r" (&_argvec[2])                            \
3140         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3141      );                                                          \
3142      lval = (__typeof__(lval)) _res;                             \
3143   } while (0)
3144
3145#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
3146   do {                                                           \
3147      volatile OrigFn        _orig = (orig);                      \
3148      volatile unsigned long _argvec[3+4];                        \
3149      volatile unsigned long _res;                                \
3150      /* _argvec[0] holds current r2 across the call */           \
3151      _argvec[1]   = (unsigned long)_orig.r2;                     \
3152      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3153      _argvec[2+1] = (unsigned long)arg1;                         \
3154      _argvec[2+2] = (unsigned long)arg2;                         \
3155      _argvec[2+3] = (unsigned long)arg3;                         \
3156      _argvec[2+4] = (unsigned long)arg4;                         \
3157      __asm__ volatile(                                           \
3158         "mr 11,%1\n\t"                                           \
3159         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3160         "std  2,-16(11)\n\t" /* save tocptr */                   \
3161         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3162         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3163         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3164         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3165         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3166         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3167         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3168         "mr 11,%1\n\t"                                           \
3169         "mr %0,3\n\t"                                            \
3170         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3171         VG_CONTRACT_FRAME_BY(512)                                \
3172         : /*out*/   "=r" (_res)                                  \
3173         : /*in*/    "r" (&_argvec[2])                            \
3174         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3175      );                                                          \
3176      lval = (__typeof__(lval)) _res;                             \
3177   } while (0)
3178
3179#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
3180   do {                                                           \
3181      volatile OrigFn        _orig = (orig);                      \
3182      volatile unsigned long _argvec[3+5];                        \
3183      volatile unsigned long _res;                                \
3184      /* _argvec[0] holds current r2 across the call */           \
3185      _argvec[1]   = (unsigned long)_orig.r2;                     \
3186      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3187      _argvec[2+1] = (unsigned long)arg1;                         \
3188      _argvec[2+2] = (unsigned long)arg2;                         \
3189      _argvec[2+3] = (unsigned long)arg3;                         \
3190      _argvec[2+4] = (unsigned long)arg4;                         \
3191      _argvec[2+5] = (unsigned long)arg5;                         \
3192      __asm__ volatile(                                           \
3193         "mr 11,%1\n\t"                                           \
3194         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3195         "std  2,-16(11)\n\t" /* save tocptr */                   \
3196         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3197         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3198         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3199         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3200         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3201         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3202         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3203         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3204         "mr 11,%1\n\t"                                           \
3205         "mr %0,3\n\t"                                            \
3206         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3207         VG_CONTRACT_FRAME_BY(512)                                \
3208         : /*out*/   "=r" (_res)                                  \
3209         : /*in*/    "r" (&_argvec[2])                            \
3210         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3211      );                                                          \
3212      lval = (__typeof__(lval)) _res;                             \
3213   } while (0)
3214
3215#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
3216   do {                                                           \
3217      volatile OrigFn        _orig = (orig);                      \
3218      volatile unsigned long _argvec[3+6];                        \
3219      volatile unsigned long _res;                                \
3220      /* _argvec[0] holds current r2 across the call */           \
3221      _argvec[1]   = (unsigned long)_orig.r2;                     \
3222      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3223      _argvec[2+1] = (unsigned long)arg1;                         \
3224      _argvec[2+2] = (unsigned long)arg2;                         \
3225      _argvec[2+3] = (unsigned long)arg3;                         \
3226      _argvec[2+4] = (unsigned long)arg4;                         \
3227      _argvec[2+5] = (unsigned long)arg5;                         \
3228      _argvec[2+6] = (unsigned long)arg6;                         \
3229      __asm__ volatile(                                           \
3230         "mr 11,%1\n\t"                                           \
3231         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3232         "std  2,-16(11)\n\t" /* save tocptr */                   \
3233         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3234         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3235         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3236         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3237         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3238         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3239         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3240         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3241         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3242         "mr 11,%1\n\t"                                           \
3243         "mr %0,3\n\t"                                            \
3244         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3245         VG_CONTRACT_FRAME_BY(512)                                \
3246         : /*out*/   "=r" (_res)                                  \
3247         : /*in*/    "r" (&_argvec[2])                            \
3248         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3249      );                                                          \
3250      lval = (__typeof__(lval)) _res;                             \
3251   } while (0)
3252
3253#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3254                                 arg7)                            \
3255   do {                                                           \
3256      volatile OrigFn        _orig = (orig);                      \
3257      volatile unsigned long _argvec[3+7];                        \
3258      volatile unsigned long _res;                                \
3259      /* _argvec[0] holds current r2 across the call */           \
3260      _argvec[1]   = (unsigned long)_orig.r2;                     \
3261      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3262      _argvec[2+1] = (unsigned long)arg1;                         \
3263      _argvec[2+2] = (unsigned long)arg2;                         \
3264      _argvec[2+3] = (unsigned long)arg3;                         \
3265      _argvec[2+4] = (unsigned long)arg4;                         \
3266      _argvec[2+5] = (unsigned long)arg5;                         \
3267      _argvec[2+6] = (unsigned long)arg6;                         \
3268      _argvec[2+7] = (unsigned long)arg7;                         \
3269      __asm__ volatile(                                           \
3270         "mr 11,%1\n\t"                                           \
3271         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3272         "std  2,-16(11)\n\t" /* save tocptr */                   \
3273         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3274         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3275         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3276         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3277         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3278         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3279         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3280         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3281         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3282         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3283         "mr 11,%1\n\t"                                           \
3284         "mr %0,3\n\t"                                            \
3285         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3286         VG_CONTRACT_FRAME_BY(512)                                \
3287         : /*out*/   "=r" (_res)                                  \
3288         : /*in*/    "r" (&_argvec[2])                            \
3289         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3290      );                                                          \
3291      lval = (__typeof__(lval)) _res;                             \
3292   } while (0)
3293
3294#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3295                                 arg7,arg8)                       \
3296   do {                                                           \
3297      volatile OrigFn        _orig = (orig);                      \
3298      volatile unsigned long _argvec[3+8];                        \
3299      volatile unsigned long _res;                                \
3300      /* _argvec[0] holds current r2 across the call */           \
3301      _argvec[1]   = (unsigned long)_orig.r2;                     \
3302      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3303      _argvec[2+1] = (unsigned long)arg1;                         \
3304      _argvec[2+2] = (unsigned long)arg2;                         \
3305      _argvec[2+3] = (unsigned long)arg3;                         \
3306      _argvec[2+4] = (unsigned long)arg4;                         \
3307      _argvec[2+5] = (unsigned long)arg5;                         \
3308      _argvec[2+6] = (unsigned long)arg6;                         \
3309      _argvec[2+7] = (unsigned long)arg7;                         \
3310      _argvec[2+8] = (unsigned long)arg8;                         \
3311      __asm__ volatile(                                           \
3312         "mr 11,%1\n\t"                                           \
3313         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3314         "std  2,-16(11)\n\t" /* save tocptr */                   \
3315         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3316         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3317         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3318         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3319         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3320         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3321         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3322         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3323         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3324         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3325         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3326         "mr 11,%1\n\t"                                           \
3327         "mr %0,3\n\t"                                            \
3328         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3329         VG_CONTRACT_FRAME_BY(512)                                \
3330         : /*out*/   "=r" (_res)                                  \
3331         : /*in*/    "r" (&_argvec[2])                            \
3332         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3333      );                                                          \
3334      lval = (__typeof__(lval)) _res;                             \
3335   } while (0)
3336
3337#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3338                                 arg7,arg8,arg9)                  \
3339   do {                                                           \
3340      volatile OrigFn        _orig = (orig);                      \
3341      volatile unsigned long _argvec[3+9];                        \
3342      volatile unsigned long _res;                                \
3343      /* _argvec[0] holds current r2 across the call */           \
3344      _argvec[1]   = (unsigned long)_orig.r2;                     \
3345      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3346      _argvec[2+1] = (unsigned long)arg1;                         \
3347      _argvec[2+2] = (unsigned long)arg2;                         \
3348      _argvec[2+3] = (unsigned long)arg3;                         \
3349      _argvec[2+4] = (unsigned long)arg4;                         \
3350      _argvec[2+5] = (unsigned long)arg5;                         \
3351      _argvec[2+6] = (unsigned long)arg6;                         \
3352      _argvec[2+7] = (unsigned long)arg7;                         \
3353      _argvec[2+8] = (unsigned long)arg8;                         \
3354      _argvec[2+9] = (unsigned long)arg9;                         \
3355      __asm__ volatile(                                           \
3356         "mr 11,%1\n\t"                                           \
3357         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3358         "std  2,-16(11)\n\t" /* save tocptr */                   \
3359         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3360         VG_EXPAND_FRAME_BY_trashes_r3(128)                       \
3361         /* arg9 */                                               \
3362         "ld  3,72(11)\n\t"                                       \
3363         "std 3,112(1)\n\t"                                       \
3364         /* args1-8 */                                            \
3365         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3366         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3367         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3368         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3369         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3370         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3371         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3372         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3373         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3374         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3375         "mr 11,%1\n\t"                                           \
3376         "mr %0,3\n\t"                                            \
3377         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3378         VG_CONTRACT_FRAME_BY(128)                                \
3379         VG_CONTRACT_FRAME_BY(512)                                \
3380         : /*out*/   "=r" (_res)                                  \
3381         : /*in*/    "r" (&_argvec[2])                            \
3382         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3383      );                                                          \
3384      lval = (__typeof__(lval)) _res;                             \
3385   } while (0)
3386
3387#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3388                                  arg7,arg8,arg9,arg10)           \
3389   do {                                                           \
3390      volatile OrigFn        _orig = (orig);                      \
3391      volatile unsigned long _argvec[3+10];                       \
3392      volatile unsigned long _res;                                \
3393      /* _argvec[0] holds current r2 across the call */           \
3394      _argvec[1]   = (unsigned long)_orig.r2;                     \
3395      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3396      _argvec[2+1] = (unsigned long)arg1;                         \
3397      _argvec[2+2] = (unsigned long)arg2;                         \
3398      _argvec[2+3] = (unsigned long)arg3;                         \
3399      _argvec[2+4] = (unsigned long)arg4;                         \
3400      _argvec[2+5] = (unsigned long)arg5;                         \
3401      _argvec[2+6] = (unsigned long)arg6;                         \
3402      _argvec[2+7] = (unsigned long)arg7;                         \
3403      _argvec[2+8] = (unsigned long)arg8;                         \
3404      _argvec[2+9] = (unsigned long)arg9;                         \
3405      _argvec[2+10] = (unsigned long)arg10;                       \
3406      __asm__ volatile(                                           \
3407         "mr 11,%1\n\t"                                           \
3408         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3409         "std  2,-16(11)\n\t" /* save tocptr */                   \
3410         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3411         VG_EXPAND_FRAME_BY_trashes_r3(128)                       \
3412         /* arg10 */                                              \
3413         "ld  3,80(11)\n\t"                                       \
3414         "std 3,120(1)\n\t"                                       \
3415         /* arg9 */                                               \
3416         "ld  3,72(11)\n\t"                                       \
3417         "std 3,112(1)\n\t"                                       \
3418         /* args1-8 */                                            \
3419         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3420         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3421         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3422         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3423         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3424         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3425         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3426         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3427         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3428         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3429         "mr 11,%1\n\t"                                           \
3430         "mr %0,3\n\t"                                            \
3431         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3432         VG_CONTRACT_FRAME_BY(128)                                \
3433         VG_CONTRACT_FRAME_BY(512)                                \
3434         : /*out*/   "=r" (_res)                                  \
3435         : /*in*/    "r" (&_argvec[2])                            \
3436         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3437      );                                                          \
3438      lval = (__typeof__(lval)) _res;                             \
3439   } while (0)
3440
3441#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3442                                  arg7,arg8,arg9,arg10,arg11)     \
3443   do {                                                           \
3444      volatile OrigFn        _orig = (orig);                      \
3445      volatile unsigned long _argvec[3+11];                       \
3446      volatile unsigned long _res;                                \
3447      /* _argvec[0] holds current r2 across the call */           \
3448      _argvec[1]   = (unsigned long)_orig.r2;                     \
3449      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3450      _argvec[2+1] = (unsigned long)arg1;                         \
3451      _argvec[2+2] = (unsigned long)arg2;                         \
3452      _argvec[2+3] = (unsigned long)arg3;                         \
3453      _argvec[2+4] = (unsigned long)arg4;                         \
3454      _argvec[2+5] = (unsigned long)arg5;                         \
3455      _argvec[2+6] = (unsigned long)arg6;                         \
3456      _argvec[2+7] = (unsigned long)arg7;                         \
3457      _argvec[2+8] = (unsigned long)arg8;                         \
3458      _argvec[2+9] = (unsigned long)arg9;                         \
3459      _argvec[2+10] = (unsigned long)arg10;                       \
3460      _argvec[2+11] = (unsigned long)arg11;                       \
3461      __asm__ volatile(                                           \
3462         "mr 11,%1\n\t"                                           \
3463         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3464         "std  2,-16(11)\n\t" /* save tocptr */                   \
3465         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3466         VG_EXPAND_FRAME_BY_trashes_r3(144)                       \
3467         /* arg11 */                                              \
3468         "ld  3,88(11)\n\t"                                       \
3469         "std 3,128(1)\n\t"                                       \
3470         /* arg10 */                                              \
3471         "ld  3,80(11)\n\t"                                       \
3472         "std 3,120(1)\n\t"                                       \
3473         /* arg9 */                                               \
3474         "ld  3,72(11)\n\t"                                       \
3475         "std 3,112(1)\n\t"                                       \
3476         /* args1-8 */                                            \
3477         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3478         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3479         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3480         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3481         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3482         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3483         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3484         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3485         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3486         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3487         "mr 11,%1\n\t"                                           \
3488         "mr %0,3\n\t"                                            \
3489         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3490         VG_CONTRACT_FRAME_BY(144)                                \
3491         VG_CONTRACT_FRAME_BY(512)                                \
3492         : /*out*/   "=r" (_res)                                  \
3493         : /*in*/    "r" (&_argvec[2])                            \
3494         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3495      );                                                          \
3496      lval = (__typeof__(lval)) _res;                             \
3497   } while (0)
3498
3499#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3500                                arg7,arg8,arg9,arg10,arg11,arg12) \
3501   do {                                                           \
3502      volatile OrigFn        _orig = (orig);                      \
3503      volatile unsigned long _argvec[3+12];                       \
3504      volatile unsigned long _res;                                \
3505      /* _argvec[0] holds current r2 across the call */           \
3506      _argvec[1]   = (unsigned long)_orig.r2;                     \
3507      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3508      _argvec[2+1] = (unsigned long)arg1;                         \
3509      _argvec[2+2] = (unsigned long)arg2;                         \
3510      _argvec[2+3] = (unsigned long)arg3;                         \
3511      _argvec[2+4] = (unsigned long)arg4;                         \
3512      _argvec[2+5] = (unsigned long)arg5;                         \
3513      _argvec[2+6] = (unsigned long)arg6;                         \
3514      _argvec[2+7] = (unsigned long)arg7;                         \
3515      _argvec[2+8] = (unsigned long)arg8;                         \
3516      _argvec[2+9] = (unsigned long)arg9;                         \
3517      _argvec[2+10] = (unsigned long)arg10;                       \
3518      _argvec[2+11] = (unsigned long)arg11;                       \
3519      _argvec[2+12] = (unsigned long)arg12;                       \
3520      __asm__ volatile(                                           \
3521         "mr 11,%1\n\t"                                           \
3522         VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
3523         "std  2,-16(11)\n\t" /* save tocptr */                   \
3524         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3525         VG_EXPAND_FRAME_BY_trashes_r3(144)                       \
3526         /* arg12 */                                              \
3527         "ld  3,96(11)\n\t"                                       \
3528         "std 3,136(1)\n\t"                                       \
3529         /* arg11 */                                              \
3530         "ld  3,88(11)\n\t"                                       \
3531         "std 3,128(1)\n\t"                                       \
3532         /* arg10 */                                              \
3533         "ld  3,80(11)\n\t"                                       \
3534         "std 3,120(1)\n\t"                                       \
3535         /* arg9 */                                               \
3536         "ld  3,72(11)\n\t"                                       \
3537         "std 3,112(1)\n\t"                                       \
3538         /* args1-8 */                                            \
3539         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3540         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3541         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3542         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3543         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3544         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3545         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3546         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3547         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3548         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3549         "mr 11,%1\n\t"                                           \
3550         "mr %0,3\n\t"                                            \
3551         "ld  2,-16(11)\n\t" /* restore tocptr */                 \
3552         VG_CONTRACT_FRAME_BY(144)                                \
3553         VG_CONTRACT_FRAME_BY(512)                                \
3554         : /*out*/   "=r" (_res)                                  \
3555         : /*in*/    "r" (&_argvec[2])                            \
3556         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
3557      );                                                          \
3558      lval = (__typeof__(lval)) _res;                             \
3559   } while (0)
3560
3561#endif /* PLAT_ppc64_aix5 */
3562
3563
3564/* ------------------------------------------------------------------ */
3565/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
3566/*                                                                    */
3567/* ------------------------------------------------------------------ */
3568
3569/* Some request codes.  There are many more of these, but most are not
3570   exposed to end-user view.  These are the public ones, all of the
3571   form 0x1000 + small_number.
3572
3573   Core ones are in the range 0x00000000--0x0000ffff.  The non-public
3574   ones start at 0x2000.
3575*/
3576
3577/* These macros are used by tools -- they must be public, but don't
3578   embed them into other programs. */
3579#define VG_USERREQ_TOOL_BASE(a,b) \
3580   ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
3581#define VG_IS_TOOL_USERREQ(a, b, v) \
3582   (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
3583
3584/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3585   This enum comprises an ABI exported by Valgrind to programs
3586   which use client requests.  DO NOT CHANGE THE ORDER OF THESE
3587   ENTRIES, NOR DELETE ANY -- add new ones at the end. */
3588typedef
3589   enum { VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
3590          VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
3591
3592          /* These allow any function to be called from the simulated
3593             CPU but run on the real CPU.  Nb: the first arg passed to
3594             the function is always the ThreadId of the running
3595             thread!  So CLIENT_CALL0 actually requires a 1 arg
3596             function, etc. */
3597          VG_USERREQ__CLIENT_CALL0 = 0x1101,
3598          VG_USERREQ__CLIENT_CALL1 = 0x1102,
3599          VG_USERREQ__CLIENT_CALL2 = 0x1103,
3600          VG_USERREQ__CLIENT_CALL3 = 0x1104,
3601
3602          /* Can be useful in regression testing suites -- eg. can
3603             send Valgrind's output to /dev/null and still count
3604             errors. */
3605          VG_USERREQ__COUNT_ERRORS = 0x1201,
3606
3607          /* These are useful and can be interpreted by any tool that
3608             tracks malloc() et al, by using vg_replace_malloc.c. */
3609          VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
3610          VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
3611          /* Memory pool support. */
3612          VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
3613          VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
3614          VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
3615          VG_USERREQ__MEMPOOL_FREE     = 0x1306,
3616          VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
3617          VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
3618          VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
3619          VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
3620
3621          /* Allow printfs to valgrind log. */
3622          VG_USERREQ__PRINTF           = 0x1401,
3623          VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
3624
3625          /* Stack support. */
3626          VG_USERREQ__STACK_REGISTER   = 0x1501,
3627          VG_USERREQ__STACK_DEREGISTER = 0x1502,
3628          VG_USERREQ__STACK_CHANGE     = 0x1503,
3629
3630          /* Wine support */
3631          VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
3632   } Vg_ClientRequest;
3633
3634#if !defined(__GNUC__)
3635#  define __extension__ /* */
3636#endif
3637
3638/* Returns the number of Valgrinds this code is running under.  That
3639   is, 0 if running natively, 1 if running under Valgrind, 2 if
3640   running under Valgrind which is running under another Valgrind,
3641   etc. */
3642#define RUNNING_ON_VALGRIND  __extension__                        \
3643   ({unsigned int _qzz_res;                                       \
3644    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */,          \
3645                               VG_USERREQ__RUNNING_ON_VALGRIND,   \
3646                               0, 0, 0, 0, 0);                    \
3647    _qzz_res;                                                     \
3648   })
3649
3650
3651/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3652   _qzz_len - 1].  Useful if you are debugging a JITter or some such,
3653   since it provides a way to make sure valgrind will retranslate the
3654   invalidated area.  Returns no value. */
3655#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len)         \
3656   {unsigned int _qzz_res;                                        \
3657    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3658                               VG_USERREQ__DISCARD_TRANSLATIONS,  \
3659                               _qzz_addr, _qzz_len, 0, 0, 0);     \
3660   }
3661
3662
3663/* These requests are for getting Valgrind itself to print something.
3664   Possibly with a backtrace.  This is a really ugly hack. */
3665
3666#if defined(NVALGRIND)
3667
3668#  define VALGRIND_PRINTF(...)
3669#  define VALGRIND_PRINTF_BACKTRACE(...)
3670
3671#else /* NVALGRIND */
3672
3673/* Modern GCC will optimize the static routine out if unused,
3674   and unused attribute will shut down warnings about it.  */
3675static int VALGRIND_PRINTF(const char *format, ...)
3676   __attribute__((format(__printf__, 1, 2), __unused__));
3677static int
3678VALGRIND_PRINTF(const char *format, ...)
3679{
3680   unsigned long _qzz_res;
3681   va_list vargs;
3682   va_start(vargs, format);
3683   VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
3684                              (unsigned long)format, (unsigned long)vargs,
3685                              0, 0, 0);
3686   va_end(vargs);
3687   return (int)_qzz_res;
3688}
3689
3690static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3691   __attribute__((format(__printf__, 1, 2), __unused__));
3692static int
3693VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3694{
3695   unsigned long _qzz_res;
3696   va_list vargs;
3697   va_start(vargs, format);
3698   VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
3699                              (unsigned long)format, (unsigned long)vargs,
3700                              0, 0, 0);
3701   va_end(vargs);
3702   return (int)_qzz_res;
3703}
3704
3705#endif /* NVALGRIND */
3706
3707
3708/* These requests allow control to move from the simulated CPU to the
3709   real CPU, calling an arbitary function.
3710
3711   Note that the current ThreadId is inserted as the first argument.
3712   So this call:
3713
3714     VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3715
3716   requires f to have this signature:
3717
3718     Word f(Word tid, Word arg1, Word arg2)
3719
3720   where "Word" is a word-sized type.
3721
3722   Note that these client requests are not entirely reliable.  For example,
3723   if you call a function with them that subsequently calls printf(),
3724   there's a high chance Valgrind will crash.  Generally, your prospects of
3725   these working are made higher if the called function does not refer to
3726   any global variables, and does not refer to any libc or other functions
3727   (printf et al).  Any kind of entanglement with libc or dynamic linking is
3728   likely to have a bad outcome, for tricky reasons which we've grappled
3729   with a lot in the past.
3730*/
3731#define VALGRIND_NON_SIMD_CALL0(_qyy_fn)                          \
3732   __extension__                                                  \
3733   ({unsigned long _qyy_res;                                      \
3734    VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
3735                               VG_USERREQ__CLIENT_CALL0,          \
3736                               _qyy_fn,                           \
3737                               0, 0, 0, 0);                       \
3738    _qyy_res;                                                     \
3739   })
3740
3741#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1)               \
3742   __extension__                                                  \
3743   ({unsigned long _qyy_res;                                      \
3744    VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
3745                               VG_USERREQ__CLIENT_CALL1,          \
3746                               _qyy_fn,                           \
3747                               _qyy_arg1, 0, 0, 0);               \
3748    _qyy_res;                                                     \
3749   })
3750
3751#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2)    \
3752   __extension__                                                  \
3753   ({unsigned long _qyy_res;                                      \
3754    VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
3755                               VG_USERREQ__CLIENT_CALL2,          \
3756                               _qyy_fn,                           \
3757                               _qyy_arg1, _qyy_arg2, 0, 0);       \
3758    _qyy_res;                                                     \
3759   })
3760
3761#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
3762   __extension__                                                  \
3763   ({unsigned long _qyy_res;                                      \
3764    VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
3765                               VG_USERREQ__CLIENT_CALL3,          \
3766                               _qyy_fn,                           \
3767                               _qyy_arg1, _qyy_arg2,              \
3768                               _qyy_arg3, 0);                     \
3769    _qyy_res;                                                     \
3770   })
3771
3772
3773/* Counts the number of errors that have been recorded by a tool.  Nb:
3774   the tool must record the errors with VG_(maybe_record_error)() or
3775   VG_(unique_error)() for them to be counted. */
3776#define VALGRIND_COUNT_ERRORS                                     \
3777   __extension__                                                  \
3778   ({unsigned int _qyy_res;                                       \
3779    VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
3780                               VG_USERREQ__COUNT_ERRORS,          \
3781                               0, 0, 0, 0, 0);                    \
3782    _qyy_res;                                                     \
3783   })
3784
3785/* Mark a block of memory as having been allocated by a malloc()-like
3786   function.  `addr' is the start of the usable block (ie. after any
3787   redzone) `rzB' is redzone size if the allocator can apply redzones;
3788   use '0' if not.  Adding redzones makes it more likely Valgrind will spot
3789   block overruns.  `is_zeroed' indicates if the memory is zeroed, as it is
3790   for calloc().  Put it immediately after the point where a block is
3791   allocated.
3792
3793   If you're using Memcheck: If you're allocating memory via superblocks,
3794   and then handing out small chunks of each superblock, if you don't have
3795   redzones on your small blocks, it's worth marking the superblock with
3796   VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
3797   detected.  But if you can put redzones on, it's probably better to not do
3798   this, so that messages for small overruns are described in terms of the
3799   small block rather than the superblock (but if you have a big overrun
3800   that skips over a redzone, you could miss an error this way).  See
3801   memcheck/tests/custom_alloc.c for an example.
3802
3803   WARNING: if your allocator uses malloc() or 'new' to allocate
3804   superblocks, rather than mmap() or brk(), this will not work properly --
3805   you'll likely get assertion failures during leak detection.  This is
3806   because Valgrind doesn't like seeing overlapping heap blocks.  Sorry.
3807
3808   Nb: block must be freed via a free()-like function specified
3809   with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
3810#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)    \
3811   {unsigned int _qzz_res;                                        \
3812    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3813                               VG_USERREQ__MALLOCLIKE_BLOCK,      \
3814                               addr, sizeB, rzB, is_zeroed, 0);   \
3815   }
3816
3817/* Mark a block of memory as having been freed by a free()-like function.
3818   `rzB' is redzone size;  it must match that given to
3819   VALGRIND_MALLOCLIKE_BLOCK.  Memory not freed will be detected by the leak
3820   checker.  Put it immediately after the point where the block is freed. */
3821#define VALGRIND_FREELIKE_BLOCK(addr, rzB)                        \
3822   {unsigned int _qzz_res;                                        \
3823    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3824                               VG_USERREQ__FREELIKE_BLOCK,        \
3825                               addr, rzB, 0, 0, 0);               \
3826   }
3827
3828/* Create a memory pool. */
3829#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)             \
3830   {unsigned int _qzz_res;                                        \
3831    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3832                               VG_USERREQ__CREATE_MEMPOOL,        \
3833                               pool, rzB, is_zeroed, 0, 0);       \
3834   }
3835
3836/* Destroy a memory pool. */
3837#define VALGRIND_DESTROY_MEMPOOL(pool)                            \
3838   {unsigned int _qzz_res;                                        \
3839    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3840                               VG_USERREQ__DESTROY_MEMPOOL,       \
3841                               pool, 0, 0, 0, 0);                 \
3842   }
3843
3844/* Associate a piece of memory with a memory pool. */
3845#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)                  \
3846   {unsigned int _qzz_res;                                        \
3847    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3848                               VG_USERREQ__MEMPOOL_ALLOC,         \
3849                               pool, addr, size, 0, 0);           \
3850   }
3851
3852/* Disassociate a piece of memory from a memory pool. */
3853#define VALGRIND_MEMPOOL_FREE(pool, addr)                         \
3854   {unsigned int _qzz_res;                                        \
3855    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3856                               VG_USERREQ__MEMPOOL_FREE,          \
3857                               pool, addr, 0, 0, 0);              \
3858   }
3859
3860/* Disassociate any pieces outside a particular range. */
3861#define VALGRIND_MEMPOOL_TRIM(pool, addr, size)                   \
3862   {unsigned int _qzz_res;                                        \
3863    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3864                               VG_USERREQ__MEMPOOL_TRIM,          \
3865                               pool, addr, size, 0, 0);           \
3866   }
3867
3868/* Resize and/or move a piece associated with a memory pool. */
3869#define VALGRIND_MOVE_MEMPOOL(poolA, poolB)                       \
3870   {unsigned int _qzz_res;                                        \
3871    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3872                               VG_USERREQ__MOVE_MEMPOOL,          \
3873                               poolA, poolB, 0, 0, 0);            \
3874   }
3875
3876/* Resize and/or move a piece associated with a memory pool. */
3877#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size)         \
3878   {unsigned int _qzz_res;                                        \
3879    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3880                               VG_USERREQ__MEMPOOL_CHANGE,        \
3881                               pool, addrA, addrB, size, 0);      \
3882   }
3883
3884/* Return 1 if a mempool exists, else 0. */
3885#define VALGRIND_MEMPOOL_EXISTS(pool)                             \
3886   __extension__                                                  \
3887   ({unsigned int _qzz_res;                                       \
3888    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3889                               VG_USERREQ__MEMPOOL_EXISTS,        \
3890                               pool, 0, 0, 0, 0);                 \
3891    _qzz_res;                                                     \
3892   })
3893
3894/* Mark a piece of memory as being a stack. Returns a stack id. */
3895#define VALGRIND_STACK_REGISTER(start, end)                       \
3896   __extension__                                                  \
3897   ({unsigned int _qzz_res;                                       \
3898    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3899                               VG_USERREQ__STACK_REGISTER,        \
3900                               start, end, 0, 0, 0);              \
3901    _qzz_res;                                                     \
3902   })
3903
3904/* Unmark the piece of memory associated with a stack id as being a
3905   stack. */
3906#define VALGRIND_STACK_DEREGISTER(id)                             \
3907   {unsigned int _qzz_res;                                        \
3908    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3909                               VG_USERREQ__STACK_DEREGISTER,      \
3910                               id, 0, 0, 0, 0);                   \
3911   }
3912
3913/* Change the start and end address of the stack id. */
3914#define VALGRIND_STACK_CHANGE(id, start, end)                     \
3915   {unsigned int _qzz_res;                                        \
3916    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3917                               VG_USERREQ__STACK_CHANGE,          \
3918                               id, start, end, 0, 0);             \
3919   }
3920
3921/* Load PDB debug info for Wine PE image_map. */
3922#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta)   \
3923   {unsigned int _qzz_res;                                        \
3924    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
3925                               VG_USERREQ__LOAD_PDB_DEBUGINFO,    \
3926                               fd, ptr, total_size, delta, 0);    \
3927   }
3928
3929
3930#undef PLAT_x86_linux
3931#undef PLAT_amd64_linux
3932#undef PLAT_ppc32_linux
3933#undef PLAT_ppc64_linux
3934#undef PLAT_ppc32_aix5
3935#undef PLAT_ppc64_aix5
3936
3937#endif   /* __VALGRIND_H */
3938