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