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