valgrind.h

00001 /* -*- c -*-
00002    ----------------------------------------------------------------
00003 
00004    Notice that the following BSD-style license applies to this one
00005    file (valgrind.h) only.  The rest of Valgrind is licensed under the
00006    terms of the GNU General Public License, version 2, unless
00007    otherwise indicated.  See the COPYING file in the source
00008    distribution for details.
00009 
00010    ----------------------------------------------------------------
00011 
00012    This file is part of Valgrind, a dynamic binary instrumentation
00013    framework.
00014 
00015    Copyright (C) 2000-2008 Julian Seward.  All rights reserved.
00016 
00017    Redistribution and use in source and binary forms, with or without
00018    modification, are permitted provided that the following conditions
00019    are met:
00020 
00021    1. Redistributions of source code must retain the above copyright
00022       notice, this list of conditions and the following disclaimer.
00023 
00024    2. The origin of this software must not be misrepresented; you must 
00025       not claim that you wrote the original software.  If you use this 
00026       software in a product, an acknowledgment in the product 
00027       documentation would be appreciated but is not required.
00028 
00029    3. Altered source versions must be plainly marked as such, and must
00030       not be misrepresented as being the original software.
00031 
00032    4. The name of the author may not be used to endorse or promote 
00033       products derived from this software without specific prior written 
00034       permission.
00035 
00036    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00037    OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00038    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00039    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00040    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00041    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00042    GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00043    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00044    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00045    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00046    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00047 
00048    ----------------------------------------------------------------
00049 
00050    Notice that the above BSD-style license applies to this one file
00051    (valgrind.h) only.  The entire rest of Valgrind is licensed under
00052    the terms of the GNU General Public License, version 2.  See the
00053    COPYING file in the source distribution for details.
00054 
00055    ---------------------------------------------------------------- 
00056 */
00057 
00058 
00059 /* This file is for inclusion into client (your!) code.
00060 
00061    You can use these macros to manipulate and query Valgrind's 
00062    execution inside your own programs.
00063 
00064    The resulting executables will still run without Valgrind, just a
00065    little bit more slowly than they otherwise would, but otherwise
00066    unchanged.  When not running on valgrind, each client request
00067    consumes very few (eg. 7) instructions, so the resulting performance
00068    loss is negligible unless you plan to execute client requests
00069    millions of times per second.  Nevertheless, if that is still a
00070    problem, you can compile with the NVALGRIND symbol defined (gcc
00071    -DNVALGRIND) so that client requests are not even compiled in.  */
00072 
00073 #ifndef __VALGRIND_H
00074 #define __VALGRIND_H
00075 
00076 #include <stdarg.h>
00077 
00078 /* Nb: this file might be included in a file compiled with -ansi.  So
00079    we can't use C++ style "//" comments nor the "asm" keyword (instead
00080    use "__asm__"). */
00081 
00082 /* Derive some tags indicating what the target platform is.  Note
00083    that in this file we're using the compiler's CPP symbols for
00084    identifying architectures, which are different to the ones we use
00085    within the rest of Valgrind.  Note, __powerpc__ is active for both
00086    32 and 64-bit PPC, whereas __powerpc64__ is only active for the
00087    latter (on Linux, that is). */
00088 #undef PLAT_x86_linux
00089 #undef PLAT_amd64_linux
00090 #undef PLAT_ppc32_linux
00091 #undef PLAT_ppc64_linux
00092 #undef PLAT_ppc32_aix5
00093 #undef PLAT_ppc64_aix5
00094 
00095 #if !defined(_AIX) && defined(__i386__)
00096 #  define PLAT_x86_linux 1
00097 #elif !defined(_AIX) && defined(__x86_64__)
00098 #  define PLAT_amd64_linux 1
00099 #elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
00100 #  define PLAT_ppc32_linux 1
00101 #elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
00102 #  define PLAT_ppc64_linux 1
00103 #elif defined(_AIX) && defined(__64BIT__)
00104 #  define PLAT_ppc64_aix5 1
00105 #elif defined(_AIX) && !defined(__64BIT__)
00106 #  define PLAT_ppc32_aix5 1
00107 #endif
00108 
00109 
00110 /* If we're not compiling for our target platform, don't generate
00111    any inline asms.  */
00112 #if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
00113     && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
00114     && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
00115 #  if !defined(NVALGRIND)
00116 #    define NVALGRIND 1
00117 #  endif
00118 #endif
00119 
00120 
00121 /* ------------------------------------------------------------------ */
00122 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS.  There is nothing */
00123 /* in here of use to end-users -- skip to the next section.           */
00124 /* ------------------------------------------------------------------ */
00125 
00126 #if defined(NVALGRIND)
00127 
00128 /* Define NVALGRIND to completely remove the Valgrind magic sequence
00129    from the compiled code (analogous to NDEBUG's effects on
00130    assert()) */
00131 #define VALGRIND_DO_CLIENT_REQUEST(                               \
00132         _zzq_rlval, _zzq_default, _zzq_request,                   \
00133         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
00134    {                                                              \
00135       (_zzq_rlval) = (_zzq_default);                              \
00136    }
00137 
00138 #else  /* ! NVALGRIND */
00139 
00140 /* The following defines the magic code sequences which the JITter
00141    spots and handles magically.  Don't look too closely at them as
00142    they will rot your brain.
00143 
00144    The assembly code sequences for all architectures is in this one
00145    file.  This is because this file must be stand-alone, and we don't
00146    want to have multiple files.
00147 
00148    For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
00149    value gets put in the return slot, so that everything works when
00150    this is executed not under Valgrind.  Args are passed in a memory
00151    block, and so there's no intrinsic limit to the number that could
00152    be passed, but it's currently five.
00153    
00154    The macro args are: 
00155       _zzq_rlval    result lvalue
00156       _zzq_default  default value (result returned when running on real CPU)
00157       _zzq_request  request code
00158       _zzq_arg1..5  request params
00159 
00160    The other two macros are used to support function wrapping, and are
00161    a lot simpler.  VALGRIND_GET_NR_CONTEXT returns the value of the
00162    guest's NRADDR pseudo-register and whatever other information is
00163    needed to safely run the call original from the wrapper: on
00164    ppc64-linux, the R2 value at the divert point is also needed.  This
00165    information is abstracted into a user-visible type, OrigFn.
00166 
00167    VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
00168    guest, but guarantees that the branch instruction will not be
00169    redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
00170    branch-and-link-to-r11.  VALGRIND_CALL_NOREDIR is just text, not a
00171    complete inline asm, since it needs to be combined with more magic
00172    inline asm stuff to be useful.
00173 */
00174 
00175 /* ------------------------- x86-linux ------------------------- */
00176 
00177 #if defined(PLAT_x86_linux)
00178 
00179 typedef
00180    struct { 
00181       unsigned int nraddr; /* where's the code? */
00182    }
00183    OrigFn;
00184 
00185 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
00186                      "roll $3,  %%edi ; roll $13, %%edi\n\t"      \
00187                      "roll $29, %%edi ; roll $19, %%edi\n\t"
00188 
00189 #define VALGRIND_DO_CLIENT_REQUEST(                               \
00190         _zzq_rlval, _zzq_default, _zzq_request,                   \
00191         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
00192   { volatile unsigned int _zzq_args[6];                           \
00193     volatile unsigned int _zzq_result;                            \
00194     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
00195     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
00196     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
00197     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
00198     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
00199     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
00200     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00201                      /* %EDX = client_request ( %EAX ) */         \
00202                      "xchgl %%ebx,%%ebx"                          \
00203                      : "=d" (_zzq_result)                         \
00204                      : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
00205                      : "cc", "memory"                             \
00206                     );                                            \
00207     _zzq_rlval = _zzq_result;                                     \
00208   }
00209 
00210 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
00211   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
00212     volatile unsigned int __addr;                                 \
00213     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00214                      /* %EAX = guest_NRADDR */                    \
00215                      "xchgl %%ecx,%%ecx"                          \
00216                      : "=a" (__addr)                              \
00217                      :                                            \
00218                      : "cc", "memory"                             \
00219                     );                                            \
00220     _zzq_orig->nraddr = __addr;                                   \
00221   }
00222 
00223 #define VALGRIND_CALL_NOREDIR_EAX                                 \
00224                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00225                      /* call-noredir *%EAX */                     \
00226                      "xchgl %%edx,%%edx\n\t"
00227 #endif /* PLAT_x86_linux */
00228 
00229 /* ------------------------ amd64-linux ------------------------ */
00230 
00231 #if defined(PLAT_amd64_linux)
00232 
00233 typedef
00234    struct { 
00235       unsigned long long int nraddr; /* where's the code? */
00236    }
00237    OrigFn;
00238 
00239 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
00240                      "rolq $3,  %%rdi ; rolq $13, %%rdi\n\t"      \
00241                      "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
00242 
00243 #define VALGRIND_DO_CLIENT_REQUEST(                               \
00244         _zzq_rlval, _zzq_default, _zzq_request,                   \
00245         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
00246   { volatile unsigned long long int _zzq_args[6];                 \
00247     volatile unsigned long long int _zzq_result;                  \
00248     _zzq_args[0] = (unsigned long long int)(_zzq_request);        \
00249     _zzq_args[1] = (unsigned long long int)(_zzq_arg1);           \
00250     _zzq_args[2] = (unsigned long long int)(_zzq_arg2);           \
00251     _zzq_args[3] = (unsigned long long int)(_zzq_arg3);           \
00252     _zzq_args[4] = (unsigned long long int)(_zzq_arg4);           \
00253     _zzq_args[5] = (unsigned long long int)(_zzq_arg5);           \
00254     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00255                      /* %RDX = client_request ( %RAX ) */         \
00256                      "xchgq %%rbx,%%rbx"                          \
00257                      : "=d" (_zzq_result)                         \
00258                      : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
00259                      : "cc", "memory"                             \
00260                     );                                            \
00261     _zzq_rlval = _zzq_result;                                     \
00262   }
00263 
00264 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
00265   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
00266     volatile unsigned long long int __addr;                       \
00267     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00268                      /* %RAX = guest_NRADDR */                    \
00269                      "xchgq %%rcx,%%rcx"                          \
00270                      : "=a" (__addr)                              \
00271                      :                                            \
00272                      : "cc", "memory"                             \
00273                     );                                            \
00274     _zzq_orig->nraddr = __addr;                                   \
00275   }
00276 
00277 #define VALGRIND_CALL_NOREDIR_RAX                                 \
00278                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00279                      /* call-noredir *%RAX */                     \
00280                      "xchgq %%rdx,%%rdx\n\t"
00281 #endif /* PLAT_amd64_linux */
00282 
00283 /* ------------------------ ppc32-linux ------------------------ */
00284 
00285 #if defined(PLAT_ppc32_linux)
00286 
00287 typedef
00288    struct { 
00289       unsigned int nraddr; /* where's the code? */
00290    }
00291    OrigFn;
00292 
00293 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
00294                      "rlwinm 0,0,3,0,0  ; rlwinm 0,0,13,0,0\n\t"  \
00295                      "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
00296 
00297 #define VALGRIND_DO_CLIENT_REQUEST(                               \
00298         _zzq_rlval, _zzq_default, _zzq_request,                   \
00299         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
00300                                                                   \
00301   {          unsigned int  _zzq_args[6];                          \
00302              unsigned int  _zzq_result;                           \
00303              unsigned int* _zzq_ptr;                              \
00304     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
00305     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
00306     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
00307     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
00308     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
00309     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
00310     _zzq_ptr = _zzq_args;                                         \
00311     __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
00312                      "mr 4,%2\n\t" /*ptr*/                        \
00313                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00314                      /* %R3 = client_request ( %R4 ) */           \
00315                      "or 1,1,1\n\t"                               \
00316                      "mr %0,3"     /*result*/                     \
00317                      : "=b" (_zzq_result)                         \
00318                      : "b" (_zzq_default), "b" (_zzq_ptr)         \
00319                      : "cc", "memory", "r3", "r4");               \
00320     _zzq_rlval = _zzq_result;                                     \
00321   }
00322 
00323 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
00324   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
00325     unsigned int __addr;                                          \
00326     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00327                      /* %R3 = guest_NRADDR */                     \
00328                      "or 2,2,2\n\t"                               \
00329                      "mr %0,3"                                    \
00330                      : "=b" (__addr)                              \
00331                      :                                            \
00332                      : "cc", "memory", "r3"                       \
00333                     );                                            \
00334     _zzq_orig->nraddr = __addr;                                   \
00335   }
00336 
00337 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
00338                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00339                      /* branch-and-link-to-noredir *%R11 */       \
00340                      "or 3,3,3\n\t"
00341 #endif /* PLAT_ppc32_linux */
00342 
00343 /* ------------------------ ppc64-linux ------------------------ */
00344 
00345 #if defined(PLAT_ppc64_linux)
00346 
00347 typedef
00348    struct { 
00349       unsigned long long int nraddr; /* where's the code? */
00350       unsigned long long int r2;  /* what tocptr do we need? */
00351    }
00352    OrigFn;
00353 
00354 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
00355                      "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
00356                      "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
00357 
00358 #define VALGRIND_DO_CLIENT_REQUEST(                               \
00359         _zzq_rlval, _zzq_default, _zzq_request,                   \
00360         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
00361                                                                   \
00362   {          unsigned long long int  _zzq_args[6];                \
00363     register unsigned long long int  _zzq_result __asm__("r3");   \
00364     register unsigned long long int* _zzq_ptr __asm__("r4");      \
00365     _zzq_args[0] = (unsigned long long int)(_zzq_request);        \
00366     _zzq_args[1] = (unsigned long long int)(_zzq_arg1);           \
00367     _zzq_args[2] = (unsigned long long int)(_zzq_arg2);           \
00368     _zzq_args[3] = (unsigned long long int)(_zzq_arg3);           \
00369     _zzq_args[4] = (unsigned long long int)(_zzq_arg4);           \
00370     _zzq_args[5] = (unsigned long long int)(_zzq_arg5);           \
00371     _zzq_ptr = _zzq_args;                                         \
00372     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00373                      /* %R3 = client_request ( %R4 ) */           \
00374                      "or 1,1,1"                                   \
00375                      : "=r" (_zzq_result)                         \
00376                      : "0" (_zzq_default), "r" (_zzq_ptr)         \
00377                      : "cc", "memory");                           \
00378     _zzq_rlval = _zzq_result;                                     \
00379   }
00380 
00381 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
00382   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
00383     register unsigned long long int __addr __asm__("r3");         \
00384     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00385                      /* %R3 = guest_NRADDR */                     \
00386                      "or 2,2,2"                                   \
00387                      : "=r" (__addr)                              \
00388                      :                                            \
00389                      : "cc", "memory"                             \
00390                     );                                            \
00391     _zzq_orig->nraddr = __addr;                                   \
00392     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00393                      /* %R3 = guest_NRADDR_GPR2 */                \
00394                      "or 4,4,4"                                   \
00395                      : "=r" (__addr)                              \
00396                      :                                            \
00397                      : "cc", "memory"                             \
00398                     );                                            \
00399     _zzq_orig->r2 = __addr;                                       \
00400   }
00401 
00402 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
00403                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00404                      /* branch-and-link-to-noredir *%R11 */       \
00405                      "or 3,3,3\n\t"
00406 
00407 #endif /* PLAT_ppc64_linux */
00408 
00409 /* ------------------------ ppc32-aix5 ------------------------- */
00410 
00411 #if defined(PLAT_ppc32_aix5)
00412 
00413 typedef
00414    struct { 
00415       unsigned int nraddr; /* where's the code? */
00416       unsigned int r2;  /* what tocptr do we need? */
00417    }
00418    OrigFn;
00419 
00420 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
00421                      "rlwinm 0,0,3,0,0  ; rlwinm 0,0,13,0,0\n\t"  \
00422                      "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
00423 
00424 #define VALGRIND_DO_CLIENT_REQUEST(                               \
00425         _zzq_rlval, _zzq_default, _zzq_request,                   \
00426         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
00427                                                                   \
00428   {          unsigned int  _zzq_args[7];                          \
00429     register unsigned int  _zzq_result;                           \
00430     register unsigned int* _zzq_ptr;                              \
00431     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
00432     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
00433     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
00434     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
00435     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
00436     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
00437     _zzq_args[6] = (unsigned int)(_zzq_default);                  \
00438     _zzq_ptr = _zzq_args;                                         \
00439     __asm__ volatile("mr 4,%1\n\t"                                \
00440                      "lwz 3, 24(4)\n\t"                           \
00441                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00442                      /* %R3 = client_request ( %R4 ) */           \
00443                      "or 1,1,1\n\t"                               \
00444                      "mr %0,3"                                    \
00445                      : "=b" (_zzq_result)                         \
00446                      : "b" (_zzq_ptr)                             \
00447                      : "r3", "r4", "cc", "memory");               \
00448     _zzq_rlval = _zzq_result;                                     \
00449   }
00450 
00451 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
00452   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
00453     register unsigned int __addr;                                 \
00454     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00455                      /* %R3 = guest_NRADDR */                     \
00456                      "or 2,2,2\n\t"                               \
00457                      "mr %0,3"                                    \
00458                      : "=b" (__addr)                              \
00459                      :                                            \
00460                      : "r3", "cc", "memory"                       \
00461                     );                                            \
00462     _zzq_orig->nraddr = __addr;                                   \
00463     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00464                      /* %R3 = guest_NRADDR_GPR2 */                \
00465                      "or 4,4,4\n\t"                               \
00466                      "mr %0,3"                                    \
00467                      : "=b" (__addr)                              \
00468                      :                                            \
00469                      : "r3", "cc", "memory"                       \
00470                     );                                            \
00471     _zzq_orig->r2 = __addr;                                       \
00472   }
00473 
00474 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
00475                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00476                      /* branch-and-link-to-noredir *%R11 */       \
00477                      "or 3,3,3\n\t"
00478 
00479 #endif /* PLAT_ppc32_aix5 */
00480 
00481 /* ------------------------ ppc64-aix5 ------------------------- */
00482 
00483 #if defined(PLAT_ppc64_aix5)
00484 
00485 typedef
00486    struct { 
00487       unsigned long long int nraddr; /* where's the code? */
00488       unsigned long long int r2;  /* what tocptr do we need? */
00489    }
00490    OrigFn;
00491 
00492 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
00493                      "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
00494                      "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
00495 
00496 #define VALGRIND_DO_CLIENT_REQUEST(                               \
00497         _zzq_rlval, _zzq_default, _zzq_request,                   \
00498         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
00499                                                                   \
00500   {          unsigned long long int  _zzq_args[7];                \
00501     register unsigned long long int  _zzq_result;                 \
00502     register unsigned long long int* _zzq_ptr;                    \
00503     _zzq_args[0] = (unsigned int long long)(_zzq_request);        \
00504     _zzq_args[1] = (unsigned int long long)(_zzq_arg1);           \
00505     _zzq_args[2] = (unsigned int long long)(_zzq_arg2);           \
00506     _zzq_args[3] = (unsigned int long long)(_zzq_arg3);           \
00507     _zzq_args[4] = (unsigned int long long)(_zzq_arg4);           \
00508     _zzq_args[5] = (unsigned int long long)(_zzq_arg5);           \
00509     _zzq_args[6] = (unsigned int long long)(_zzq_default);        \
00510     _zzq_ptr = _zzq_args;                                         \
00511     __asm__ volatile("mr 4,%1\n\t"                                \
00512                      "ld 3, 48(4)\n\t"                            \
00513                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00514                      /* %R3 = client_request ( %R4 ) */           \
00515                      "or 1,1,1\n\t"                               \
00516                      "mr %0,3"                                    \
00517                      : "=b" (_zzq_result)                         \
00518                      : "b" (_zzq_ptr)                             \
00519                      : "r3", "r4", "cc", "memory");               \
00520     _zzq_rlval = _zzq_result;                                     \
00521   }
00522 
00523 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
00524   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
00525     register unsigned long long int __addr;                       \
00526     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00527                      /* %R3 = guest_NRADDR */                     \
00528                      "or 2,2,2\n\t"                               \
00529                      "mr %0,3"                                    \
00530                      : "=b" (__addr)                              \
00531                      :                                            \
00532                      : "r3", "cc", "memory"                       \
00533                     );                                            \
00534     _zzq_orig->nraddr = __addr;                                   \
00535     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
00536                      /* %R3 = guest_NRADDR_GPR2 */                \
00537                      "or 4,4,4\n\t"                               \
00538                      "mr %0,3"                                    \
00539                      : "=b" (__addr)                              \
00540                      :                                            \
00541                      : "r3", "cc", "memory"                       \
00542                     );                                            \
00543     _zzq_orig->r2 = __addr;                                       \
00544   }
00545 
00546 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
00547                      __SPECIAL_INSTRUCTION_PREAMBLE               \
00548                      /* branch-and-link-to-noredir *%R11 */       \
00549                      "or 3,3,3\n\t"
00550 
00551 #endif /* PLAT_ppc64_aix5 */
00552 
00553 /* Insert assembly code for other platforms here... */
00554 
00555 #endif /* NVALGRIND */
00556 
00557 
00558 /* ------------------------------------------------------------------ */
00559 /* PLATFORM SPECIFICS for FUNCTION WRAPPING.  This is all very        */
00560 /* ugly.  It's the least-worst tradeoff I can think of.               */
00561 /* ------------------------------------------------------------------ */
00562 
00563 /* This section defines magic (a.k.a appalling-hack) macros for doing
00564    guaranteed-no-redirection macros, so as to get from function
00565    wrappers to the functions they are wrapping.  The whole point is to
00566    construct standard call sequences, but to do the call itself with a
00567    special no-redirect call pseudo-instruction that the JIT
00568    understands and handles specially.  This section is long and
00569    repetitious, and I can't see a way to make it shorter.
00570 
00571    The naming scheme is as follows:
00572 
00573       CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
00574 
00575    'W' stands for "word" and 'v' for "void".  Hence there are
00576    different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
00577    and for each, the possibility of returning a word-typed result, or
00578    no result.
00579 */
00580 
00581 /* Use these to write the name of your wrapper.  NOTE: duplicates
00582    VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
00583 
00584 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname)                    \
00585    _vgwZU_##soname##_##fnname
00586 
00587 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname)                    \
00588    _vgwZZ_##soname##_##fnname
00589 
00590 /* Use this macro from within a wrapper function to collect the
00591    context (address and possibly other info) of the original function.
00592    Once you have that you can then use it in one of the CALL_FN_
00593    macros.  The type of the argument _lval is OrigFn. */
00594 #define VALGRIND_GET_ORIG_FN(_lval)  VALGRIND_GET_NR_CONTEXT(_lval)
00595 
00596 /* Derivatives of the main macros below, for calling functions
00597    returning void. */
00598 
00599 #define CALL_FN_v_v(fnptr)                                        \
00600    do { volatile unsigned long _junk;                             \
00601         CALL_FN_W_v(_junk,fnptr); } while (0)
00602 
00603 #define CALL_FN_v_W(fnptr, arg1)                                  \
00604    do { volatile unsigned long _junk;                             \
00605         CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
00606 
00607 #define CALL_FN_v_WW(fnptr, arg1,arg2)                            \
00608    do { volatile unsigned long _junk;                             \
00609         CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
00610 
00611 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3)                      \
00612    do { volatile unsigned long _junk;                             \
00613         CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
00614 
00615 /* ------------------------- x86-linux ------------------------- */
00616 
00617 #if defined(PLAT_x86_linux)
00618 
00619 /* These regs are trashed by the hidden call.  No need to mention eax
00620    as gcc can already see that, plus causes gcc to bomb. */
00621 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
00622 
00623 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
00624    long) == 4. */
00625 
00626 #define CALL_FN_W_v(lval, orig)                                   \
00627    do {                                                           \
00628       volatile OrigFn        _orig = (orig);                      \
00629       volatile unsigned long _argvec[1];                          \
00630       volatile unsigned long _res;                                \
00631       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00632       __asm__ volatile(                                           \
00633          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00634          VALGRIND_CALL_NOREDIR_EAX                                \
00635          : /*out*/   "=a" (_res)                                  \
00636          : /*in*/    "a" (&_argvec[0])                            \
00637          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00638       );                                                          \
00639       lval = (__typeof__(lval)) _res;                             \
00640    } while (0)
00641 
00642 #define CALL_FN_W_W(lval, orig, arg1)                             \
00643    do {                                                           \
00644       volatile OrigFn        _orig = (orig);                      \
00645       volatile unsigned long _argvec[2];                          \
00646       volatile unsigned long _res;                                \
00647       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00648       _argvec[1] = (unsigned long)(arg1);                         \
00649       __asm__ volatile(                                           \
00650          "pushl 4(%%eax)\n\t"                                     \
00651          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00652          VALGRIND_CALL_NOREDIR_EAX                                \
00653          "addl $4, %%esp\n"                                       \
00654          : /*out*/   "=a" (_res)                                  \
00655          : /*in*/    "a" (&_argvec[0])                            \
00656          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00657       );                                                          \
00658       lval = (__typeof__(lval)) _res;                             \
00659    } while (0)
00660 
00661 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
00662    do {                                                           \
00663       volatile OrigFn        _orig = (orig);                      \
00664       volatile unsigned long _argvec[3];                          \
00665       volatile unsigned long _res;                                \
00666       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00667       _argvec[1] = (unsigned long)(arg1);                         \
00668       _argvec[2] = (unsigned long)(arg2);                         \
00669       __asm__ volatile(                                           \
00670          "pushl 8(%%eax)\n\t"                                     \
00671          "pushl 4(%%eax)\n\t"                                     \
00672          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00673          VALGRIND_CALL_NOREDIR_EAX                                \
00674          "addl $8, %%esp\n"                                       \
00675          : /*out*/   "=a" (_res)                                  \
00676          : /*in*/    "a" (&_argvec[0])                            \
00677          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00678       );                                                          \
00679       lval = (__typeof__(lval)) _res;                             \
00680    } while (0)
00681 
00682 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
00683    do {                                                           \
00684       volatile OrigFn        _orig = (orig);                      \
00685       volatile unsigned long _argvec[4];                          \
00686       volatile unsigned long _res;                                \
00687       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00688       _argvec[1] = (unsigned long)(arg1);                         \
00689       _argvec[2] = (unsigned long)(arg2);                         \
00690       _argvec[3] = (unsigned long)(arg3);                         \
00691       __asm__ volatile(                                           \
00692          "pushl 12(%%eax)\n\t"                                    \
00693          "pushl 8(%%eax)\n\t"                                     \
00694          "pushl 4(%%eax)\n\t"                                     \
00695          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00696          VALGRIND_CALL_NOREDIR_EAX                                \
00697          "addl $12, %%esp\n"                                      \
00698          : /*out*/   "=a" (_res)                                  \
00699          : /*in*/    "a" (&_argvec[0])                            \
00700          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00701       );                                                          \
00702       lval = (__typeof__(lval)) _res;                             \
00703    } while (0)
00704 
00705 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
00706    do {                                                           \
00707       volatile OrigFn        _orig = (orig);                      \
00708       volatile unsigned long _argvec[5];                          \
00709       volatile unsigned long _res;                                \
00710       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00711       _argvec[1] = (unsigned long)(arg1);                         \
00712       _argvec[2] = (unsigned long)(arg2);                         \
00713       _argvec[3] = (unsigned long)(arg3);                         \
00714       _argvec[4] = (unsigned long)(arg4);                         \
00715       __asm__ volatile(                                           \
00716          "pushl 16(%%eax)\n\t"                                    \
00717          "pushl 12(%%eax)\n\t"                                    \
00718          "pushl 8(%%eax)\n\t"                                     \
00719          "pushl 4(%%eax)\n\t"                                     \
00720          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00721          VALGRIND_CALL_NOREDIR_EAX                                \
00722          "addl $16, %%esp\n"                                      \
00723          : /*out*/   "=a" (_res)                                  \
00724          : /*in*/    "a" (&_argvec[0])                            \
00725          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00726       );                                                          \
00727       lval = (__typeof__(lval)) _res;                             \
00728    } while (0)
00729 
00730 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
00731    do {                                                           \
00732       volatile OrigFn        _orig = (orig);                      \
00733       volatile unsigned long _argvec[6];                          \
00734       volatile unsigned long _res;                                \
00735       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00736       _argvec[1] = (unsigned long)(arg1);                         \
00737       _argvec[2] = (unsigned long)(arg2);                         \
00738       _argvec[3] = (unsigned long)(arg3);                         \
00739       _argvec[4] = (unsigned long)(arg4);                         \
00740       _argvec[5] = (unsigned long)(arg5);                         \
00741       __asm__ volatile(                                           \
00742          "pushl 20(%%eax)\n\t"                                    \
00743          "pushl 16(%%eax)\n\t"                                    \
00744          "pushl 12(%%eax)\n\t"                                    \
00745          "pushl 8(%%eax)\n\t"                                     \
00746          "pushl 4(%%eax)\n\t"                                     \
00747          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00748          VALGRIND_CALL_NOREDIR_EAX                                \
00749          "addl $20, %%esp\n"                                      \
00750          : /*out*/   "=a" (_res)                                  \
00751          : /*in*/    "a" (&_argvec[0])                            \
00752          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00753       );                                                          \
00754       lval = (__typeof__(lval)) _res;                             \
00755    } while (0)
00756 
00757 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
00758    do {                                                           \
00759       volatile OrigFn        _orig = (orig);                      \
00760       volatile unsigned long _argvec[7];                          \
00761       volatile unsigned long _res;                                \
00762       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00763       _argvec[1] = (unsigned long)(arg1);                         \
00764       _argvec[2] = (unsigned long)(arg2);                         \
00765       _argvec[3] = (unsigned long)(arg3);                         \
00766       _argvec[4] = (unsigned long)(arg4);                         \
00767       _argvec[5] = (unsigned long)(arg5);                         \
00768       _argvec[6] = (unsigned long)(arg6);                         \
00769       __asm__ volatile(                                           \
00770          "pushl 24(%%eax)\n\t"                                    \
00771          "pushl 20(%%eax)\n\t"                                    \
00772          "pushl 16(%%eax)\n\t"                                    \
00773          "pushl 12(%%eax)\n\t"                                    \
00774          "pushl 8(%%eax)\n\t"                                     \
00775          "pushl 4(%%eax)\n\t"                                     \
00776          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00777          VALGRIND_CALL_NOREDIR_EAX                                \
00778          "addl $24, %%esp\n"                                      \
00779          : /*out*/   "=a" (_res)                                  \
00780          : /*in*/    "a" (&_argvec[0])                            \
00781          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00782       );                                                          \
00783       lval = (__typeof__(lval)) _res;                             \
00784    } while (0)
00785 
00786 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
00787                                  arg7)                            \
00788    do {                                                           \
00789       volatile OrigFn        _orig = (orig);                      \
00790       volatile unsigned long _argvec[8];                          \
00791       volatile unsigned long _res;                                \
00792       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00793       _argvec[1] = (unsigned long)(arg1);                         \
00794       _argvec[2] = (unsigned long)(arg2);                         \
00795       _argvec[3] = (unsigned long)(arg3);                         \
00796       _argvec[4] = (unsigned long)(arg4);                         \
00797       _argvec[5] = (unsigned long)(arg5);                         \
00798       _argvec[6] = (unsigned long)(arg6);                         \
00799       _argvec[7] = (unsigned long)(arg7);                         \
00800       __asm__ volatile(                                           \
00801          "pushl 28(%%eax)\n\t"                                    \
00802          "pushl 24(%%eax)\n\t"                                    \
00803          "pushl 20(%%eax)\n\t"                                    \
00804          "pushl 16(%%eax)\n\t"                                    \
00805          "pushl 12(%%eax)\n\t"                                    \
00806          "pushl 8(%%eax)\n\t"                                     \
00807          "pushl 4(%%eax)\n\t"                                     \
00808          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00809          VALGRIND_CALL_NOREDIR_EAX                                \
00810          "addl $28, %%esp\n"                                      \
00811          : /*out*/   "=a" (_res)                                  \
00812          : /*in*/    "a" (&_argvec[0])                            \
00813          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00814       );                                                          \
00815       lval = (__typeof__(lval)) _res;                             \
00816    } while (0)
00817 
00818 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
00819                                  arg7,arg8)                       \
00820    do {                                                           \
00821       volatile OrigFn        _orig = (orig);                      \
00822       volatile unsigned long _argvec[9];                          \
00823       volatile unsigned long _res;                                \
00824       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00825       _argvec[1] = (unsigned long)(arg1);                         \
00826       _argvec[2] = (unsigned long)(arg2);                         \
00827       _argvec[3] = (unsigned long)(arg3);                         \
00828       _argvec[4] = (unsigned long)(arg4);                         \
00829       _argvec[5] = (unsigned long)(arg5);                         \
00830       _argvec[6] = (unsigned long)(arg6);                         \
00831       _argvec[7] = (unsigned long)(arg7);                         \
00832       _argvec[8] = (unsigned long)(arg8);                         \
00833       __asm__ volatile(                                           \
00834          "pushl 32(%%eax)\n\t"                                    \
00835          "pushl 28(%%eax)\n\t"                                    \
00836          "pushl 24(%%eax)\n\t"                                    \
00837          "pushl 20(%%eax)\n\t"                                    \
00838          "pushl 16(%%eax)\n\t"                                    \
00839          "pushl 12(%%eax)\n\t"                                    \
00840          "pushl 8(%%eax)\n\t"                                     \
00841          "pushl 4(%%eax)\n\t"                                     \
00842          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00843          VALGRIND_CALL_NOREDIR_EAX                                \
00844          "addl $32, %%esp\n"                                      \
00845          : /*out*/   "=a" (_res)                                  \
00846          : /*in*/    "a" (&_argvec[0])                            \
00847          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00848       );                                                          \
00849       lval = (__typeof__(lval)) _res;                             \
00850    } while (0)
00851 
00852 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
00853                                  arg7,arg8,arg9)                  \
00854    do {                                                           \
00855       volatile OrigFn        _orig = (orig);                      \
00856       volatile unsigned long _argvec[10];                         \
00857       volatile unsigned long _res;                                \
00858       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00859       _argvec[1] = (unsigned long)(arg1);                         \
00860       _argvec[2] = (unsigned long)(arg2);                         \
00861       _argvec[3] = (unsigned long)(arg3);                         \
00862       _argvec[4] = (unsigned long)(arg4);                         \
00863       _argvec[5] = (unsigned long)(arg5);                         \
00864       _argvec[6] = (unsigned long)(arg6);                         \
00865       _argvec[7] = (unsigned long)(arg7);                         \
00866       _argvec[8] = (unsigned long)(arg8);                         \
00867       _argvec[9] = (unsigned long)(arg9);                         \
00868       __asm__ volatile(                                           \
00869          "pushl 36(%%eax)\n\t"                                    \
00870          "pushl 32(%%eax)\n\t"                                    \
00871          "pushl 28(%%eax)\n\t"                                    \
00872          "pushl 24(%%eax)\n\t"                                    \
00873          "pushl 20(%%eax)\n\t"                                    \
00874          "pushl 16(%%eax)\n\t"                                    \
00875          "pushl 12(%%eax)\n\t"                                    \
00876          "pushl 8(%%eax)\n\t"                                     \
00877          "pushl 4(%%eax)\n\t"                                     \
00878          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00879          VALGRIND_CALL_NOREDIR_EAX                                \
00880          "addl $36, %%esp\n"                                      \
00881          : /*out*/   "=a" (_res)                                  \
00882          : /*in*/    "a" (&_argvec[0])                            \
00883          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00884       );                                                          \
00885       lval = (__typeof__(lval)) _res;                             \
00886    } while (0)
00887 
00888 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
00889                                   arg7,arg8,arg9,arg10)           \
00890    do {                                                           \
00891       volatile OrigFn        _orig = (orig);                      \
00892       volatile unsigned long _argvec[11];                         \
00893       volatile unsigned long _res;                                \
00894       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00895       _argvec[1] = (unsigned long)(arg1);                         \
00896       _argvec[2] = (unsigned long)(arg2);                         \
00897       _argvec[3] = (unsigned long)(arg3);                         \
00898       _argvec[4] = (unsigned long)(arg4);                         \
00899       _argvec[5] = (unsigned long)(arg5);                         \
00900       _argvec[6] = (unsigned long)(arg6);                         \
00901       _argvec[7] = (unsigned long)(arg7);                         \
00902       _argvec[8] = (unsigned long)(arg8);                         \
00903       _argvec[9] = (unsigned long)(arg9);                         \
00904       _argvec[10] = (unsigned long)(arg10);                       \
00905       __asm__ volatile(                                           \
00906          "pushl 40(%%eax)\n\t"                                    \
00907          "pushl 36(%%eax)\n\t"                                    \
00908          "pushl 32(%%eax)\n\t"                                    \
00909          "pushl 28(%%eax)\n\t"                                    \
00910          "pushl 24(%%eax)\n\t"                                    \
00911          "pushl 20(%%eax)\n\t"                                    \
00912          "pushl 16(%%eax)\n\t"                                    \
00913          "pushl 12(%%eax)\n\t"                                    \
00914          "pushl 8(%%eax)\n\t"                                     \
00915          "pushl 4(%%eax)\n\t"                                     \
00916          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00917          VALGRIND_CALL_NOREDIR_EAX                                \
00918          "addl $40, %%esp\n"                                      \
00919          : /*out*/   "=a" (_res)                                  \
00920          : /*in*/    "a" (&_argvec[0])                            \
00921          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00922       );                                                          \
00923       lval = (__typeof__(lval)) _res;                             \
00924    } while (0)
00925 
00926 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
00927                                   arg6,arg7,arg8,arg9,arg10,      \
00928                                   arg11)                          \
00929    do {                                                           \
00930       volatile OrigFn        _orig = (orig);                      \
00931       volatile unsigned long _argvec[12];                         \
00932       volatile unsigned long _res;                                \
00933       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00934       _argvec[1] = (unsigned long)(arg1);                         \
00935       _argvec[2] = (unsigned long)(arg2);                         \
00936       _argvec[3] = (unsigned long)(arg3);                         \
00937       _argvec[4] = (unsigned long)(arg4);                         \
00938       _argvec[5] = (unsigned long)(arg5);                         \
00939       _argvec[6] = (unsigned long)(arg6);                         \
00940       _argvec[7] = (unsigned long)(arg7);                         \
00941       _argvec[8] = (unsigned long)(arg8);                         \
00942       _argvec[9] = (unsigned long)(arg9);                         \
00943       _argvec[10] = (unsigned long)(arg10);                       \
00944       _argvec[11] = (unsigned long)(arg11);                       \
00945       __asm__ volatile(                                           \
00946          "pushl 44(%%eax)\n\t"                                    \
00947          "pushl 40(%%eax)\n\t"                                    \
00948          "pushl 36(%%eax)\n\t"                                    \
00949          "pushl 32(%%eax)\n\t"                                    \
00950          "pushl 28(%%eax)\n\t"                                    \
00951          "pushl 24(%%eax)\n\t"                                    \
00952          "pushl 20(%%eax)\n\t"                                    \
00953          "pushl 16(%%eax)\n\t"                                    \
00954          "pushl 12(%%eax)\n\t"                                    \
00955          "pushl 8(%%eax)\n\t"                                     \
00956          "pushl 4(%%eax)\n\t"                                     \
00957          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
00958          VALGRIND_CALL_NOREDIR_EAX                                \
00959          "addl $44, %%esp\n"                                      \
00960          : /*out*/   "=a" (_res)                                  \
00961          : /*in*/    "a" (&_argvec[0])                            \
00962          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
00963       );                                                          \
00964       lval = (__typeof__(lval)) _res;                             \
00965    } while (0)
00966 
00967 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
00968                                   arg6,arg7,arg8,arg9,arg10,      \
00969                                   arg11,arg12)                    \
00970    do {                                                           \
00971       volatile OrigFn        _orig = (orig);                      \
00972       volatile unsigned long _argvec[13];                         \
00973       volatile unsigned long _res;                                \
00974       _argvec[0] = (unsigned long)_orig.nraddr;                   \
00975       _argvec[1] = (unsigned long)(arg1);                         \
00976       _argvec[2] = (unsigned long)(arg2);                         \
00977       _argvec[3] = (unsigned long)(arg3);                         \
00978       _argvec[4] = (unsigned long)(arg4);                         \
00979       _argvec[5] = (unsigned long)(arg5);                         \
00980       _argvec[6] = (unsigned long)(arg6);                         \
00981       _argvec[7] = (unsigned long)(arg7);                         \
00982       _argvec[8] = (unsigned long)(arg8);                         \
00983       _argvec[9] = (unsigned long)(arg9);                         \
00984       _argvec[10] = (unsigned long)(arg10);                       \
00985       _argvec[11] = (unsigned long)(arg11);                       \
00986       _argvec[12] = (unsigned long)(arg12);                       \
00987       __asm__ volatile(                                           \
00988          "pushl 48(%%eax)\n\t"                                    \
00989          "pushl 44(%%eax)\n\t"                                    \
00990          "pushl 40(%%eax)\n\t"                                    \
00991          "pushl 36(%%eax)\n\t"                                    \
00992          "pushl 32(%%eax)\n\t"                                    \
00993          "pushl 28(%%eax)\n\t"                                    \
00994          "pushl 24(%%eax)\n\t"                                    \
00995          "pushl 20(%%eax)\n\t"                                    \
00996          "pushl 16(%%eax)\n\t"                                    \
00997          "pushl 12(%%eax)\n\t"                                    \
00998          "pushl 8(%%eax)\n\t"                                     \
00999          "pushl 4(%%eax)\n\t"                                     \
01000          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
01001          VALGRIND_CALL_NOREDIR_EAX                                \
01002          "addl $48, %%esp\n"                                      \
01003          : /*out*/   "=a" (_res)                                  \
01004          : /*in*/    "a" (&_argvec[0])                            \
01005          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01006       );                                                          \
01007       lval = (__typeof__(lval)) _res;                             \
01008    } while (0)
01009 
01010 #endif /* PLAT_x86_linux */
01011 
01012 /* ------------------------ amd64-linux ------------------------ */
01013 
01014 #if defined(PLAT_amd64_linux)
01015 
01016 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
01017 
01018 /* These regs are trashed by the hidden call. */
01019 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi",       \
01020                             "rdi", "r8", "r9", "r10", "r11"
01021 
01022 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
01023    long) == 8. */
01024 
01025 /* NB 9 Sept 07.  There is a nasty kludge here in all these CALL_FN_
01026    macros.  In order not to trash the stack redzone, we need to drop
01027    %rsp by 128 before the hidden call, and restore afterwards.  The
01028    nastyness is that it is only by luck that the stack still appears
01029    to be unwindable during the hidden call - since then the behaviour
01030    of any routine using this macro does not match what the CFI data
01031    says.  Sigh.
01032 
01033    Why is this important?  Imagine that a wrapper has a stack
01034    allocated local, and passes to the hidden call, a pointer to it.
01035    Because gcc does not know about the hidden call, it may allocate
01036    that local in the redzone.  Unfortunately the hidden call may then
01037    trash it before it comes to use it.  So we must step clear of the
01038    redzone, for the duration of the hidden call, to make it safe.
01039 
01040    Probably the same problem afflicts the other redzone-style ABIs too
01041    (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
01042    self describing (none of this CFI nonsense) so at least messing
01043    with the stack pointer doesn't give a danger of non-unwindable
01044    stack. */
01045 
01046 #define CALL_FN_W_v(lval, orig)                                   \
01047    do {                                                           \
01048       volatile OrigFn        _orig = (orig);                      \
01049       volatile unsigned long _argvec[1];                          \
01050       volatile unsigned long _res;                                \
01051       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01052       __asm__ volatile(                                           \
01053          "subq $128,%%rsp\n\t"                                    \
01054          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01055          VALGRIND_CALL_NOREDIR_RAX                                \
01056          "addq $128,%%rsp\n\t"                                    \
01057          : /*out*/   "=a" (_res)                                  \
01058          : /*in*/    "a" (&_argvec[0])                            \
01059          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01060       );                                                          \
01061       lval = (__typeof__(lval)) _res;                             \
01062    } while (0)
01063 
01064 #define CALL_FN_W_W(lval, orig, arg1)                             \
01065    do {                                                           \
01066       volatile OrigFn        _orig = (orig);                      \
01067       volatile unsigned long _argvec[2];                          \
01068       volatile unsigned long _res;                                \
01069       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01070       _argvec[1] = (unsigned long)(arg1);                         \
01071       __asm__ volatile(                                           \
01072          "subq $128,%%rsp\n\t"                                    \
01073          "movq 8(%%rax), %%rdi\n\t"                               \
01074          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01075          VALGRIND_CALL_NOREDIR_RAX                                \
01076          "addq $128,%%rsp\n\t"                                    \
01077          : /*out*/   "=a" (_res)                                  \
01078          : /*in*/    "a" (&_argvec[0])                            \
01079          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01080       );                                                          \
01081       lval = (__typeof__(lval)) _res;                             \
01082    } while (0)
01083 
01084 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
01085    do {                                                           \
01086       volatile OrigFn        _orig = (orig);                      \
01087       volatile unsigned long _argvec[3];                          \
01088       volatile unsigned long _res;                                \
01089       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01090       _argvec[1] = (unsigned long)(arg1);                         \
01091       _argvec[2] = (unsigned long)(arg2);                         \
01092       __asm__ volatile(                                           \
01093          "subq $128,%%rsp\n\t"                                    \
01094          "movq 16(%%rax), %%rsi\n\t"                              \
01095          "movq 8(%%rax), %%rdi\n\t"                               \
01096          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01097          VALGRIND_CALL_NOREDIR_RAX                                \
01098          "addq $128,%%rsp\n\t"                                    \
01099          : /*out*/   "=a" (_res)                                  \
01100          : /*in*/    "a" (&_argvec[0])                            \
01101          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01102       );                                                          \
01103       lval = (__typeof__(lval)) _res;                             \
01104    } while (0)
01105 
01106 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
01107    do {                                                           \
01108       volatile OrigFn        _orig = (orig);                      \
01109       volatile unsigned long _argvec[4];                          \
01110       volatile unsigned long _res;                                \
01111       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01112       _argvec[1] = (unsigned long)(arg1);                         \
01113       _argvec[2] = (unsigned long)(arg2);                         \
01114       _argvec[3] = (unsigned long)(arg3);                         \
01115       __asm__ volatile(                                           \
01116          "subq $128,%%rsp\n\t"                                    \
01117          "movq 24(%%rax), %%rdx\n\t"                              \
01118          "movq 16(%%rax), %%rsi\n\t"                              \
01119          "movq 8(%%rax), %%rdi\n\t"                               \
01120          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01121          VALGRIND_CALL_NOREDIR_RAX                                \
01122          "addq $128,%%rsp\n\t"                                    \
01123          : /*out*/   "=a" (_res)                                  \
01124          : /*in*/    "a" (&_argvec[0])                            \
01125          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01126       );                                                          \
01127       lval = (__typeof__(lval)) _res;                             \
01128    } while (0)
01129 
01130 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
01131    do {                                                           \
01132       volatile OrigFn        _orig = (orig);                      \
01133       volatile unsigned long _argvec[5];                          \
01134       volatile unsigned long _res;                                \
01135       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01136       _argvec[1] = (unsigned long)(arg1);                         \
01137       _argvec[2] = (unsigned long)(arg2);                         \
01138       _argvec[3] = (unsigned long)(arg3);                         \
01139       _argvec[4] = (unsigned long)(arg4);                         \
01140       __asm__ volatile(                                           \
01141          "subq $128,%%rsp\n\t"                                    \
01142          "movq 32(%%rax), %%rcx\n\t"                              \
01143          "movq 24(%%rax), %%rdx\n\t"                              \
01144          "movq 16(%%rax), %%rsi\n\t"                              \
01145          "movq 8(%%rax), %%rdi\n\t"                               \
01146          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01147          VALGRIND_CALL_NOREDIR_RAX                                \
01148          "addq $128,%%rsp\n\t"                                    \
01149          : /*out*/   "=a" (_res)                                  \
01150          : /*in*/    "a" (&_argvec[0])                            \
01151          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01152       );                                                          \
01153       lval = (__typeof__(lval)) _res;                             \
01154    } while (0)
01155 
01156 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
01157    do {                                                           \
01158       volatile OrigFn        _orig = (orig);                      \
01159       volatile unsigned long _argvec[6];                          \
01160       volatile unsigned long _res;                                \
01161       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01162       _argvec[1] = (unsigned long)(arg1);                         \
01163       _argvec[2] = (unsigned long)(arg2);                         \
01164       _argvec[3] = (unsigned long)(arg3);                         \
01165       _argvec[4] = (unsigned long)(arg4);                         \
01166       _argvec[5] = (unsigned long)(arg5);                         \
01167       __asm__ volatile(                                           \
01168          "subq $128,%%rsp\n\t"                                    \
01169          "movq 40(%%rax), %%r8\n\t"                               \
01170          "movq 32(%%rax), %%rcx\n\t"                              \
01171          "movq 24(%%rax), %%rdx\n\t"                              \
01172          "movq 16(%%rax), %%rsi\n\t"                              \
01173          "movq 8(%%rax), %%rdi\n\t"                               \
01174          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01175          VALGRIND_CALL_NOREDIR_RAX                                \
01176          "addq $128,%%rsp\n\t"                                    \
01177          : /*out*/   "=a" (_res)                                  \
01178          : /*in*/    "a" (&_argvec[0])                            \
01179          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01180       );                                                          \
01181       lval = (__typeof__(lval)) _res;                             \
01182    } while (0)
01183 
01184 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
01185    do {                                                           \
01186       volatile OrigFn        _orig = (orig);                      \
01187       volatile unsigned long _argvec[7];                          \
01188       volatile unsigned long _res;                                \
01189       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01190       _argvec[1] = (unsigned long)(arg1);                         \
01191       _argvec[2] = (unsigned long)(arg2);                         \
01192       _argvec[3] = (unsigned long)(arg3);                         \
01193       _argvec[4] = (unsigned long)(arg4);                         \
01194       _argvec[5] = (unsigned long)(arg5);                         \
01195       _argvec[6] = (unsigned long)(arg6);                         \
01196       __asm__ volatile(                                           \
01197          "subq $128,%%rsp\n\t"                                    \
01198          "movq 48(%%rax), %%r9\n\t"                               \
01199          "movq 40(%%rax), %%r8\n\t"                               \
01200          "movq 32(%%rax), %%rcx\n\t"                              \
01201          "movq 24(%%rax), %%rdx\n\t"                              \
01202          "movq 16(%%rax), %%rsi\n\t"                              \
01203          "movq 8(%%rax), %%rdi\n\t"                               \
01204          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01205          "addq $128,%%rsp\n\t"                                    \
01206          VALGRIND_CALL_NOREDIR_RAX                                \
01207          : /*out*/   "=a" (_res)                                  \
01208          : /*in*/    "a" (&_argvec[0])                            \
01209          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01210       );                                                          \
01211       lval = (__typeof__(lval)) _res;                             \
01212    } while (0)
01213 
01214 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
01215                                  arg7)                            \
01216    do {                                                           \
01217       volatile OrigFn        _orig = (orig);                      \
01218       volatile unsigned long _argvec[8];                          \
01219       volatile unsigned long _res;                                \
01220       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01221       _argvec[1] = (unsigned long)(arg1);                         \
01222       _argvec[2] = (unsigned long)(arg2);                         \
01223       _argvec[3] = (unsigned long)(arg3);                         \
01224       _argvec[4] = (unsigned long)(arg4);                         \
01225       _argvec[5] = (unsigned long)(arg5);                         \
01226       _argvec[6] = (unsigned long)(arg6);                         \
01227       _argvec[7] = (unsigned long)(arg7);                         \
01228       __asm__ volatile(                                           \
01229          "subq $128,%%rsp\n\t"                                    \
01230          "pushq 56(%%rax)\n\t"                                    \
01231          "movq 48(%%rax), %%r9\n\t"                               \
01232          "movq 40(%%rax), %%r8\n\t"                               \
01233          "movq 32(%%rax), %%rcx\n\t"                              \
01234          "movq 24(%%rax), %%rdx\n\t"                              \
01235          "movq 16(%%rax), %%rsi\n\t"                              \
01236          "movq 8(%%rax), %%rdi\n\t"                               \
01237          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01238          VALGRIND_CALL_NOREDIR_RAX                                \
01239          "addq $8, %%rsp\n"                                       \
01240          "addq $128,%%rsp\n\t"                                    \
01241          : /*out*/   "=a" (_res)                                  \
01242          : /*in*/    "a" (&_argvec[0])                            \
01243          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01244       );                                                          \
01245       lval = (__typeof__(lval)) _res;                             \
01246    } while (0)
01247 
01248 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
01249                                  arg7,arg8)                       \
01250    do {                                                           \
01251       volatile OrigFn        _orig = (orig);                      \
01252       volatile unsigned long _argvec[9];                          \
01253       volatile unsigned long _res;                                \
01254       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01255       _argvec[1] = (unsigned long)(arg1);                         \
01256       _argvec[2] = (unsigned long)(arg2);                         \
01257       _argvec[3] = (unsigned long)(arg3);                         \
01258       _argvec[4] = (unsigned long)(arg4);                         \
01259       _argvec[5] = (unsigned long)(arg5);                         \
01260       _argvec[6] = (unsigned long)(arg6);                         \
01261       _argvec[7] = (unsigned long)(arg7);                         \
01262       _argvec[8] = (unsigned long)(arg8);                         \
01263       __asm__ volatile(                                           \
01264          "subq $128,%%rsp\n\t"                                    \
01265          "pushq 64(%%rax)\n\t"                                    \
01266          "pushq 56(%%rax)\n\t"                                    \
01267          "movq 48(%%rax), %%r9\n\t"                               \
01268          "movq 40(%%rax), %%r8\n\t"                               \
01269          "movq 32(%%rax), %%rcx\n\t"                              \
01270          "movq 24(%%rax), %%rdx\n\t"                              \
01271          "movq 16(%%rax), %%rsi\n\t"                              \
01272          "movq 8(%%rax), %%rdi\n\t"                               \
01273          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01274          VALGRIND_CALL_NOREDIR_RAX                                \
01275          "addq $16, %%rsp\n"                                      \
01276          "addq $128,%%rsp\n\t"                                    \
01277          : /*out*/   "=a" (_res)                                  \
01278          : /*in*/    "a" (&_argvec[0])                            \
01279          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01280       );                                                          \
01281       lval = (__typeof__(lval)) _res;                             \
01282    } while (0)
01283 
01284 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
01285                                  arg7,arg8,arg9)                  \
01286    do {                                                           \
01287       volatile OrigFn        _orig = (orig);                      \
01288       volatile unsigned long _argvec[10];                         \
01289       volatile unsigned long _res;                                \
01290       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01291       _argvec[1] = (unsigned long)(arg1);                         \
01292       _argvec[2] = (unsigned long)(arg2);                         \
01293       _argvec[3] = (unsigned long)(arg3);                         \
01294       _argvec[4] = (unsigned long)(arg4);                         \
01295       _argvec[5] = (unsigned long)(arg5);                         \
01296       _argvec[6] = (unsigned long)(arg6);                         \
01297       _argvec[7] = (unsigned long)(arg7);                         \
01298       _argvec[8] = (unsigned long)(arg8);                         \
01299       _argvec[9] = (unsigned long)(arg9);                         \
01300       __asm__ volatile(                                           \
01301          "subq $128,%%rsp\n\t"                                    \
01302          "pushq 72(%%rax)\n\t"                                    \
01303          "pushq 64(%%rax)\n\t"                                    \
01304          "pushq 56(%%rax)\n\t"                                    \
01305          "movq 48(%%rax), %%r9\n\t"                               \
01306          "movq 40(%%rax), %%r8\n\t"                               \
01307          "movq 32(%%rax), %%rcx\n\t"                              \
01308          "movq 24(%%rax), %%rdx\n\t"                              \
01309          "movq 16(%%rax), %%rsi\n\t"                              \
01310          "movq 8(%%rax), %%rdi\n\t"                               \
01311          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01312          VALGRIND_CALL_NOREDIR_RAX                                \
01313          "addq $24, %%rsp\n"                                      \
01314          "addq $128,%%rsp\n\t"                                    \
01315          : /*out*/   "=a" (_res)                                  \
01316          : /*in*/    "a" (&_argvec[0])                            \
01317          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01318       );                                                          \
01319       lval = (__typeof__(lval)) _res;                             \
01320    } while (0)
01321 
01322 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
01323                                   arg7,arg8,arg9,arg10)           \
01324    do {                                                           \
01325       volatile OrigFn        _orig = (orig);                      \
01326       volatile unsigned long _argvec[11];                         \
01327       volatile unsigned long _res;                                \
01328       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01329       _argvec[1] = (unsigned long)(arg1);                         \
01330       _argvec[2] = (unsigned long)(arg2);                         \
01331       _argvec[3] = (unsigned long)(arg3);                         \
01332       _argvec[4] = (unsigned long)(arg4);                         \
01333       _argvec[5] = (unsigned long)(arg5);                         \
01334       _argvec[6] = (unsigned long)(arg6);                         \
01335       _argvec[7] = (unsigned long)(arg7);                         \
01336       _argvec[8] = (unsigned long)(arg8);                         \
01337       _argvec[9] = (unsigned long)(arg9);                         \
01338       _argvec[10] = (unsigned long)(arg10);                       \
01339       __asm__ volatile(                                           \
01340          "subq $128,%%rsp\n\t"                                    \
01341          "pushq 80(%%rax)\n\t"                                    \
01342          "pushq 72(%%rax)\n\t"                                    \
01343          "pushq 64(%%rax)\n\t"                                    \
01344          "pushq 56(%%rax)\n\t"                                    \
01345          "movq 48(%%rax), %%r9\n\t"                               \
01346          "movq 40(%%rax), %%r8\n\t"                               \
01347          "movq 32(%%rax), %%rcx\n\t"                              \
01348          "movq 24(%%rax), %%rdx\n\t"                              \
01349          "movq 16(%%rax), %%rsi\n\t"                              \
01350          "movq 8(%%rax), %%rdi\n\t"                               \
01351          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01352          VALGRIND_CALL_NOREDIR_RAX                                \
01353          "addq $32, %%rsp\n"                                      \
01354          "addq $128,%%rsp\n\t"                                    \
01355          : /*out*/   "=a" (_res)                                  \
01356          : /*in*/    "a" (&_argvec[0])                            \
01357          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01358       );                                                          \
01359       lval = (__typeof__(lval)) _res;                             \
01360    } while (0)
01361 
01362 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
01363                                   arg7,arg8,arg9,arg10,arg11)     \
01364    do {                                                           \
01365       volatile OrigFn        _orig = (orig);                      \
01366       volatile unsigned long _argvec[12];                         \
01367       volatile unsigned long _res;                                \
01368       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01369       _argvec[1] = (unsigned long)(arg1);                         \
01370       _argvec[2] = (unsigned long)(arg2);                         \
01371       _argvec[3] = (unsigned long)(arg3);                         \
01372       _argvec[4] = (unsigned long)(arg4);                         \
01373       _argvec[5] = (unsigned long)(arg5);                         \
01374       _argvec[6] = (unsigned long)(arg6);                         \
01375       _argvec[7] = (unsigned long)(arg7);                         \
01376       _argvec[8] = (unsigned long)(arg8);                         \
01377       _argvec[9] = (unsigned long)(arg9);                         \
01378       _argvec[10] = (unsigned long)(arg10);                       \
01379       _argvec[11] = (unsigned long)(arg11);                       \
01380       __asm__ volatile(                                           \
01381          "subq $128,%%rsp\n\t"                                    \
01382          "pushq 88(%%rax)\n\t"                                    \
01383          "pushq 80(%%rax)\n\t"                                    \
01384          "pushq 72(%%rax)\n\t"                                    \
01385          "pushq 64(%%rax)\n\t"                                    \
01386          "pushq 56(%%rax)\n\t"                                    \
01387          "movq 48(%%rax), %%r9\n\t"                               \
01388          "movq 40(%%rax), %%r8\n\t"                               \
01389          "movq 32(%%rax), %%rcx\n\t"                              \
01390          "movq 24(%%rax), %%rdx\n\t"                              \
01391          "movq 16(%%rax), %%rsi\n\t"                              \
01392          "movq 8(%%rax), %%rdi\n\t"                               \
01393          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01394          VALGRIND_CALL_NOREDIR_RAX                                \
01395          "addq $40, %%rsp\n"                                      \
01396          "addq $128,%%rsp\n\t"                                    \
01397          : /*out*/   "=a" (_res)                                  \
01398          : /*in*/    "a" (&_argvec[0])                            \
01399          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01400       );                                                          \
01401       lval = (__typeof__(lval)) _res;                             \
01402    } while (0)
01403 
01404 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
01405                                 arg7,arg8,arg9,arg10,arg11,arg12) \
01406    do {                                                           \
01407       volatile OrigFn        _orig = (orig);                      \
01408       volatile unsigned long _argvec[13];                         \
01409       volatile unsigned long _res;                                \
01410       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01411       _argvec[1] = (unsigned long)(arg1);                         \
01412       _argvec[2] = (unsigned long)(arg2);                         \
01413       _argvec[3] = (unsigned long)(arg3);                         \
01414       _argvec[4] = (unsigned long)(arg4);                         \
01415       _argvec[5] = (unsigned long)(arg5);                         \
01416       _argvec[6] = (unsigned long)(arg6);                         \
01417       _argvec[7] = (unsigned long)(arg7);                         \
01418       _argvec[8] = (unsigned long)(arg8);                         \
01419       _argvec[9] = (unsigned long)(arg9);                         \
01420       _argvec[10] = (unsigned long)(arg10);                       \
01421       _argvec[11] = (unsigned long)(arg11);                       \
01422       _argvec[12] = (unsigned long)(arg12);                       \
01423       __asm__ volatile(                                           \
01424          "subq $128,%%rsp\n\t"                                    \
01425          "pushq 96(%%rax)\n\t"                                    \
01426          "pushq 88(%%rax)\n\t"                                    \
01427          "pushq 80(%%rax)\n\t"                                    \
01428          "pushq 72(%%rax)\n\t"                                    \
01429          "pushq 64(%%rax)\n\t"                                    \
01430          "pushq 56(%%rax)\n\t"                                    \
01431          "movq 48(%%rax), %%r9\n\t"                               \
01432          "movq 40(%%rax), %%r8\n\t"                               \
01433          "movq 32(%%rax), %%rcx\n\t"                              \
01434          "movq 24(%%rax), %%rdx\n\t"                              \
01435          "movq 16(%%rax), %%rsi\n\t"                              \
01436          "movq 8(%%rax), %%rdi\n\t"                               \
01437          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
01438          VALGRIND_CALL_NOREDIR_RAX                                \
01439          "addq $48, %%rsp\n"                                      \
01440          "addq $128,%%rsp\n\t"                                    \
01441          : /*out*/   "=a" (_res)                                  \
01442          : /*in*/    "a" (&_argvec[0])                            \
01443          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01444       );                                                          \
01445       lval = (__typeof__(lval)) _res;                             \
01446    } while (0)
01447 
01448 #endif /* PLAT_amd64_linux */
01449 
01450 /* ------------------------ ppc32-linux ------------------------ */
01451 
01452 #if defined(PLAT_ppc32_linux)
01453 
01454 /* This is useful for finding out about the on-stack stuff:
01455 
01456    extern int f9  ( int,int,int,int,int,int,int,int,int );
01457    extern int f10 ( int,int,int,int,int,int,int,int,int,int );
01458    extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
01459    extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
01460 
01461    int g9 ( void ) {
01462       return f9(11,22,33,44,55,66,77,88,99);
01463    }
01464    int g10 ( void ) {
01465       return f10(11,22,33,44,55,66,77,88,99,110);
01466    }
01467    int g11 ( void ) {
01468       return f11(11,22,33,44,55,66,77,88,99,110,121);
01469    }
01470    int g12 ( void ) {
01471       return f12(11,22,33,44,55,66,77,88,99,110,121,132);
01472    }
01473 */
01474 
01475 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
01476 
01477 /* These regs are trashed by the hidden call. */
01478 #define __CALLER_SAVED_REGS                                       \
01479    "lr", "ctr", "xer",                                            \
01480    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
01481    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
01482    "r11", "r12", "r13"
01483 
01484 /* These CALL_FN_ macros assume that on ppc32-linux, 
01485    sizeof(unsigned long) == 4. */
01486 
01487 #define CALL_FN_W_v(lval, orig)                                   \
01488    do {                                                           \
01489       volatile OrigFn        _orig = (orig);                      \
01490       volatile unsigned long _argvec[1];                          \
01491       volatile unsigned long _res;                                \
01492       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01493       __asm__ volatile(                                           \
01494          "mr 11,%1\n\t"                                           \
01495          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01496          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01497          "mr %0,3"                                                \
01498          : /*out*/   "=r" (_res)                                  \
01499          : /*in*/    "r" (&_argvec[0])                            \
01500          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01501       );                                                          \
01502       lval = (__typeof__(lval)) _res;                             \
01503    } while (0)
01504 
01505 #define CALL_FN_W_W(lval, orig, arg1)                             \
01506    do {                                                           \
01507       volatile OrigFn        _orig = (orig);                      \
01508       volatile unsigned long _argvec[2];                          \
01509       volatile unsigned long _res;                                \
01510       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01511       _argvec[1] = (unsigned long)arg1;                           \
01512       __asm__ volatile(                                           \
01513          "mr 11,%1\n\t"                                           \
01514          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01515          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01516          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01517          "mr %0,3"                                                \
01518          : /*out*/   "=r" (_res)                                  \
01519          : /*in*/    "r" (&_argvec[0])                            \
01520          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01521       );                                                          \
01522       lval = (__typeof__(lval)) _res;                             \
01523    } while (0)
01524 
01525 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
01526    do {                                                           \
01527       volatile OrigFn        _orig = (orig);                      \
01528       volatile unsigned long _argvec[3];                          \
01529       volatile unsigned long _res;                                \
01530       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01531       _argvec[1] = (unsigned long)arg1;                           \
01532       _argvec[2] = (unsigned long)arg2;                           \
01533       __asm__ volatile(                                           \
01534          "mr 11,%1\n\t"                                           \
01535          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01536          "lwz 4,8(11)\n\t"                                        \
01537          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01538          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01539          "mr %0,3"                                                \
01540          : /*out*/   "=r" (_res)                                  \
01541          : /*in*/    "r" (&_argvec[0])                            \
01542          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01543       );                                                          \
01544       lval = (__typeof__(lval)) _res;                             \
01545    } while (0)
01546 
01547 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
01548    do {                                                           \
01549       volatile OrigFn        _orig = (orig);                      \
01550       volatile unsigned long _argvec[4];                          \
01551       volatile unsigned long _res;                                \
01552       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01553       _argvec[1] = (unsigned long)arg1;                           \
01554       _argvec[2] = (unsigned long)arg2;                           \
01555       _argvec[3] = (unsigned long)arg3;                           \
01556       __asm__ volatile(                                           \
01557          "mr 11,%1\n\t"                                           \
01558          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01559          "lwz 4,8(11)\n\t"                                        \
01560          "lwz 5,12(11)\n\t"                                       \
01561          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01562          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01563          "mr %0,3"                                                \
01564          : /*out*/   "=r" (_res)                                  \
01565          : /*in*/    "r" (&_argvec[0])                            \
01566          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01567       );                                                          \
01568       lval = (__typeof__(lval)) _res;                             \
01569    } while (0)
01570 
01571 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
01572    do {                                                           \
01573       volatile OrigFn        _orig = (orig);                      \
01574       volatile unsigned long _argvec[5];                          \
01575       volatile unsigned long _res;                                \
01576       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01577       _argvec[1] = (unsigned long)arg1;                           \
01578       _argvec[2] = (unsigned long)arg2;                           \
01579       _argvec[3] = (unsigned long)arg3;                           \
01580       _argvec[4] = (unsigned long)arg4;                           \
01581       __asm__ volatile(                                           \
01582          "mr 11,%1\n\t"                                           \
01583          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01584          "lwz 4,8(11)\n\t"                                        \
01585          "lwz 5,12(11)\n\t"                                       \
01586          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01587          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01588          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01589          "mr %0,3"                                                \
01590          : /*out*/   "=r" (_res)                                  \
01591          : /*in*/    "r" (&_argvec[0])                            \
01592          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01593       );                                                          \
01594       lval = (__typeof__(lval)) _res;                             \
01595    } while (0)
01596 
01597 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
01598    do {                                                           \
01599       volatile OrigFn        _orig = (orig);                      \
01600       volatile unsigned long _argvec[6];                          \
01601       volatile unsigned long _res;                                \
01602       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01603       _argvec[1] = (unsigned long)arg1;                           \
01604       _argvec[2] = (unsigned long)arg2;                           \
01605       _argvec[3] = (unsigned long)arg3;                           \
01606       _argvec[4] = (unsigned long)arg4;                           \
01607       _argvec[5] = (unsigned long)arg5;                           \
01608       __asm__ volatile(                                           \
01609          "mr 11,%1\n\t"                                           \
01610          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01611          "lwz 4,8(11)\n\t"                                        \
01612          "lwz 5,12(11)\n\t"                                       \
01613          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01614          "lwz 7,20(11)\n\t"                                       \
01615          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01616          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01617          "mr %0,3"                                                \
01618          : /*out*/   "=r" (_res)                                  \
01619          : /*in*/    "r" (&_argvec[0])                            \
01620          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01621       );                                                          \
01622       lval = (__typeof__(lval)) _res;                             \
01623    } while (0)
01624 
01625 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
01626    do {                                                           \
01627       volatile OrigFn        _orig = (orig);                      \
01628       volatile unsigned long _argvec[7];                          \
01629       volatile unsigned long _res;                                \
01630       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01631       _argvec[1] = (unsigned long)arg1;                           \
01632       _argvec[2] = (unsigned long)arg2;                           \
01633       _argvec[3] = (unsigned long)arg3;                           \
01634       _argvec[4] = (unsigned long)arg4;                           \
01635       _argvec[5] = (unsigned long)arg5;                           \
01636       _argvec[6] = (unsigned long)arg6;                           \
01637       __asm__ volatile(                                           \
01638          "mr 11,%1\n\t"                                           \
01639          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01640          "lwz 4,8(11)\n\t"                                        \
01641          "lwz 5,12(11)\n\t"                                       \
01642          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01643          "lwz 7,20(11)\n\t"                                       \
01644          "lwz 8,24(11)\n\t"                                       \
01645          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01646          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01647          "mr %0,3"                                                \
01648          : /*out*/   "=r" (_res)                                  \
01649          : /*in*/    "r" (&_argvec[0])                            \
01650          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01651       );                                                          \
01652       lval = (__typeof__(lval)) _res;                             \
01653    } while (0)
01654 
01655 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
01656                                  arg7)                            \
01657    do {                                                           \
01658       volatile OrigFn        _orig = (orig);                      \
01659       volatile unsigned long _argvec[8];                          \
01660       volatile unsigned long _res;                                \
01661       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01662       _argvec[1] = (unsigned long)arg1;                           \
01663       _argvec[2] = (unsigned long)arg2;                           \
01664       _argvec[3] = (unsigned long)arg3;                           \
01665       _argvec[4] = (unsigned long)arg4;                           \
01666       _argvec[5] = (unsigned long)arg5;                           \
01667       _argvec[6] = (unsigned long)arg6;                           \
01668       _argvec[7] = (unsigned long)arg7;                           \
01669       __asm__ volatile(                                           \
01670          "mr 11,%1\n\t"                                           \
01671          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01672          "lwz 4,8(11)\n\t"                                        \
01673          "lwz 5,12(11)\n\t"                                       \
01674          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01675          "lwz 7,20(11)\n\t"                                       \
01676          "lwz 8,24(11)\n\t"                                       \
01677          "lwz 9,28(11)\n\t"                                       \
01678          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01679          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01680          "mr %0,3"                                                \
01681          : /*out*/   "=r" (_res)                                  \
01682          : /*in*/    "r" (&_argvec[0])                            \
01683          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01684       );                                                          \
01685       lval = (__typeof__(lval)) _res;                             \
01686    } while (0)
01687 
01688 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
01689                                  arg7,arg8)                       \
01690    do {                                                           \
01691       volatile OrigFn        _orig = (orig);                      \
01692       volatile unsigned long _argvec[9];                          \
01693       volatile unsigned long _res;                                \
01694       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01695       _argvec[1] = (unsigned long)arg1;                           \
01696       _argvec[2] = (unsigned long)arg2;                           \
01697       _argvec[3] = (unsigned long)arg3;                           \
01698       _argvec[4] = (unsigned long)arg4;                           \
01699       _argvec[5] = (unsigned long)arg5;                           \
01700       _argvec[6] = (unsigned long)arg6;                           \
01701       _argvec[7] = (unsigned long)arg7;                           \
01702       _argvec[8] = (unsigned long)arg8;                           \
01703       __asm__ volatile(                                           \
01704          "mr 11,%1\n\t"                                           \
01705          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01706          "lwz 4,8(11)\n\t"                                        \
01707          "lwz 5,12(11)\n\t"                                       \
01708          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01709          "lwz 7,20(11)\n\t"                                       \
01710          "lwz 8,24(11)\n\t"                                       \
01711          "lwz 9,28(11)\n\t"                                       \
01712          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
01713          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01714          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01715          "mr %0,3"                                                \
01716          : /*out*/   "=r" (_res)                                  \
01717          : /*in*/    "r" (&_argvec[0])                            \
01718          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01719       );                                                          \
01720       lval = (__typeof__(lval)) _res;                             \
01721    } while (0)
01722 
01723 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
01724                                  arg7,arg8,arg9)                  \
01725    do {                                                           \
01726       volatile OrigFn        _orig = (orig);                      \
01727       volatile unsigned long _argvec[10];                         \
01728       volatile unsigned long _res;                                \
01729       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01730       _argvec[1] = (unsigned long)arg1;                           \
01731       _argvec[2] = (unsigned long)arg2;                           \
01732       _argvec[3] = (unsigned long)arg3;                           \
01733       _argvec[4] = (unsigned long)arg4;                           \
01734       _argvec[5] = (unsigned long)arg5;                           \
01735       _argvec[6] = (unsigned long)arg6;                           \
01736       _argvec[7] = (unsigned long)arg7;                           \
01737       _argvec[8] = (unsigned long)arg8;                           \
01738       _argvec[9] = (unsigned long)arg9;                           \
01739       __asm__ volatile(                                           \
01740          "mr 11,%1\n\t"                                           \
01741          "addi 1,1,-16\n\t"                                       \
01742          /* arg9 */                                               \
01743          "lwz 3,36(11)\n\t"                                       \
01744          "stw 3,8(1)\n\t"                                         \
01745          /* args1-8 */                                            \
01746          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01747          "lwz 4,8(11)\n\t"                                        \
01748          "lwz 5,12(11)\n\t"                                       \
01749          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01750          "lwz 7,20(11)\n\t"                                       \
01751          "lwz 8,24(11)\n\t"                                       \
01752          "lwz 9,28(11)\n\t"                                       \
01753          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
01754          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01755          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01756          "addi 1,1,16\n\t"                                        \
01757          "mr %0,3"                                                \
01758          : /*out*/   "=r" (_res)                                  \
01759          : /*in*/    "r" (&_argvec[0])                            \
01760          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01761       );                                                          \
01762       lval = (__typeof__(lval)) _res;                             \
01763    } while (0)
01764 
01765 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
01766                                   arg7,arg8,arg9,arg10)           \
01767    do {                                                           \
01768       volatile OrigFn        _orig = (orig);                      \
01769       volatile unsigned long _argvec[11];                         \
01770       volatile unsigned long _res;                                \
01771       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01772       _argvec[1] = (unsigned long)arg1;                           \
01773       _argvec[2] = (unsigned long)arg2;                           \
01774       _argvec[3] = (unsigned long)arg3;                           \
01775       _argvec[4] = (unsigned long)arg4;                           \
01776       _argvec[5] = (unsigned long)arg5;                           \
01777       _argvec[6] = (unsigned long)arg6;                           \
01778       _argvec[7] = (unsigned long)arg7;                           \
01779       _argvec[8] = (unsigned long)arg8;                           \
01780       _argvec[9] = (unsigned long)arg9;                           \
01781       _argvec[10] = (unsigned long)arg10;                         \
01782       __asm__ volatile(                                           \
01783          "mr 11,%1\n\t"                                           \
01784          "addi 1,1,-16\n\t"                                       \
01785          /* arg10 */                                              \
01786          "lwz 3,40(11)\n\t"                                       \
01787          "stw 3,12(1)\n\t"                                        \
01788          /* arg9 */                                               \
01789          "lwz 3,36(11)\n\t"                                       \
01790          "stw 3,8(1)\n\t"                                         \
01791          /* args1-8 */                                            \
01792          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01793          "lwz 4,8(11)\n\t"                                        \
01794          "lwz 5,12(11)\n\t"                                       \
01795          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01796          "lwz 7,20(11)\n\t"                                       \
01797          "lwz 8,24(11)\n\t"                                       \
01798          "lwz 9,28(11)\n\t"                                       \
01799          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
01800          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01801          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01802          "addi 1,1,16\n\t"                                        \
01803          "mr %0,3"                                                \
01804          : /*out*/   "=r" (_res)                                  \
01805          : /*in*/    "r" (&_argvec[0])                            \
01806          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01807       );                                                          \
01808       lval = (__typeof__(lval)) _res;                             \
01809    } while (0)
01810 
01811 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
01812                                   arg7,arg8,arg9,arg10,arg11)     \
01813    do {                                                           \
01814       volatile OrigFn        _orig = (orig);                      \
01815       volatile unsigned long _argvec[12];                         \
01816       volatile unsigned long _res;                                \
01817       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01818       _argvec[1] = (unsigned long)arg1;                           \
01819       _argvec[2] = (unsigned long)arg2;                           \
01820       _argvec[3] = (unsigned long)arg3;                           \
01821       _argvec[4] = (unsigned long)arg4;                           \
01822       _argvec[5] = (unsigned long)arg5;                           \
01823       _argvec[6] = (unsigned long)arg6;                           \
01824       _argvec[7] = (unsigned long)arg7;                           \
01825       _argvec[8] = (unsigned long)arg8;                           \
01826       _argvec[9] = (unsigned long)arg9;                           \
01827       _argvec[10] = (unsigned long)arg10;                         \
01828       _argvec[11] = (unsigned long)arg11;                         \
01829       __asm__ volatile(                                           \
01830          "mr 11,%1\n\t"                                           \
01831          "addi 1,1,-32\n\t"                                       \
01832          /* arg11 */                                              \
01833          "lwz 3,44(11)\n\t"                                       \
01834          "stw 3,16(1)\n\t"                                        \
01835          /* arg10 */                                              \
01836          "lwz 3,40(11)\n\t"                                       \
01837          "stw 3,12(1)\n\t"                                        \
01838          /* arg9 */                                               \
01839          "lwz 3,36(11)\n\t"                                       \
01840          "stw 3,8(1)\n\t"                                         \
01841          /* args1-8 */                                            \
01842          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01843          "lwz 4,8(11)\n\t"                                        \
01844          "lwz 5,12(11)\n\t"                                       \
01845          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01846          "lwz 7,20(11)\n\t"                                       \
01847          "lwz 8,24(11)\n\t"                                       \
01848          "lwz 9,28(11)\n\t"                                       \
01849          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
01850          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01851          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01852          "addi 1,1,32\n\t"                                        \
01853          "mr %0,3"                                                \
01854          : /*out*/   "=r" (_res)                                  \
01855          : /*in*/    "r" (&_argvec[0])                            \
01856          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01857       );                                                          \
01858       lval = (__typeof__(lval)) _res;                             \
01859    } while (0)
01860 
01861 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
01862                                 arg7,arg8,arg9,arg10,arg11,arg12) \
01863    do {                                                           \
01864       volatile OrigFn        _orig = (orig);                      \
01865       volatile unsigned long _argvec[13];                         \
01866       volatile unsigned long _res;                                \
01867       _argvec[0] = (unsigned long)_orig.nraddr;                   \
01868       _argvec[1] = (unsigned long)arg1;                           \
01869       _argvec[2] = (unsigned long)arg2;                           \
01870       _argvec[3] = (unsigned long)arg3;                           \
01871       _argvec[4] = (unsigned long)arg4;                           \
01872       _argvec[5] = (unsigned long)arg5;                           \
01873       _argvec[6] = (unsigned long)arg6;                           \
01874       _argvec[7] = (unsigned long)arg7;                           \
01875       _argvec[8] = (unsigned long)arg8;                           \
01876       _argvec[9] = (unsigned long)arg9;                           \
01877       _argvec[10] = (unsigned long)arg10;                         \
01878       _argvec[11] = (unsigned long)arg11;                         \
01879       _argvec[12] = (unsigned long)arg12;                         \
01880       __asm__ volatile(                                           \
01881          "mr 11,%1\n\t"                                           \
01882          "addi 1,1,-32\n\t"                                       \
01883          /* arg12 */                                              \
01884          "lwz 3,48(11)\n\t"                                       \
01885          "stw 3,20(1)\n\t"                                        \
01886          /* arg11 */                                              \
01887          "lwz 3,44(11)\n\t"                                       \
01888          "stw 3,16(1)\n\t"                                        \
01889          /* arg10 */                                              \
01890          "lwz 3,40(11)\n\t"                                       \
01891          "stw 3,12(1)\n\t"                                        \
01892          /* arg9 */                                               \
01893          "lwz 3,36(11)\n\t"                                       \
01894          "stw 3,8(1)\n\t"                                         \
01895          /* args1-8 */                                            \
01896          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
01897          "lwz 4,8(11)\n\t"                                        \
01898          "lwz 5,12(11)\n\t"                                       \
01899          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
01900          "lwz 7,20(11)\n\t"                                       \
01901          "lwz 8,24(11)\n\t"                                       \
01902          "lwz 9,28(11)\n\t"                                       \
01903          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
01904          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
01905          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01906          "addi 1,1,32\n\t"                                        \
01907          "mr %0,3"                                                \
01908          : /*out*/   "=r" (_res)                                  \
01909          : /*in*/    "r" (&_argvec[0])                            \
01910          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01911       );                                                          \
01912       lval = (__typeof__(lval)) _res;                             \
01913    } while (0)
01914 
01915 #endif /* PLAT_ppc32_linux */
01916 
01917 /* ------------------------ ppc64-linux ------------------------ */
01918 
01919 #if defined(PLAT_ppc64_linux)
01920 
01921 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
01922 
01923 /* These regs are trashed by the hidden call. */
01924 #define __CALLER_SAVED_REGS                                       \
01925    "lr", "ctr", "xer",                                            \
01926    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
01927    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
01928    "r11", "r12", "r13"
01929 
01930 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
01931    long) == 8. */
01932 
01933 #define CALL_FN_W_v(lval, orig)                                   \
01934    do {                                                           \
01935       volatile OrigFn        _orig = (orig);                      \
01936       volatile unsigned long _argvec[3+0];                        \
01937       volatile unsigned long _res;                                \
01938       /* _argvec[0] holds current r2 across the call */           \
01939       _argvec[1] = (unsigned long)_orig.r2;                       \
01940       _argvec[2] = (unsigned long)_orig.nraddr;                   \
01941       __asm__ volatile(                                           \
01942          "mr 11,%1\n\t"                                           \
01943          "std 2,-16(11)\n\t"  /* save tocptr */                   \
01944          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
01945          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
01946          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01947          "mr 11,%1\n\t"                                           \
01948          "mr %0,3\n\t"                                            \
01949          "ld 2,-16(11)" /* restore tocptr */                      \
01950          : /*out*/   "=r" (_res)                                  \
01951          : /*in*/    "r" (&_argvec[2])                            \
01952          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01953       );                                                          \
01954       lval = (__typeof__(lval)) _res;                             \
01955    } while (0)
01956 
01957 #define CALL_FN_W_W(lval, orig, arg1)                             \
01958    do {                                                           \
01959       volatile OrigFn        _orig = (orig);                      \
01960       volatile unsigned long _argvec[3+1];                        \
01961       volatile unsigned long _res;                                \
01962       /* _argvec[0] holds current r2 across the call */           \
01963       _argvec[1]   = (unsigned long)_orig.r2;                     \
01964       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
01965       _argvec[2+1] = (unsigned long)arg1;                         \
01966       __asm__ volatile(                                           \
01967          "mr 11,%1\n\t"                                           \
01968          "std 2,-16(11)\n\t"  /* save tocptr */                   \
01969          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
01970          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
01971          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
01972          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
01973          "mr 11,%1\n\t"                                           \
01974          "mr %0,3\n\t"                                            \
01975          "ld 2,-16(11)" /* restore tocptr */                      \
01976          : /*out*/   "=r" (_res)                                  \
01977          : /*in*/    "r" (&_argvec[2])                            \
01978          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
01979       );                                                          \
01980       lval = (__typeof__(lval)) _res;                             \
01981    } while (0)
01982 
01983 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
01984    do {                                                           \
01985       volatile OrigFn        _orig = (orig);                      \
01986       volatile unsigned long _argvec[3+2];                        \
01987       volatile unsigned long _res;                                \
01988       /* _argvec[0] holds current r2 across the call */           \
01989       _argvec[1]   = (unsigned long)_orig.r2;                     \
01990       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
01991       _argvec[2+1] = (unsigned long)arg1;                         \
01992       _argvec[2+2] = (unsigned long)arg2;                         \
01993       __asm__ volatile(                                           \
01994          "mr 11,%1\n\t"                                           \
01995          "std 2,-16(11)\n\t"  /* save tocptr */                   \
01996          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
01997          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
01998          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
01999          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02000          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02001          "mr 11,%1\n\t"                                           \
02002          "mr %0,3\n\t"                                            \
02003          "ld 2,-16(11)" /* restore tocptr */                      \
02004          : /*out*/   "=r" (_res)                                  \
02005          : /*in*/    "r" (&_argvec[2])                            \
02006          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02007       );                                                          \
02008       lval = (__typeof__(lval)) _res;                             \
02009    } while (0)
02010 
02011 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
02012    do {                                                           \
02013       volatile OrigFn        _orig = (orig);                      \
02014       volatile unsigned long _argvec[3+3];                        \
02015       volatile unsigned long _res;                                \
02016       /* _argvec[0] holds current r2 across the call */           \
02017       _argvec[1]   = (unsigned long)_orig.r2;                     \
02018       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02019       _argvec[2+1] = (unsigned long)arg1;                         \
02020       _argvec[2+2] = (unsigned long)arg2;                         \
02021       _argvec[2+3] = (unsigned long)arg3;                         \
02022       __asm__ volatile(                                           \
02023          "mr 11,%1\n\t"                                           \
02024          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02025          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02026          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02027          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02028          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02029          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02030          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02031          "mr 11,%1\n\t"                                           \
02032          "mr %0,3\n\t"                                            \
02033          "ld 2,-16(11)" /* restore tocptr */                      \
02034          : /*out*/   "=r" (_res)                                  \
02035          : /*in*/    "r" (&_argvec[2])                            \
02036          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02037       );                                                          \
02038       lval = (__typeof__(lval)) _res;                             \
02039    } while (0)
02040 
02041 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
02042    do {                                                           \
02043       volatile OrigFn        _orig = (orig);                      \
02044       volatile unsigned long _argvec[3+4];                        \
02045       volatile unsigned long _res;                                \
02046       /* _argvec[0] holds current r2 across the call */           \
02047       _argvec[1]   = (unsigned long)_orig.r2;                     \
02048       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02049       _argvec[2+1] = (unsigned long)arg1;                         \
02050       _argvec[2+2] = (unsigned long)arg2;                         \
02051       _argvec[2+3] = (unsigned long)arg3;                         \
02052       _argvec[2+4] = (unsigned long)arg4;                         \
02053       __asm__ volatile(                                           \
02054          "mr 11,%1\n\t"                                           \
02055          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02056          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02057          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02058          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02059          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02060          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02061          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02062          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02063          "mr 11,%1\n\t"                                           \
02064          "mr %0,3\n\t"                                            \
02065          "ld 2,-16(11)" /* restore tocptr */                      \
02066          : /*out*/   "=r" (_res)                                  \
02067          : /*in*/    "r" (&_argvec[2])                            \
02068          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02069       );                                                          \
02070       lval = (__typeof__(lval)) _res;                             \
02071    } while (0)
02072 
02073 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
02074    do {                                                           \
02075       volatile OrigFn        _orig = (orig);                      \
02076       volatile unsigned long _argvec[3+5];                        \
02077       volatile unsigned long _res;                                \
02078       /* _argvec[0] holds current r2 across the call */           \
02079       _argvec[1]   = (unsigned long)_orig.r2;                     \
02080       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02081       _argvec[2+1] = (unsigned long)arg1;                         \
02082       _argvec[2+2] = (unsigned long)arg2;                         \
02083       _argvec[2+3] = (unsigned long)arg3;                         \
02084       _argvec[2+4] = (unsigned long)arg4;                         \
02085       _argvec[2+5] = (unsigned long)arg5;                         \
02086       __asm__ volatile(                                           \
02087          "mr 11,%1\n\t"                                           \
02088          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02089          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02090          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02091          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02092          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02093          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02094          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02095          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02096          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02097          "mr 11,%1\n\t"                                           \
02098          "mr %0,3\n\t"                                            \
02099          "ld 2,-16(11)" /* restore tocptr */                      \
02100          : /*out*/   "=r" (_res)                                  \
02101          : /*in*/    "r" (&_argvec[2])                            \
02102          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02103       );                                                          \
02104       lval = (__typeof__(lval)) _res;                             \
02105    } while (0)
02106 
02107 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
02108    do {                                                           \
02109       volatile OrigFn        _orig = (orig);                      \
02110       volatile unsigned long _argvec[3+6];                        \
02111       volatile unsigned long _res;                                \
02112       /* _argvec[0] holds current r2 across the call */           \
02113       _argvec[1]   = (unsigned long)_orig.r2;                     \
02114       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02115       _argvec[2+1] = (unsigned long)arg1;                         \
02116       _argvec[2+2] = (unsigned long)arg2;                         \
02117       _argvec[2+3] = (unsigned long)arg3;                         \
02118       _argvec[2+4] = (unsigned long)arg4;                         \
02119       _argvec[2+5] = (unsigned long)arg5;                         \
02120       _argvec[2+6] = (unsigned long)arg6;                         \
02121       __asm__ volatile(                                           \
02122          "mr 11,%1\n\t"                                           \
02123          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02124          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02125          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02126          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02127          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02128          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02129          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02130          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
02131          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02132          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02133          "mr 11,%1\n\t"                                           \
02134          "mr %0,3\n\t"                                            \
02135          "ld 2,-16(11)" /* restore tocptr */                      \
02136          : /*out*/   "=r" (_res)                                  \
02137          : /*in*/    "r" (&_argvec[2])                            \
02138          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02139       );                                                          \
02140       lval = (__typeof__(lval)) _res;                             \
02141    } while (0)
02142 
02143 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
02144                                  arg7)                            \
02145    do {                                                           \
02146       volatile OrigFn        _orig = (orig);                      \
02147       volatile unsigned long _argvec[3+7];                        \
02148       volatile unsigned long _res;                                \
02149       /* _argvec[0] holds current r2 across the call */           \
02150       _argvec[1]   = (unsigned long)_orig.r2;                     \
02151       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02152       _argvec[2+1] = (unsigned long)arg1;                         \
02153       _argvec[2+2] = (unsigned long)arg2;                         \
02154       _argvec[2+3] = (unsigned long)arg3;                         \
02155       _argvec[2+4] = (unsigned long)arg4;                         \
02156       _argvec[2+5] = (unsigned long)arg5;                         \
02157       _argvec[2+6] = (unsigned long)arg6;                         \
02158       _argvec[2+7] = (unsigned long)arg7;                         \
02159       __asm__ volatile(                                           \
02160          "mr 11,%1\n\t"                                           \
02161          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02162          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02163          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02164          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02165          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02166          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02167          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02168          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
02169          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
02170          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02171          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02172          "mr 11,%1\n\t"                                           \
02173          "mr %0,3\n\t"                                            \
02174          "ld 2,-16(11)" /* restore tocptr */                      \
02175          : /*out*/   "=r" (_res)                                  \
02176          : /*in*/    "r" (&_argvec[2])                            \
02177          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02178       );                                                          \
02179       lval = (__typeof__(lval)) _res;                             \
02180    } while (0)
02181 
02182 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
02183                                  arg7,arg8)                       \
02184    do {                                                           \
02185       volatile OrigFn        _orig = (orig);                      \
02186       volatile unsigned long _argvec[3+8];                        \
02187       volatile unsigned long _res;                                \
02188       /* _argvec[0] holds current r2 across the call */           \
02189       _argvec[1]   = (unsigned long)_orig.r2;                     \
02190       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02191       _argvec[2+1] = (unsigned long)arg1;                         \
02192       _argvec[2+2] = (unsigned long)arg2;                         \
02193       _argvec[2+3] = (unsigned long)arg3;                         \
02194       _argvec[2+4] = (unsigned long)arg4;                         \
02195       _argvec[2+5] = (unsigned long)arg5;                         \
02196       _argvec[2+6] = (unsigned long)arg6;                         \
02197       _argvec[2+7] = (unsigned long)arg7;                         \
02198       _argvec[2+8] = (unsigned long)arg8;                         \
02199       __asm__ volatile(                                           \
02200          "mr 11,%1\n\t"                                           \
02201          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02202          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02203          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02204          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02205          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02206          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02207          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02208          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
02209          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
02210          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
02211          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02212          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02213          "mr 11,%1\n\t"                                           \
02214          "mr %0,3\n\t"                                            \
02215          "ld 2,-16(11)" /* restore tocptr */                      \
02216          : /*out*/   "=r" (_res)                                  \
02217          : /*in*/    "r" (&_argvec[2])                            \
02218          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02219       );                                                          \
02220       lval = (__typeof__(lval)) _res;                             \
02221    } while (0)
02222 
02223 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
02224                                  arg7,arg8,arg9)                  \
02225    do {                                                           \
02226       volatile OrigFn        _orig = (orig);                      \
02227       volatile unsigned long _argvec[3+9];                        \
02228       volatile unsigned long _res;                                \
02229       /* _argvec[0] holds current r2 across the call */           \
02230       _argvec[1]   = (unsigned long)_orig.r2;                     \
02231       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02232       _argvec[2+1] = (unsigned long)arg1;                         \
02233       _argvec[2+2] = (unsigned long)arg2;                         \
02234       _argvec[2+3] = (unsigned long)arg3;                         \
02235       _argvec[2+4] = (unsigned long)arg4;                         \
02236       _argvec[2+5] = (unsigned long)arg5;                         \
02237       _argvec[2+6] = (unsigned long)arg6;                         \
02238       _argvec[2+7] = (unsigned long)arg7;                         \
02239       _argvec[2+8] = (unsigned long)arg8;                         \
02240       _argvec[2+9] = (unsigned long)arg9;                         \
02241       __asm__ volatile(                                           \
02242          "mr 11,%1\n\t"                                           \
02243          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02244          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02245          "addi 1,1,-128\n\t"  /* expand stack frame */            \
02246          /* arg9 */                                               \
02247          "ld  3,72(11)\n\t"                                       \
02248          "std 3,112(1)\n\t"                                       \
02249          /* args1-8 */                                            \
02250          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02251          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02252          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02253          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02254          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02255          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
02256          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
02257          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
02258          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02259          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02260          "mr 11,%1\n\t"                                           \
02261          "mr %0,3\n\t"                                            \
02262          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
02263          "addi 1,1,128"     /* restore frame */                   \
02264          : /*out*/   "=r" (_res)                                  \
02265          : /*in*/    "r" (&_argvec[2])                            \
02266          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02267       );                                                          \
02268       lval = (__typeof__(lval)) _res;                             \
02269    } while (0)
02270 
02271 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
02272                                   arg7,arg8,arg9,arg10)           \
02273    do {                                                           \
02274       volatile OrigFn        _orig = (orig);                      \
02275       volatile unsigned long _argvec[3+10];                       \
02276       volatile unsigned long _res;                                \
02277       /* _argvec[0] holds current r2 across the call */           \
02278       _argvec[1]   = (unsigned long)_orig.r2;                     \
02279       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02280       _argvec[2+1] = (unsigned long)arg1;                         \
02281       _argvec[2+2] = (unsigned long)arg2;                         \
02282       _argvec[2+3] = (unsigned long)arg3;                         \
02283       _argvec[2+4] = (unsigned long)arg4;                         \
02284       _argvec[2+5] = (unsigned long)arg5;                         \
02285       _argvec[2+6] = (unsigned long)arg6;                         \
02286       _argvec[2+7] = (unsigned long)arg7;                         \
02287       _argvec[2+8] = (unsigned long)arg8;                         \
02288       _argvec[2+9] = (unsigned long)arg9;                         \
02289       _argvec[2+10] = (unsigned long)arg10;                       \
02290       __asm__ volatile(                                           \
02291          "mr 11,%1\n\t"                                           \
02292          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02293          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02294          "addi 1,1,-128\n\t"  /* expand stack frame */            \
02295          /* arg10 */                                              \
02296          "ld  3,80(11)\n\t"                                       \
02297          "std 3,120(1)\n\t"                                       \
02298          /* arg9 */                                               \
02299          "ld  3,72(11)\n\t"                                       \
02300          "std 3,112(1)\n\t"                                       \
02301          /* args1-8 */                                            \
02302          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02303          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02304          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02305          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02306          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02307          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
02308          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
02309          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
02310          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02311          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02312          "mr 11,%1\n\t"                                           \
02313          "mr %0,3\n\t"                                            \
02314          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
02315          "addi 1,1,128"     /* restore frame */                   \
02316          : /*out*/   "=r" (_res)                                  \
02317          : /*in*/    "r" (&_argvec[2])                            \
02318          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02319       );                                                          \
02320       lval = (__typeof__(lval)) _res;                             \
02321    } while (0)
02322 
02323 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
02324                                   arg7,arg8,arg9,arg10,arg11)     \
02325    do {                                                           \
02326       volatile OrigFn        _orig = (orig);                      \
02327       volatile unsigned long _argvec[3+11];                       \
02328       volatile unsigned long _res;                                \
02329       /* _argvec[0] holds current r2 across the call */           \
02330       _argvec[1]   = (unsigned long)_orig.r2;                     \
02331       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02332       _argvec[2+1] = (unsigned long)arg1;                         \
02333       _argvec[2+2] = (unsigned long)arg2;                         \
02334       _argvec[2+3] = (unsigned long)arg3;                         \
02335       _argvec[2+4] = (unsigned long)arg4;                         \
02336       _argvec[2+5] = (unsigned long)arg5;                         \
02337       _argvec[2+6] = (unsigned long)arg6;                         \
02338       _argvec[2+7] = (unsigned long)arg7;                         \
02339       _argvec[2+8] = (unsigned long)arg8;                         \
02340       _argvec[2+9] = (unsigned long)arg9;                         \
02341       _argvec[2+10] = (unsigned long)arg10;                       \
02342       _argvec[2+11] = (unsigned long)arg11;                       \
02343       __asm__ volatile(                                           \
02344          "mr 11,%1\n\t"                                           \
02345          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02346          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02347          "addi 1,1,-144\n\t"  /* expand stack frame */            \
02348          /* arg11 */                                              \
02349          "ld  3,88(11)\n\t"                                       \
02350          "std 3,128(1)\n\t"                                       \
02351          /* arg10 */                                              \
02352          "ld  3,80(11)\n\t"                                       \
02353          "std 3,120(1)\n\t"                                       \
02354          /* arg9 */                                               \
02355          "ld  3,72(11)\n\t"                                       \
02356          "std 3,112(1)\n\t"                                       \
02357          /* args1-8 */                                            \
02358          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02359          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02360          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02361          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02362          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02363          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
02364          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
02365          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
02366          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02367          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02368          "mr 11,%1\n\t"                                           \
02369          "mr %0,3\n\t"                                            \
02370          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
02371          "addi 1,1,144"     /* restore frame */                   \
02372          : /*out*/   "=r" (_res)                                  \
02373          : /*in*/    "r" (&_argvec[2])                            \
02374          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02375       );                                                          \
02376       lval = (__typeof__(lval)) _res;                             \
02377    } while (0)
02378 
02379 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
02380                                 arg7,arg8,arg9,arg10,arg11,arg12) \
02381    do {                                                           \
02382       volatile OrigFn        _orig = (orig);                      \
02383       volatile unsigned long _argvec[3+12];                       \
02384       volatile unsigned long _res;                                \
02385       /* _argvec[0] holds current r2 across the call */           \
02386       _argvec[1]   = (unsigned long)_orig.r2;                     \
02387       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02388       _argvec[2+1] = (unsigned long)arg1;                         \
02389       _argvec[2+2] = (unsigned long)arg2;                         \
02390       _argvec[2+3] = (unsigned long)arg3;                         \
02391       _argvec[2+4] = (unsigned long)arg4;                         \
02392       _argvec[2+5] = (unsigned long)arg5;                         \
02393       _argvec[2+6] = (unsigned long)arg6;                         \
02394       _argvec[2+7] = (unsigned long)arg7;                         \
02395       _argvec[2+8] = (unsigned long)arg8;                         \
02396       _argvec[2+9] = (unsigned long)arg9;                         \
02397       _argvec[2+10] = (unsigned long)arg10;                       \
02398       _argvec[2+11] = (unsigned long)arg11;                       \
02399       _argvec[2+12] = (unsigned long)arg12;                       \
02400       __asm__ volatile(                                           \
02401          "mr 11,%1\n\t"                                           \
02402          "std 2,-16(11)\n\t"  /* save tocptr */                   \
02403          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
02404          "addi 1,1,-144\n\t"  /* expand stack frame */            \
02405          /* arg12 */                                              \
02406          "ld  3,96(11)\n\t"                                       \
02407          "std 3,136(1)\n\t"                                       \
02408          /* arg11 */                                              \
02409          "ld  3,88(11)\n\t"                                       \
02410          "std 3,128(1)\n\t"                                       \
02411          /* arg10 */                                              \
02412          "ld  3,80(11)\n\t"                                       \
02413          "std 3,120(1)\n\t"                                       \
02414          /* arg9 */                                               \
02415          "ld  3,72(11)\n\t"                                       \
02416          "std 3,112(1)\n\t"                                       \
02417          /* args1-8 */                                            \
02418          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
02419          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
02420          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
02421          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
02422          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
02423          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
02424          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
02425          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
02426          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
02427          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02428          "mr 11,%1\n\t"                                           \
02429          "mr %0,3\n\t"                                            \
02430          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
02431          "addi 1,1,144"     /* restore frame */                   \
02432          : /*out*/   "=r" (_res)                                  \
02433          : /*in*/    "r" (&_argvec[2])                            \
02434          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02435       );                                                          \
02436       lval = (__typeof__(lval)) _res;                             \
02437    } while (0)
02438 
02439 #endif /* PLAT_ppc64_linux */
02440 
02441 /* ------------------------ ppc32-aix5 ------------------------- */
02442 
02443 #if defined(PLAT_ppc32_aix5)
02444 
02445 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
02446 
02447 /* These regs are trashed by the hidden call. */
02448 #define __CALLER_SAVED_REGS                                       \
02449    "lr", "ctr", "xer",                                            \
02450    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
02451    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
02452    "r11", "r12", "r13"
02453 
02454 /* Expand the stack frame, copying enough info that unwinding
02455    still works.  Trashes r3. */
02456 
02457 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr)                      \
02458          "addi 1,1,-" #_n_fr "\n\t"                               \
02459          "lwz  3," #_n_fr "(1)\n\t"                               \
02460          "stw  3,0(1)\n\t"
02461 
02462 #define VG_CONTRACT_FRAME_BY(_n_fr)                               \
02463          "addi 1,1," #_n_fr "\n\t"
02464 
02465 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
02466    long) == 4. */
02467 
02468 #define CALL_FN_W_v(lval, orig)                                   \
02469    do {                                                           \
02470       volatile OrigFn        _orig = (orig);                      \
02471       volatile unsigned long _argvec[3+0];                        \
02472       volatile unsigned long _res;                                \
02473       /* _argvec[0] holds current r2 across the call */           \
02474       _argvec[1] = (unsigned long)_orig.r2;                       \
02475       _argvec[2] = (unsigned long)_orig.nraddr;                   \
02476       __asm__ volatile(                                           \
02477          "mr 11,%1\n\t"                                           \
02478          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02479          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02480          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02481          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02482          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02483          "mr 11,%1\n\t"                                           \
02484          "mr %0,3\n\t"                                            \
02485          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02486          VG_CONTRACT_FRAME_BY(512)                                \
02487          : /*out*/   "=r" (_res)                                  \
02488          : /*in*/    "r" (&_argvec[2])                            \
02489          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02490       );                                                          \
02491       lval = (__typeof__(lval)) _res;                             \
02492    } while (0)
02493 
02494 #define CALL_FN_W_W(lval, orig, arg1)                             \
02495    do {                                                           \
02496       volatile OrigFn        _orig = (orig);                      \
02497       volatile unsigned long _argvec[3+1];                        \
02498       volatile unsigned long _res;                                \
02499       /* _argvec[0] holds current r2 across the call */           \
02500       _argvec[1]   = (unsigned long)_orig.r2;                     \
02501       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02502       _argvec[2+1] = (unsigned long)arg1;                         \
02503       __asm__ volatile(                                           \
02504          "mr 11,%1\n\t"                                           \
02505          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02506          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02507          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02508          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02509          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02510          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02511          "mr 11,%1\n\t"                                           \
02512          "mr %0,3\n\t"                                            \
02513          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02514          VG_CONTRACT_FRAME_BY(512)                                \
02515          : /*out*/   "=r" (_res)                                  \
02516          : /*in*/    "r" (&_argvec[2])                            \
02517          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02518       );                                                          \
02519       lval = (__typeof__(lval)) _res;                             \
02520    } while (0)
02521 
02522 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
02523    do {                                                           \
02524       volatile OrigFn        _orig = (orig);                      \
02525       volatile unsigned long _argvec[3+2];                        \
02526       volatile unsigned long _res;                                \
02527       /* _argvec[0] holds current r2 across the call */           \
02528       _argvec[1]   = (unsigned long)_orig.r2;                     \
02529       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02530       _argvec[2+1] = (unsigned long)arg1;                         \
02531       _argvec[2+2] = (unsigned long)arg2;                         \
02532       __asm__ volatile(                                           \
02533          "mr 11,%1\n\t"                                           \
02534          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02535          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02536          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02537          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02538          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02539          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02540          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02541          "mr 11,%1\n\t"                                           \
02542          "mr %0,3\n\t"                                            \
02543          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02544          VG_CONTRACT_FRAME_BY(512)                                \
02545          : /*out*/   "=r" (_res)                                  \
02546          : /*in*/    "r" (&_argvec[2])                            \
02547          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02548       );                                                          \
02549       lval = (__typeof__(lval)) _res;                             \
02550    } while (0)
02551 
02552 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
02553    do {                                                           \
02554       volatile OrigFn        _orig = (orig);                      \
02555       volatile unsigned long _argvec[3+3];                        \
02556       volatile unsigned long _res;                                \
02557       /* _argvec[0] holds current r2 across the call */           \
02558       _argvec[1]   = (unsigned long)_orig.r2;                     \
02559       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02560       _argvec[2+1] = (unsigned long)arg1;                         \
02561       _argvec[2+2] = (unsigned long)arg2;                         \
02562       _argvec[2+3] = (unsigned long)arg3;                         \
02563       __asm__ volatile(                                           \
02564          "mr 11,%1\n\t"                                           \
02565          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02566          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02567          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02568          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02569          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02570          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02571          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02572          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02573          "mr 11,%1\n\t"                                           \
02574          "mr %0,3\n\t"                                            \
02575          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02576          VG_CONTRACT_FRAME_BY(512)                                \
02577          : /*out*/   "=r" (_res)                                  \
02578          : /*in*/    "r" (&_argvec[2])                            \
02579          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02580       );                                                          \
02581       lval = (__typeof__(lval)) _res;                             \
02582    } while (0)
02583 
02584 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
02585    do {                                                           \
02586       volatile OrigFn        _orig = (orig);                      \
02587       volatile unsigned long _argvec[3+4];                        \
02588       volatile unsigned long _res;                                \
02589       /* _argvec[0] holds current r2 across the call */           \
02590       _argvec[1]   = (unsigned long)_orig.r2;                     \
02591       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02592       _argvec[2+1] = (unsigned long)arg1;                         \
02593       _argvec[2+2] = (unsigned long)arg2;                         \
02594       _argvec[2+3] = (unsigned long)arg3;                         \
02595       _argvec[2+4] = (unsigned long)arg4;                         \
02596       __asm__ volatile(                                           \
02597          "mr 11,%1\n\t"                                           \
02598          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02599          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02600          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02601          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02602          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02603          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02604          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02605          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02606          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02607          "mr 11,%1\n\t"                                           \
02608          "mr %0,3\n\t"                                            \
02609          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02610          VG_CONTRACT_FRAME_BY(512)                                \
02611          : /*out*/   "=r" (_res)                                  \
02612          : /*in*/    "r" (&_argvec[2])                            \
02613          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02614       );                                                          \
02615       lval = (__typeof__(lval)) _res;                             \
02616    } while (0)
02617 
02618 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
02619    do {                                                           \
02620       volatile OrigFn        _orig = (orig);                      \
02621       volatile unsigned long _argvec[3+5];                        \
02622       volatile unsigned long _res;                                \
02623       /* _argvec[0] holds current r2 across the call */           \
02624       _argvec[1]   = (unsigned long)_orig.r2;                     \
02625       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02626       _argvec[2+1] = (unsigned long)arg1;                         \
02627       _argvec[2+2] = (unsigned long)arg2;                         \
02628       _argvec[2+3] = (unsigned long)arg3;                         \
02629       _argvec[2+4] = (unsigned long)arg4;                         \
02630       _argvec[2+5] = (unsigned long)arg5;                         \
02631       __asm__ volatile(                                           \
02632          "mr 11,%1\n\t"                                           \
02633          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02634          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02635          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02636          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02637          "lwz  4, 8(11)\n\t" /* arg2->r4 */                       \
02638          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02639          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02640          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02641          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02642          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02643          "mr 11,%1\n\t"                                           \
02644          "mr %0,3\n\t"                                            \
02645          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02646          VG_CONTRACT_FRAME_BY(512)                                \
02647          : /*out*/   "=r" (_res)                                  \
02648          : /*in*/    "r" (&_argvec[2])                            \
02649          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02650       );                                                          \
02651       lval = (__typeof__(lval)) _res;                             \
02652    } while (0)
02653 
02654 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
02655    do {                                                           \
02656       volatile OrigFn        _orig = (orig);                      \
02657       volatile unsigned long _argvec[3+6];                        \
02658       volatile unsigned long _res;                                \
02659       /* _argvec[0] holds current r2 across the call */           \
02660       _argvec[1]   = (unsigned long)_orig.r2;                     \
02661       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02662       _argvec[2+1] = (unsigned long)arg1;                         \
02663       _argvec[2+2] = (unsigned long)arg2;                         \
02664       _argvec[2+3] = (unsigned long)arg3;                         \
02665       _argvec[2+4] = (unsigned long)arg4;                         \
02666       _argvec[2+5] = (unsigned long)arg5;                         \
02667       _argvec[2+6] = (unsigned long)arg6;                         \
02668       __asm__ volatile(                                           \
02669          "mr 11,%1\n\t"                                           \
02670          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02671          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02672          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02673          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02674          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02675          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02676          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02677          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02678          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
02679          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02680          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02681          "mr 11,%1\n\t"                                           \
02682          "mr %0,3\n\t"                                            \
02683          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02684          VG_CONTRACT_FRAME_BY(512)                                \
02685          : /*out*/   "=r" (_res)                                  \
02686          : /*in*/    "r" (&_argvec[2])                            \
02687          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02688       );                                                          \
02689       lval = (__typeof__(lval)) _res;                             \
02690    } while (0)
02691 
02692 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
02693                                  arg7)                            \
02694    do {                                                           \
02695       volatile OrigFn        _orig = (orig);                      \
02696       volatile unsigned long _argvec[3+7];                        \
02697       volatile unsigned long _res;                                \
02698       /* _argvec[0] holds current r2 across the call */           \
02699       _argvec[1]   = (unsigned long)_orig.r2;                     \
02700       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02701       _argvec[2+1] = (unsigned long)arg1;                         \
02702       _argvec[2+2] = (unsigned long)arg2;                         \
02703       _argvec[2+3] = (unsigned long)arg3;                         \
02704       _argvec[2+4] = (unsigned long)arg4;                         \
02705       _argvec[2+5] = (unsigned long)arg5;                         \
02706       _argvec[2+6] = (unsigned long)arg6;                         \
02707       _argvec[2+7] = (unsigned long)arg7;                         \
02708       __asm__ volatile(                                           \
02709          "mr 11,%1\n\t"                                           \
02710          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02711          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02712          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02713          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02714          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02715          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02716          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02717          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02718          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
02719          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
02720          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02721          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02722          "mr 11,%1\n\t"                                           \
02723          "mr %0,3\n\t"                                            \
02724          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02725          VG_CONTRACT_FRAME_BY(512)                                \
02726          : /*out*/   "=r" (_res)                                  \
02727          : /*in*/    "r" (&_argvec[2])                            \
02728          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02729       );                                                          \
02730       lval = (__typeof__(lval)) _res;                             \
02731    } while (0)
02732 
02733 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
02734                                  arg7,arg8)                       \
02735    do {                                                           \
02736       volatile OrigFn        _orig = (orig);                      \
02737       volatile unsigned long _argvec[3+8];                        \
02738       volatile unsigned long _res;                                \
02739       /* _argvec[0] holds current r2 across the call */           \
02740       _argvec[1]   = (unsigned long)_orig.r2;                     \
02741       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02742       _argvec[2+1] = (unsigned long)arg1;                         \
02743       _argvec[2+2] = (unsigned long)arg2;                         \
02744       _argvec[2+3] = (unsigned long)arg3;                         \
02745       _argvec[2+4] = (unsigned long)arg4;                         \
02746       _argvec[2+5] = (unsigned long)arg5;                         \
02747       _argvec[2+6] = (unsigned long)arg6;                         \
02748       _argvec[2+7] = (unsigned long)arg7;                         \
02749       _argvec[2+8] = (unsigned long)arg8;                         \
02750       __asm__ volatile(                                           \
02751          "mr 11,%1\n\t"                                           \
02752          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02753          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02754          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02755          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02756          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02757          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02758          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02759          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02760          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
02761          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
02762          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
02763          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02764          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02765          "mr 11,%1\n\t"                                           \
02766          "mr %0,3\n\t"                                            \
02767          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02768          VG_CONTRACT_FRAME_BY(512)                                \
02769          : /*out*/   "=r" (_res)                                  \
02770          : /*in*/    "r" (&_argvec[2])                            \
02771          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02772       );                                                          \
02773       lval = (__typeof__(lval)) _res;                             \
02774    } while (0)
02775 
02776 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
02777                                  arg7,arg8,arg9)                  \
02778    do {                                                           \
02779       volatile OrigFn        _orig = (orig);                      \
02780       volatile unsigned long _argvec[3+9];                        \
02781       volatile unsigned long _res;                                \
02782       /* _argvec[0] holds current r2 across the call */           \
02783       _argvec[1]   = (unsigned long)_orig.r2;                     \
02784       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02785       _argvec[2+1] = (unsigned long)arg1;                         \
02786       _argvec[2+2] = (unsigned long)arg2;                         \
02787       _argvec[2+3] = (unsigned long)arg3;                         \
02788       _argvec[2+4] = (unsigned long)arg4;                         \
02789       _argvec[2+5] = (unsigned long)arg5;                         \
02790       _argvec[2+6] = (unsigned long)arg6;                         \
02791       _argvec[2+7] = (unsigned long)arg7;                         \
02792       _argvec[2+8] = (unsigned long)arg8;                         \
02793       _argvec[2+9] = (unsigned long)arg9;                         \
02794       __asm__ volatile(                                           \
02795          "mr 11,%1\n\t"                                           \
02796          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02797          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02798          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02799          VG_EXPAND_FRAME_BY_trashes_r3(64)                        \
02800          /* arg9 */                                               \
02801          "lwz 3,36(11)\n\t"                                       \
02802          "stw 3,56(1)\n\t"                                        \
02803          /* args1-8 */                                            \
02804          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02805          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02806          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02807          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02808          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02809          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
02810          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
02811          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
02812          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02813          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02814          "mr 11,%1\n\t"                                           \
02815          "mr %0,3\n\t"                                            \
02816          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02817          VG_CONTRACT_FRAME_BY(64)                                 \
02818          VG_CONTRACT_FRAME_BY(512)                                \
02819          : /*out*/   "=r" (_res)                                  \
02820          : /*in*/    "r" (&_argvec[2])                            \
02821          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02822       );                                                          \
02823       lval = (__typeof__(lval)) _res;                             \
02824    } while (0)
02825 
02826 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
02827                                   arg7,arg8,arg9,arg10)           \
02828    do {                                                           \
02829       volatile OrigFn        _orig = (orig);                      \
02830       volatile unsigned long _argvec[3+10];                       \
02831       volatile unsigned long _res;                                \
02832       /* _argvec[0] holds current r2 across the call */           \
02833       _argvec[1]   = (unsigned long)_orig.r2;                     \
02834       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02835       _argvec[2+1] = (unsigned long)arg1;                         \
02836       _argvec[2+2] = (unsigned long)arg2;                         \
02837       _argvec[2+3] = (unsigned long)arg3;                         \
02838       _argvec[2+4] = (unsigned long)arg4;                         \
02839       _argvec[2+5] = (unsigned long)arg5;                         \
02840       _argvec[2+6] = (unsigned long)arg6;                         \
02841       _argvec[2+7] = (unsigned long)arg7;                         \
02842       _argvec[2+8] = (unsigned long)arg8;                         \
02843       _argvec[2+9] = (unsigned long)arg9;                         \
02844       _argvec[2+10] = (unsigned long)arg10;                       \
02845       __asm__ volatile(                                           \
02846          "mr 11,%1\n\t"                                           \
02847          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02848          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02849          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02850          VG_EXPAND_FRAME_BY_trashes_r3(64)                        \
02851          /* arg10 */                                              \
02852          "lwz 3,40(11)\n\t"                                       \
02853          "stw 3,60(1)\n\t"                                        \
02854          /* arg9 */                                               \
02855          "lwz 3,36(11)\n\t"                                       \
02856          "stw 3,56(1)\n\t"                                        \
02857          /* args1-8 */                                            \
02858          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02859          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02860          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02861          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02862          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02863          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
02864          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
02865          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
02866          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02867          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02868          "mr 11,%1\n\t"                                           \
02869          "mr %0,3\n\t"                                            \
02870          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02871          VG_CONTRACT_FRAME_BY(64)                                 \
02872          VG_CONTRACT_FRAME_BY(512)                                \
02873          : /*out*/   "=r" (_res)                                  \
02874          : /*in*/    "r" (&_argvec[2])                            \
02875          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02876       );                                                          \
02877       lval = (__typeof__(lval)) _res;                             \
02878    } while (0)
02879 
02880 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
02881                                   arg7,arg8,arg9,arg10,arg11)     \
02882    do {                                                           \
02883       volatile OrigFn        _orig = (orig);                      \
02884       volatile unsigned long _argvec[3+11];                       \
02885       volatile unsigned long _res;                                \
02886       /* _argvec[0] holds current r2 across the call */           \
02887       _argvec[1]   = (unsigned long)_orig.r2;                     \
02888       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02889       _argvec[2+1] = (unsigned long)arg1;                         \
02890       _argvec[2+2] = (unsigned long)arg2;                         \
02891       _argvec[2+3] = (unsigned long)arg3;                         \
02892       _argvec[2+4] = (unsigned long)arg4;                         \
02893       _argvec[2+5] = (unsigned long)arg5;                         \
02894       _argvec[2+6] = (unsigned long)arg6;                         \
02895       _argvec[2+7] = (unsigned long)arg7;                         \
02896       _argvec[2+8] = (unsigned long)arg8;                         \
02897       _argvec[2+9] = (unsigned long)arg9;                         \
02898       _argvec[2+10] = (unsigned long)arg10;                       \
02899       _argvec[2+11] = (unsigned long)arg11;                       \
02900       __asm__ volatile(                                           \
02901          "mr 11,%1\n\t"                                           \
02902          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02903          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02904          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02905          VG_EXPAND_FRAME_BY_trashes_r3(72)                        \
02906          /* arg11 */                                              \
02907          "lwz 3,44(11)\n\t"                                       \
02908          "stw 3,64(1)\n\t"                                        \
02909          /* arg10 */                                              \
02910          "lwz 3,40(11)\n\t"                                       \
02911          "stw 3,60(1)\n\t"                                        \
02912          /* arg9 */                                               \
02913          "lwz 3,36(11)\n\t"                                       \
02914          "stw 3,56(1)\n\t"                                        \
02915          /* args1-8 */                                            \
02916          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02917          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02918          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02919          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02920          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02921          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
02922          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
02923          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
02924          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02925          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02926          "mr 11,%1\n\t"                                           \
02927          "mr %0,3\n\t"                                            \
02928          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02929          VG_CONTRACT_FRAME_BY(72)                                 \
02930          VG_CONTRACT_FRAME_BY(512)                                \
02931          : /*out*/   "=r" (_res)                                  \
02932          : /*in*/    "r" (&_argvec[2])                            \
02933          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02934       );                                                          \
02935       lval = (__typeof__(lval)) _res;                             \
02936    } while (0)
02937 
02938 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
02939                                 arg7,arg8,arg9,arg10,arg11,arg12) \
02940    do {                                                           \
02941       volatile OrigFn        _orig = (orig);                      \
02942       volatile unsigned long _argvec[3+12];                       \
02943       volatile unsigned long _res;                                \
02944       /* _argvec[0] holds current r2 across the call */           \
02945       _argvec[1]   = (unsigned long)_orig.r2;                     \
02946       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
02947       _argvec[2+1] = (unsigned long)arg1;                         \
02948       _argvec[2+2] = (unsigned long)arg2;                         \
02949       _argvec[2+3] = (unsigned long)arg3;                         \
02950       _argvec[2+4] = (unsigned long)arg4;                         \
02951       _argvec[2+5] = (unsigned long)arg5;                         \
02952       _argvec[2+6] = (unsigned long)arg6;                         \
02953       _argvec[2+7] = (unsigned long)arg7;                         \
02954       _argvec[2+8] = (unsigned long)arg8;                         \
02955       _argvec[2+9] = (unsigned long)arg9;                         \
02956       _argvec[2+10] = (unsigned long)arg10;                       \
02957       _argvec[2+11] = (unsigned long)arg11;                       \
02958       _argvec[2+12] = (unsigned long)arg12;                       \
02959       __asm__ volatile(                                           \
02960          "mr 11,%1\n\t"                                           \
02961          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
02962          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
02963          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
02964          VG_EXPAND_FRAME_BY_trashes_r3(72)                        \
02965          /* arg12 */                                              \
02966          "lwz 3,48(11)\n\t"                                       \
02967          "stw 3,68(1)\n\t"                                        \
02968          /* arg11 */                                              \
02969          "lwz 3,44(11)\n\t"                                       \
02970          "stw 3,64(1)\n\t"                                        \
02971          /* arg10 */                                              \
02972          "lwz 3,40(11)\n\t"                                       \
02973          "stw 3,60(1)\n\t"                                        \
02974          /* arg9 */                                               \
02975          "lwz 3,36(11)\n\t"                                       \
02976          "stw 3,56(1)\n\t"                                        \
02977          /* args1-8 */                                            \
02978          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
02979          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
02980          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
02981          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
02982          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
02983          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
02984          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
02985          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
02986          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
02987          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
02988          "mr 11,%1\n\t"                                           \
02989          "mr %0,3\n\t"                                            \
02990          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
02991          VG_CONTRACT_FRAME_BY(72)                                 \
02992          VG_CONTRACT_FRAME_BY(512)                                \
02993          : /*out*/   "=r" (_res)                                  \
02994          : /*in*/    "r" (&_argvec[2])                            \
02995          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
02996       );                                                          \
02997       lval = (__typeof__(lval)) _res;                             \
02998    } while (0)
02999 
03000 #endif /* PLAT_ppc32_aix5 */
03001 
03002 /* ------------------------ ppc64-aix5 ------------------------- */
03003 
03004 #if defined(PLAT_ppc64_aix5)
03005 
03006 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
03007 
03008 /* These regs are trashed by the hidden call. */
03009 #define __CALLER_SAVED_REGS                                       \
03010    "lr", "ctr", "xer",                                            \
03011    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
03012    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
03013    "r11", "r12", "r13"
03014 
03015 /* Expand the stack frame, copying enough info that unwinding
03016    still works.  Trashes r3. */
03017 
03018 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr)                      \
03019          "addi 1,1,-" #_n_fr "\n\t"                               \
03020          "ld   3," #_n_fr "(1)\n\t"                               \
03021          "std  3,0(1)\n\t"
03022 
03023 #define VG_CONTRACT_FRAME_BY(_n_fr)                               \
03024          "addi 1,1," #_n_fr "\n\t"
03025 
03026 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
03027    long) == 8. */
03028 
03029 #define CALL_FN_W_v(lval, orig)                                   \
03030    do {                                                           \
03031       volatile OrigFn        _orig = (orig);                      \
03032       volatile unsigned long _argvec[3+0];                        \
03033       volatile unsigned long _res;                                \
03034       /* _argvec[0] holds current r2 across the call */           \
03035       _argvec[1] = (unsigned long)_orig.r2;                       \
03036       _argvec[2] = (unsigned long)_orig.nraddr;                   \
03037       __asm__ volatile(                                           \
03038          "mr 11,%1\n\t"                                           \
03039          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03040          "std  2,-16(11)\n\t" /* save tocptr */                   \
03041          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03042          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03043          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03044          "mr 11,%1\n\t"                                           \
03045          "mr %0,3\n\t"                                            \
03046          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
03047          VG_CONTRACT_FRAME_BY(512)                                \
03048          : /*out*/   "=r" (_res)                                  \
03049          : /*in*/    "r" (&_argvec[2])                            \
03050          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03051       );                                                          \
03052       lval = (__typeof__(lval)) _res;                             \
03053    } while (0)
03054 
03055 #define CALL_FN_W_W(lval, orig, arg1)                             \
03056    do {                                                           \
03057       volatile OrigFn        _orig = (orig);                      \
03058       volatile unsigned long _argvec[3+1];                        \
03059       volatile unsigned long _res;                                \
03060       /* _argvec[0] holds current r2 across the call */           \
03061       _argvec[1]   = (unsigned long)_orig.r2;                     \
03062       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03063       _argvec[2+1] = (unsigned long)arg1;                         \
03064       __asm__ volatile(                                           \
03065          "mr 11,%1\n\t"                                           \
03066          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03067          "std  2,-16(11)\n\t" /* save tocptr */                   \
03068          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03069          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03070          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03071          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03072          "mr 11,%1\n\t"                                           \
03073          "mr %0,3\n\t"                                            \
03074          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
03075          VG_CONTRACT_FRAME_BY(512)                                \
03076          : /*out*/   "=r" (_res)                                  \
03077          : /*in*/    "r" (&_argvec[2])                            \
03078          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03079       );                                                          \
03080       lval = (__typeof__(lval)) _res;                             \
03081    } while (0)
03082 
03083 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
03084    do {                                                           \
03085       volatile OrigFn        _orig = (orig);                      \
03086       volatile unsigned long _argvec[3+2];                        \
03087       volatile unsigned long _res;                                \
03088       /* _argvec[0] holds current r2 across the call */           \
03089       _argvec[1]   = (unsigned long)_orig.r2;                     \
03090       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03091       _argvec[2+1] = (unsigned long)arg1;                         \
03092       _argvec[2+2] = (unsigned long)arg2;                         \
03093       __asm__ volatile(                                           \
03094          "mr 11,%1\n\t"                                           \
03095          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03096          "std  2,-16(11)\n\t" /* save tocptr */                   \
03097          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03098          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03099          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03100          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03101          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03102          "mr 11,%1\n\t"                                           \
03103          "mr %0,3\n\t"                                            \
03104          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03105          VG_CONTRACT_FRAME_BY(512)                                \
03106          : /*out*/   "=r" (_res)                                  \
03107          : /*in*/    "r" (&_argvec[2])                            \
03108          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03109       );                                                          \
03110       lval = (__typeof__(lval)) _res;                             \
03111    } while (0)
03112 
03113 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
03114    do {                                                           \
03115       volatile OrigFn        _orig = (orig);                      \
03116       volatile unsigned long _argvec[3+3];                        \
03117       volatile unsigned long _res;                                \
03118       /* _argvec[0] holds current r2 across the call */           \
03119       _argvec[1]   = (unsigned long)_orig.r2;                     \
03120       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03121       _argvec[2+1] = (unsigned long)arg1;                         \
03122       _argvec[2+2] = (unsigned long)arg2;                         \
03123       _argvec[2+3] = (unsigned long)arg3;                         \
03124       __asm__ volatile(                                           \
03125          "mr 11,%1\n\t"                                           \
03126          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03127          "std  2,-16(11)\n\t" /* save tocptr */                   \
03128          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03129          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03130          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03131          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03132          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03133          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03134          "mr 11,%1\n\t"                                           \
03135          "mr %0,3\n\t"                                            \
03136          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03137          VG_CONTRACT_FRAME_BY(512)                                \
03138          : /*out*/   "=r" (_res)                                  \
03139          : /*in*/    "r" (&_argvec[2])                            \
03140          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03141       );                                                          \
03142       lval = (__typeof__(lval)) _res;                             \
03143    } while (0)
03144 
03145 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
03146    do {                                                           \
03147       volatile OrigFn        _orig = (orig);                      \
03148       volatile unsigned long _argvec[3+4];                        \
03149       volatile unsigned long _res;                                \
03150       /* _argvec[0] holds current r2 across the call */           \
03151       _argvec[1]   = (unsigned long)_orig.r2;                     \
03152       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03153       _argvec[2+1] = (unsigned long)arg1;                         \
03154       _argvec[2+2] = (unsigned long)arg2;                         \
03155       _argvec[2+3] = (unsigned long)arg3;                         \
03156       _argvec[2+4] = (unsigned long)arg4;                         \
03157       __asm__ volatile(                                           \
03158          "mr 11,%1\n\t"                                           \
03159          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03160          "std  2,-16(11)\n\t" /* save tocptr */                   \
03161          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03162          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03163          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03164          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03165          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03166          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03167          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03168          "mr 11,%1\n\t"                                           \
03169          "mr %0,3\n\t"                                            \
03170          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03171          VG_CONTRACT_FRAME_BY(512)                                \
03172          : /*out*/   "=r" (_res)                                  \
03173          : /*in*/    "r" (&_argvec[2])                            \
03174          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03175       );                                                          \
03176       lval = (__typeof__(lval)) _res;                             \
03177    } while (0)
03178 
03179 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
03180    do {                                                           \
03181       volatile OrigFn        _orig = (orig);                      \
03182       volatile unsigned long _argvec[3+5];                        \
03183       volatile unsigned long _res;                                \
03184       /* _argvec[0] holds current r2 across the call */           \
03185       _argvec[1]   = (unsigned long)_orig.r2;                     \
03186       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03187       _argvec[2+1] = (unsigned long)arg1;                         \
03188       _argvec[2+2] = (unsigned long)arg2;                         \
03189       _argvec[2+3] = (unsigned long)arg3;                         \
03190       _argvec[2+4] = (unsigned long)arg4;                         \
03191       _argvec[2+5] = (unsigned long)arg5;                         \
03192       __asm__ volatile(                                           \
03193          "mr 11,%1\n\t"                                           \
03194          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03195          "std  2,-16(11)\n\t" /* save tocptr */                   \
03196          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03197          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03198          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03199          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03200          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03201          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03202          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03203          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03204          "mr 11,%1\n\t"                                           \
03205          "mr %0,3\n\t"                                            \
03206          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03207          VG_CONTRACT_FRAME_BY(512)                                \
03208          : /*out*/   "=r" (_res)                                  \
03209          : /*in*/    "r" (&_argvec[2])                            \
03210          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03211       );                                                          \
03212       lval = (__typeof__(lval)) _res;                             \
03213    } while (0)
03214 
03215 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
03216    do {                                                           \
03217       volatile OrigFn        _orig = (orig);                      \
03218       volatile unsigned long _argvec[3+6];                        \
03219       volatile unsigned long _res;                                \
03220       /* _argvec[0] holds current r2 across the call */           \
03221       _argvec[1]   = (unsigned long)_orig.r2;                     \
03222       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03223       _argvec[2+1] = (unsigned long)arg1;                         \
03224       _argvec[2+2] = (unsigned long)arg2;                         \
03225       _argvec[2+3] = (unsigned long)arg3;                         \
03226       _argvec[2+4] = (unsigned long)arg4;                         \
03227       _argvec[2+5] = (unsigned long)arg5;                         \
03228       _argvec[2+6] = (unsigned long)arg6;                         \
03229       __asm__ volatile(                                           \
03230          "mr 11,%1\n\t"                                           \
03231          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03232          "std  2,-16(11)\n\t" /* save tocptr */                   \
03233          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03234          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03235          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03236          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03237          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03238          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03239          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
03240          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03241          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03242          "mr 11,%1\n\t"                                           \
03243          "mr %0,3\n\t"                                            \
03244          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03245          VG_CONTRACT_FRAME_BY(512)                                \
03246          : /*out*/   "=r" (_res)                                  \
03247          : /*in*/    "r" (&_argvec[2])                            \
03248          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03249       );                                                          \
03250       lval = (__typeof__(lval)) _res;                             \
03251    } while (0)
03252 
03253 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
03254                                  arg7)                            \
03255    do {                                                           \
03256       volatile OrigFn        _orig = (orig);                      \
03257       volatile unsigned long _argvec[3+7];                        \
03258       volatile unsigned long _res;                                \
03259       /* _argvec[0] holds current r2 across the call */           \
03260       _argvec[1]   = (unsigned long)_orig.r2;                     \
03261       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03262       _argvec[2+1] = (unsigned long)arg1;                         \
03263       _argvec[2+2] = (unsigned long)arg2;                         \
03264       _argvec[2+3] = (unsigned long)arg3;                         \
03265       _argvec[2+4] = (unsigned long)arg4;                         \
03266       _argvec[2+5] = (unsigned long)arg5;                         \
03267       _argvec[2+6] = (unsigned long)arg6;                         \
03268       _argvec[2+7] = (unsigned long)arg7;                         \
03269       __asm__ volatile(                                           \
03270          "mr 11,%1\n\t"                                           \
03271          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03272          "std  2,-16(11)\n\t" /* save tocptr */                   \
03273          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03274          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03275          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03276          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03277          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03278          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03279          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
03280          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
03281          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03282          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03283          "mr 11,%1\n\t"                                           \
03284          "mr %0,3\n\t"                                            \
03285          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03286          VG_CONTRACT_FRAME_BY(512)                                \
03287          : /*out*/   "=r" (_res)                                  \
03288          : /*in*/    "r" (&_argvec[2])                            \
03289          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03290       );                                                          \
03291       lval = (__typeof__(lval)) _res;                             \
03292    } while (0)
03293 
03294 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
03295                                  arg7,arg8)                       \
03296    do {                                                           \
03297       volatile OrigFn        _orig = (orig);                      \
03298       volatile unsigned long _argvec[3+8];                        \
03299       volatile unsigned long _res;                                \
03300       /* _argvec[0] holds current r2 across the call */           \
03301       _argvec[1]   = (unsigned long)_orig.r2;                     \
03302       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03303       _argvec[2+1] = (unsigned long)arg1;                         \
03304       _argvec[2+2] = (unsigned long)arg2;                         \
03305       _argvec[2+3] = (unsigned long)arg3;                         \
03306       _argvec[2+4] = (unsigned long)arg4;                         \
03307       _argvec[2+5] = (unsigned long)arg5;                         \
03308       _argvec[2+6] = (unsigned long)arg6;                         \
03309       _argvec[2+7] = (unsigned long)arg7;                         \
03310       _argvec[2+8] = (unsigned long)arg8;                         \
03311       __asm__ volatile(                                           \
03312          "mr 11,%1\n\t"                                           \
03313          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03314          "std  2,-16(11)\n\t" /* save tocptr */                   \
03315          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03316          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03317          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03318          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03319          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03320          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03321          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
03322          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
03323          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
03324          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03325          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03326          "mr 11,%1\n\t"                                           \
03327          "mr %0,3\n\t"                                            \
03328          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03329          VG_CONTRACT_FRAME_BY(512)                                \
03330          : /*out*/   "=r" (_res)                                  \
03331          : /*in*/    "r" (&_argvec[2])                            \
03332          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03333       );                                                          \
03334       lval = (__typeof__(lval)) _res;                             \
03335    } while (0)
03336 
03337 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
03338                                  arg7,arg8,arg9)                  \
03339    do {                                                           \
03340       volatile OrigFn        _orig = (orig);                      \
03341       volatile unsigned long _argvec[3+9];                        \
03342       volatile unsigned long _res;                                \
03343       /* _argvec[0] holds current r2 across the call */           \
03344       _argvec[1]   = (unsigned long)_orig.r2;                     \
03345       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03346       _argvec[2+1] = (unsigned long)arg1;                         \
03347       _argvec[2+2] = (unsigned long)arg2;                         \
03348       _argvec[2+3] = (unsigned long)arg3;                         \
03349       _argvec[2+4] = (unsigned long)arg4;                         \
03350       _argvec[2+5] = (unsigned long)arg5;                         \
03351       _argvec[2+6] = (unsigned long)arg6;                         \
03352       _argvec[2+7] = (unsigned long)arg7;                         \
03353       _argvec[2+8] = (unsigned long)arg8;                         \
03354       _argvec[2+9] = (unsigned long)arg9;                         \
03355       __asm__ volatile(                                           \
03356          "mr 11,%1\n\t"                                           \
03357          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03358          "std  2,-16(11)\n\t" /* save tocptr */                   \
03359          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03360          VG_EXPAND_FRAME_BY_trashes_r3(128)                       \
03361          /* arg9 */                                               \
03362          "ld  3,72(11)\n\t"                                       \
03363          "std 3,112(1)\n\t"                                       \
03364          /* args1-8 */                                            \
03365          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03366          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03367          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03368          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03369          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03370          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
03371          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
03372          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
03373          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03374          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03375          "mr 11,%1\n\t"                                           \
03376          "mr %0,3\n\t"                                            \
03377          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03378          VG_CONTRACT_FRAME_BY(128)                                \
03379          VG_CONTRACT_FRAME_BY(512)                                \
03380          : /*out*/   "=r" (_res)                                  \
03381          : /*in*/    "r" (&_argvec[2])                            \
03382          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03383       );                                                          \
03384       lval = (__typeof__(lval)) _res;                             \
03385    } while (0)
03386 
03387 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
03388                                   arg7,arg8,arg9,arg10)           \
03389    do {                                                           \
03390       volatile OrigFn        _orig = (orig);                      \
03391       volatile unsigned long _argvec[3+10];                       \
03392       volatile unsigned long _res;                                \
03393       /* _argvec[0] holds current r2 across the call */           \
03394       _argvec[1]   = (unsigned long)_orig.r2;                     \
03395       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03396       _argvec[2+1] = (unsigned long)arg1;                         \
03397       _argvec[2+2] = (unsigned long)arg2;                         \
03398       _argvec[2+3] = (unsigned long)arg3;                         \
03399       _argvec[2+4] = (unsigned long)arg4;                         \
03400       _argvec[2+5] = (unsigned long)arg5;                         \
03401       _argvec[2+6] = (unsigned long)arg6;                         \
03402       _argvec[2+7] = (unsigned long)arg7;                         \
03403       _argvec[2+8] = (unsigned long)arg8;                         \
03404       _argvec[2+9] = (unsigned long)arg9;                         \
03405       _argvec[2+10] = (unsigned long)arg10;                       \
03406       __asm__ volatile(                                           \
03407          "mr 11,%1\n\t"                                           \
03408          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03409          "std  2,-16(11)\n\t" /* save tocptr */                   \
03410          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03411          VG_EXPAND_FRAME_BY_trashes_r3(128)                       \
03412          /* arg10 */                                              \
03413          "ld  3,80(11)\n\t"                                       \
03414          "std 3,120(1)\n\t"                                       \
03415          /* arg9 */                                               \
03416          "ld  3,72(11)\n\t"                                       \
03417          "std 3,112(1)\n\t"                                       \
03418          /* args1-8 */                                            \
03419          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03420          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03421          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03422          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03423          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03424          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
03425          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
03426          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
03427          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03428          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03429          "mr 11,%1\n\t"                                           \
03430          "mr %0,3\n\t"                                            \
03431          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03432          VG_CONTRACT_FRAME_BY(128)                                \
03433          VG_CONTRACT_FRAME_BY(512)                                \
03434          : /*out*/   "=r" (_res)                                  \
03435          : /*in*/    "r" (&_argvec[2])                            \
03436          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03437       );                                                          \
03438       lval = (__typeof__(lval)) _res;                             \
03439    } while (0)
03440 
03441 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
03442                                   arg7,arg8,arg9,arg10,arg11)     \
03443    do {                                                           \
03444       volatile OrigFn        _orig = (orig);                      \
03445       volatile unsigned long _argvec[3+11];                       \
03446       volatile unsigned long _res;                                \
03447       /* _argvec[0] holds current r2 across the call */           \
03448       _argvec[1]   = (unsigned long)_orig.r2;                     \
03449       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03450       _argvec[2+1] = (unsigned long)arg1;                         \
03451       _argvec[2+2] = (unsigned long)arg2;                         \
03452       _argvec[2+3] = (unsigned long)arg3;                         \
03453       _argvec[2+4] = (unsigned long)arg4;                         \
03454       _argvec[2+5] = (unsigned long)arg5;                         \
03455       _argvec[2+6] = (unsigned long)arg6;                         \
03456       _argvec[2+7] = (unsigned long)arg7;                         \
03457       _argvec[2+8] = (unsigned long)arg8;                         \
03458       _argvec[2+9] = (unsigned long)arg9;                         \
03459       _argvec[2+10] = (unsigned long)arg10;                       \
03460       _argvec[2+11] = (unsigned long)arg11;                       \
03461       __asm__ volatile(                                           \
03462          "mr 11,%1\n\t"                                           \
03463          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03464          "std  2,-16(11)\n\t" /* save tocptr */                   \
03465          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03466          VG_EXPAND_FRAME_BY_trashes_r3(144)                       \
03467          /* arg11 */                                              \
03468          "ld  3,88(11)\n\t"                                       \
03469          "std 3,128(1)\n\t"                                       \
03470          /* arg10 */                                              \
03471          "ld  3,80(11)\n\t"                                       \
03472          "std 3,120(1)\n\t"                                       \
03473          /* arg9 */                                               \
03474          "ld  3,72(11)\n\t"                                       \
03475          "std 3,112(1)\n\t"                                       \
03476          /* args1-8 */                                            \
03477          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03478          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03479          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03480          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03481          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03482          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
03483          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
03484          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
03485          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03486          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03487          "mr 11,%1\n\t"                                           \
03488          "mr %0,3\n\t"                                            \
03489          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03490          VG_CONTRACT_FRAME_BY(144)                                \
03491          VG_CONTRACT_FRAME_BY(512)                                \
03492          : /*out*/   "=r" (_res)                                  \
03493          : /*in*/    "r" (&_argvec[2])                            \
03494          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03495       );                                                          \
03496       lval = (__typeof__(lval)) _res;                             \
03497    } while (0)
03498 
03499 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
03500                                 arg7,arg8,arg9,arg10,arg11,arg12) \
03501    do {                                                           \
03502       volatile OrigFn        _orig = (orig);                      \
03503       volatile unsigned long _argvec[3+12];                       \
03504       volatile unsigned long _res;                                \
03505       /* _argvec[0] holds current r2 across the call */           \
03506       _argvec[1]   = (unsigned long)_orig.r2;                     \
03507       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
03508       _argvec[2+1] = (unsigned long)arg1;                         \
03509       _argvec[2+2] = (unsigned long)arg2;                         \
03510       _argvec[2+3] = (unsigned long)arg3;                         \
03511       _argvec[2+4] = (unsigned long)arg4;                         \
03512       _argvec[2+5] = (unsigned long)arg5;                         \
03513       _argvec[2+6] = (unsigned long)arg6;                         \
03514       _argvec[2+7] = (unsigned long)arg7;                         \
03515       _argvec[2+8] = (unsigned long)arg8;                         \
03516       _argvec[2+9] = (unsigned long)arg9;                         \
03517       _argvec[2+10] = (unsigned long)arg10;                       \
03518       _argvec[2+11] = (unsigned long)arg11;                       \
03519       _argvec[2+12] = (unsigned long)arg12;                       \
03520       __asm__ volatile(                                           \
03521          "mr 11,%1\n\t"                                           \
03522          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
03523          "std  2,-16(11)\n\t" /* save tocptr */                   \
03524          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
03525          VG_EXPAND_FRAME_BY_trashes_r3(144)                       \
03526          /* arg12 */                                              \
03527          "ld  3,96(11)\n\t"                                       \
03528          "std 3,136(1)\n\t"                                       \
03529          /* arg11 */                                              \
03530          "ld  3,88(11)\n\t"                                       \
03531          "std 3,128(1)\n\t"                                       \
03532          /* arg10 */                                              \
03533          "ld  3,80(11)\n\t"                                       \
03534          "std 3,120(1)\n\t"                                       \
03535          /* arg9 */                                               \
03536          "ld  3,72(11)\n\t"                                       \
03537          "std 3,112(1)\n\t"                                       \
03538          /* args1-8 */                                            \
03539          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
03540          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
03541          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
03542          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
03543          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
03544          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
03545          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
03546          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
03547          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
03548          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
03549          "mr 11,%1\n\t"                                           \
03550          "mr %0,3\n\t"                                            \
03551          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
03552          VG_CONTRACT_FRAME_BY(144)                                \
03553          VG_CONTRACT_FRAME_BY(512)                                \
03554          : /*out*/   "=r" (_res)                                  \
03555          : /*in*/    "r" (&_argvec[2])                            \
03556          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
03557       );                                                          \
03558       lval = (__typeof__(lval)) _res;                             \
03559    } while (0)
03560 
03561 #endif /* PLAT_ppc64_aix5 */
03562 
03563 
03564 /* ------------------------------------------------------------------ */
03565 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
03566 /*                                                                    */
03567 /* ------------------------------------------------------------------ */
03568 
03569 /* Some request codes.  There are many more of these, but most are not
03570    exposed to end-user view.  These are the public ones, all of the
03571    form 0x1000 + small_number.
03572 
03573    Core ones are in the range 0x00000000--0x0000ffff.  The non-public
03574    ones start at 0x2000.
03575 */
03576 
03577 /* These macros are used by tools -- they must be public, but don't
03578    embed them into other programs. */
03579 #define VG_USERREQ_TOOL_BASE(a,b) \
03580    ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
03581 #define VG_IS_TOOL_USERREQ(a, b, v) \
03582    (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
03583 
03584 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 
03585    This enum comprises an ABI exported by Valgrind to programs
03586    which use client requests.  DO NOT CHANGE THE ORDER OF THESE
03587    ENTRIES, NOR DELETE ANY -- add new ones at the end. */
03588 typedef
03589    enum { VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
03590           VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
03591 
03592           /* These allow any function to be called from the simulated
03593              CPU but run on the real CPU.  Nb: the first arg passed to
03594              the function is always the ThreadId of the running
03595              thread!  So CLIENT_CALL0 actually requires a 1 arg
03596              function, etc. */
03597           VG_USERREQ__CLIENT_CALL0 = 0x1101,
03598           VG_USERREQ__CLIENT_CALL1 = 0x1102,
03599           VG_USERREQ__CLIENT_CALL2 = 0x1103,
03600           VG_USERREQ__CLIENT_CALL3 = 0x1104,
03601 
03602           /* Can be useful in regression testing suites -- eg. can
03603              send Valgrind's output to /dev/null and still count
03604              errors. */
03605           VG_USERREQ__COUNT_ERRORS = 0x1201,
03606 
03607           /* These are useful and can be interpreted by any tool that
03608              tracks malloc() et al, by using vg_replace_malloc.c. */
03609           VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
03610           VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
03611           /* Memory pool support. */
03612           VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
03613           VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
03614           VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
03615           VG_USERREQ__MEMPOOL_FREE     = 0x1306,
03616           VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
03617           VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
03618           VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
03619           VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
03620 
03621           /* Allow printfs to valgrind log. */
03622           VG_USERREQ__PRINTF           = 0x1401,
03623           VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
03624 
03625           /* Stack support. */
03626           VG_USERREQ__STACK_REGISTER   = 0x1501,
03627           VG_USERREQ__STACK_DEREGISTER = 0x1502,
03628           VG_USERREQ__STACK_CHANGE     = 0x1503
03629    } Vg_ClientRequest;
03630 
03631 #if !defined(__GNUC__)
03632 #  define __extension__ /* */
03633 #endif
03634 
03635 /* Returns the number of Valgrinds this code is running under.  That
03636    is, 0 if running natively, 1 if running under Valgrind, 2 if
03637    running under Valgrind which is running under another Valgrind,
03638    etc. */
03639 #define RUNNING_ON_VALGRIND  __extension__                        \
03640    ({unsigned int _qzz_res;                                       \
03641     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */,          \
03642                                VG_USERREQ__RUNNING_ON_VALGRIND,   \
03643                                0, 0, 0, 0, 0);                    \
03644     _qzz_res;                                                     \
03645    })
03646 
03647 
03648 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
03649    _qzz_len - 1].  Useful if you are debugging a JITter or some such,
03650    since it provides a way to make sure valgrind will retranslate the
03651    invalidated area.  Returns no value. */
03652 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len)         \
03653    {unsigned int _qzz_res;                                        \
03654     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03655                                VG_USERREQ__DISCARD_TRANSLATIONS,  \
03656                                _qzz_addr, _qzz_len, 0, 0, 0);     \
03657    }
03658 
03659 
03660 /* These requests are for getting Valgrind itself to print something.
03661    Possibly with a backtrace.  This is a really ugly hack. */
03662 
03663 #if defined(NVALGRIND)
03664 
03665 #  define VALGRIND_PRINTF(...)
03666 #  define VALGRIND_PRINTF_BACKTRACE(...)
03667 
03668 #else /* NVALGRIND */
03669 
03670 /* Modern GCC will optimize the static routine out if unused,
03671    and unused attribute will shut down warnings about it.  */
03672 static int VALGRIND_PRINTF(const char *format, ...)
03673    __attribute__((format(__printf__, 1, 2), __unused__));
03674 static int
03675 VALGRIND_PRINTF(const char *format, ...)
03676 {
03677    unsigned long _qzz_res;
03678    va_list vargs;
03679    va_start(vargs, format);
03680    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
03681                               (unsigned long)format, (unsigned long)vargs, 
03682                               0, 0, 0);
03683    va_end(vargs);
03684    return (int)_qzz_res;
03685 }
03686 
03687 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
03688    __attribute__((format(__printf__, 1, 2), __unused__));
03689 static int
03690 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
03691 {
03692    unsigned long _qzz_res;
03693    va_list vargs;
03694    va_start(vargs, format);
03695    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
03696                               (unsigned long)format, (unsigned long)vargs, 
03697                               0, 0, 0);
03698    va_end(vargs);
03699    return (int)_qzz_res;
03700 }
03701 
03702 #endif /* NVALGRIND */
03703 
03704 
03705 /* These requests allow control to move from the simulated CPU to the
03706    real CPU, calling an arbitary function.
03707    
03708    Note that the current ThreadId is inserted as the first argument.
03709    So this call:
03710 
03711      VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
03712 
03713    requires f to have this signature:
03714 
03715      Word f(Word tid, Word arg1, Word arg2)
03716 
03717    where "Word" is a word-sized type.
03718 
03719    Note that these client requests are not entirely reliable.  For example,
03720    if you call a function with them that subsequently calls printf(),
03721    there's a high chance Valgrind will crash.  Generally, your prospects of
03722    these working are made higher if the called function does not refer to
03723    any global variables, and does not refer to any libc or other functions
03724    (printf et al).  Any kind of entanglement with libc or dynamic linking is
03725    likely to have a bad outcome, for tricky reasons which we've grappled
03726    with a lot in the past.
03727 */
03728 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn)                          \
03729    __extension__                                                  \
03730    ({unsigned long _qyy_res;                                      \
03731     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
03732                                VG_USERREQ__CLIENT_CALL0,          \
03733                                _qyy_fn,                           \
03734                                0, 0, 0, 0);                       \
03735     _qyy_res;                                                     \
03736    })
03737 
03738 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1)               \
03739    __extension__                                                  \
03740    ({unsigned long _qyy_res;                                      \
03741     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
03742                                VG_USERREQ__CLIENT_CALL1,          \
03743                                _qyy_fn,                           \
03744                                _qyy_arg1, 0, 0, 0);               \
03745     _qyy_res;                                                     \
03746    })
03747 
03748 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2)    \
03749    __extension__                                                  \
03750    ({unsigned long _qyy_res;                                      \
03751     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
03752                                VG_USERREQ__CLIENT_CALL2,          \
03753                                _qyy_fn,                           \
03754                                _qyy_arg1, _qyy_arg2, 0, 0);       \
03755     _qyy_res;                                                     \
03756    })
03757 
03758 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
03759    __extension__                                                  \
03760    ({unsigned long _qyy_res;                                      \
03761     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
03762                                VG_USERREQ__CLIENT_CALL3,          \
03763                                _qyy_fn,                           \
03764                                _qyy_arg1, _qyy_arg2,              \
03765                                _qyy_arg3, 0);                     \
03766     _qyy_res;                                                     \
03767    })
03768 
03769 
03770 /* Counts the number of errors that have been recorded by a tool.  Nb:
03771    the tool must record the errors with VG_(maybe_record_error)() or
03772    VG_(unique_error)() for them to be counted. */
03773 #define VALGRIND_COUNT_ERRORS                                     \
03774    __extension__                                                  \
03775    ({unsigned int _qyy_res;                                       \
03776     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
03777                                VG_USERREQ__COUNT_ERRORS,          \
03778                                0, 0, 0, 0, 0);                    \
03779     _qyy_res;                                                     \
03780    })
03781 
03782 /* Mark a block of memory as having been allocated by a malloc()-like
03783    function.  `addr' is the start of the usable block (ie. after any
03784    redzone) `rzB' is redzone size if the allocator can apply redzones;
03785    use '0' if not.  Adding redzones makes it more likely Valgrind will spot
03786    block overruns.  `is_zeroed' indicates if the memory is zeroed, as it is
03787    for calloc().  Put it immediately after the point where a block is
03788    allocated. 
03789    
03790    If you're using Memcheck: If you're allocating memory via superblocks,
03791    and then handing out small chunks of each superblock, if you don't have
03792    redzones on your small blocks, it's worth marking the superblock with
03793    VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
03794    detected.  But if you can put redzones on, it's probably better to not do
03795    this, so that messages for small overruns are described in terms of the
03796    small block rather than the superblock (but if you have a big overrun
03797    that skips over a redzone, you could miss an error this way).  See
03798    memcheck/tests/custom_alloc.c for an example.
03799 
03800    WARNING: if your allocator uses malloc() or 'new' to allocate
03801    superblocks, rather than mmap() or brk(), this will not work properly --
03802    you'll likely get assertion failures during leak detection.  This is
03803    because Valgrind doesn't like seeing overlapping heap blocks.  Sorry.
03804 
03805    Nb: block must be freed via a free()-like function specified
03806    with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
03807 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)    \
03808    {unsigned int _qzz_res;                                        \
03809     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03810                                VG_USERREQ__MALLOCLIKE_BLOCK,      \
03811                                addr, sizeB, rzB, is_zeroed, 0);   \
03812    }
03813 
03814 /* Mark a block of memory as having been freed by a free()-like function.
03815    `rzB' is redzone size;  it must match that given to
03816    VALGRIND_MALLOCLIKE_BLOCK.  Memory not freed will be detected by the leak
03817    checker.  Put it immediately after the point where the block is freed. */
03818 #define VALGRIND_FREELIKE_BLOCK(addr, rzB)                        \
03819    {unsigned int _qzz_res;                                        \
03820     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03821                                VG_USERREQ__FREELIKE_BLOCK,        \
03822                                addr, rzB, 0, 0, 0);               \
03823    }
03824 
03825 /* Create a memory pool. */
03826 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)             \
03827    {unsigned int _qzz_res;                                        \
03828     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03829                                VG_USERREQ__CREATE_MEMPOOL,        \
03830                                pool, rzB, is_zeroed, 0, 0);       \
03831    }
03832 
03833 /* Destroy a memory pool. */
03834 #define VALGRIND_DESTROY_MEMPOOL(pool)                            \
03835    {unsigned int _qzz_res;                                        \
03836     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03837                                VG_USERREQ__DESTROY_MEMPOOL,       \
03838                                pool, 0, 0, 0, 0);                 \
03839    }
03840 
03841 /* Associate a piece of memory with a memory pool. */
03842 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)                  \
03843    {unsigned int _qzz_res;                                        \
03844     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03845                                VG_USERREQ__MEMPOOL_ALLOC,         \
03846                                pool, addr, size, 0, 0);           \
03847    }
03848 
03849 /* Disassociate a piece of memory from a memory pool. */
03850 #define VALGRIND_MEMPOOL_FREE(pool, addr)                         \
03851    {unsigned int _qzz_res;                                        \
03852     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03853                                VG_USERREQ__MEMPOOL_FREE,          \
03854                                pool, addr, 0, 0, 0);              \
03855    }
03856 
03857 /* Disassociate any pieces outside a particular range. */
03858 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size)                   \
03859    {unsigned int _qzz_res;                                        \
03860     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03861                                VG_USERREQ__MEMPOOL_TRIM,          \
03862                                pool, addr, size, 0, 0);           \
03863    }
03864 
03865 /* Resize and/or move a piece associated with a memory pool. */
03866 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB)                       \
03867    {unsigned int _qzz_res;                                        \
03868     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03869                                VG_USERREQ__MOVE_MEMPOOL,          \
03870                                poolA, poolB, 0, 0, 0);            \
03871    }
03872 
03873 /* Resize and/or move a piece associated with a memory pool. */
03874 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size)         \
03875    {unsigned int _qzz_res;                                        \
03876     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03877                                VG_USERREQ__MEMPOOL_CHANGE,        \
03878                                pool, addrA, addrB, size, 0);      \
03879    }
03880 
03881 /* Return 1 if a mempool exists, else 0. */
03882 #define VALGRIND_MEMPOOL_EXISTS(pool)                             \
03883    ({unsigned int _qzz_res;                                       \
03884     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03885                                VG_USERREQ__MEMPOOL_EXISTS,        \
03886                                pool, 0, 0, 0, 0);                 \
03887     _qzz_res;                                                     \
03888    })
03889 
03890 /* Mark a piece of memory as being a stack. Returns a stack id. */
03891 #define VALGRIND_STACK_REGISTER(start, end)                       \
03892    ({unsigned int _qzz_res;                                       \
03893     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03894                                VG_USERREQ__STACK_REGISTER,        \
03895                                start, end, 0, 0, 0);              \
03896     _qzz_res;                                                     \
03897    })
03898 
03899 /* Unmark the piece of memory associated with a stack id as being a
03900    stack. */
03901 #define VALGRIND_STACK_DEREGISTER(id)                             \
03902    {unsigned int _qzz_res;                                        \
03903     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03904                                VG_USERREQ__STACK_DEREGISTER,      \
03905                                id, 0, 0, 0, 0);                   \
03906    }
03907 
03908 /* Change the start and end address of the stack id. */
03909 #define VALGRIND_STACK_CHANGE(id, start, end)                     \
03910    {unsigned int _qzz_res;                                        \
03911     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
03912                                VG_USERREQ__STACK_CHANGE,          \
03913                                id, start, end, 0, 0);             \
03914    }
03915 
03916 
03917 #undef PLAT_x86_linux
03918 #undef PLAT_amd64_linux
03919 #undef PLAT_ppc32_linux
03920 #undef PLAT_ppc64_linux
03921 #undef PLAT_ppc32_aix5
03922 #undef PLAT_ppc64_aix5
03923 
03924 #endif   /* __VALGRIND_H */