Home | History | Annotate | Download | only in valgrind
      1 /* -*- c -*-
      2    ----------------------------------------------------------------
      3 
      4    Notice that the following BSD-style license applies to this one
      5    file (valgrind.h) only.  The rest of Valgrind is licensed under the
      6    terms of the GNU General Public License, version 2, unless
      7    otherwise indicated.  See the COPYING file in the source
      8    distribution for details.
      9 
     10    ----------------------------------------------------------------
     11 
     12    This file is part of Valgrind, a dynamic binary instrumentation
     13    framework.
     14 
     15    Copyright (C) 2000-2007 Julian Seward.  All rights reserved.
     16 
     17    Redistribution and use in source and binary forms, with or without
     18    modification, are permitted provided that the following conditions
     19    are met:
     20 
     21    1. Redistributions of source code must retain the above copyright
     22       notice, this list of conditions and the following disclaimer.
     23 
     24    2. The origin of this software must not be misrepresented; you must
     25       not claim that you wrote the original software.  If you use this
     26       software in a product, an acknowledgment in the product
     27       documentation would be appreciated but is not required.
     28 
     29    3. Altered source versions must be plainly marked as such, and must
     30       not be misrepresented as being the original software.
     31 
     32    4. The name of the author may not be used to endorse or promote
     33       products derived from this software without specific prior written
     34       permission.
     35 
     36    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     37    OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     38    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     39    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     40    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     41    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     42    GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     43    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     44    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     45    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     46    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     47 
     48    ----------------------------------------------------------------
     49 
     50    Notice that the above BSD-style license applies to this one file
     51    (valgrind.h) only.  The entire rest of Valgrind is licensed under
     52    the terms of the GNU General Public License, version 2.  See the
     53    COPYING file in the source distribution for details.
     54 
     55    ----------------------------------------------------------------
     56 */
     57 
     58 
     59 /* This file is for inclusion into client (your!) code.
     60 
     61    You can use these macros to manipulate and query Valgrind's
     62    execution inside your own programs.
     63 
     64    The resulting executables will still run without Valgrind, just a
     65    little bit more slowly than they otherwise would, but otherwise
     66    unchanged.  When not running on valgrind, each client request
     67    consumes very few (eg. 7) instructions, so the resulting performance
     68    loss is negligible unless you plan to execute client requests
     69    millions of times per second.  Nevertheless, if that is still a
     70    problem, you can compile with the NVALGRIND symbol defined (gcc
     71    -DNVALGRIND) so that client requests are not even compiled in.  */
     72 
     73 #ifndef __VALGRIND_H
     74 #define __VALGRIND_H
     75 
     76 #include <stdarg.h>
     77 #include <stdint.h>
     78 
     79 /* Nb: this file might be included in a file compiled with -ansi.  So
     80    we can't use C++ style "//" comments nor the "asm" keyword (instead
     81    use "__asm__"). */
     82 
     83 /* Derive some tags indicating what the target platform is.  Note
     84    that in this file we're using the compiler's CPP symbols for
     85    identifying architectures, which are different to the ones we use
     86    within the rest of Valgrind.  Note, __powerpc__ is active for both
     87    32 and 64-bit PPC, whereas __powerpc64__ is only active for the
     88    latter (on Linux, that is). */
     89 #undef PLAT_x86_linux
     90 #undef PLAT_amd64_linux
     91 #undef PLAT_ppc32_linux
     92 #undef PLAT_ppc64_linux
     93 #undef PLAT_ppc32_aix5
     94 #undef PLAT_ppc64_aix5
     95 
     96 #if !defined(_AIX) && defined(__i386__)
     97 #  define PLAT_x86_linux 1
     98 #elif !defined(_AIX) && defined(__x86_64__)
     99 #  define PLAT_amd64_linux 1
    100 #elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
    101 #  define PLAT_ppc32_linux 1
    102 #elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
    103 #  define PLAT_ppc64_linux 1
    104 #elif defined(_AIX) && defined(__64BIT__)
    105 #  define PLAT_ppc64_aix5 1
    106 #elif defined(_AIX) && !defined(__64BIT__)
    107 #  define PLAT_ppc32_aix5 1
    108 #endif
    109 
    110 
    111 /* If we're not compiling for our target platform, don't generate
    112    any inline asms.  */
    113 #if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
    114     && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
    115     && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
    116 #  if !defined(NVALGRIND)
    117 #    define NVALGRIND 1
    118 #  endif
    119 #endif
    120 
    121 
    122 /* ------------------------------------------------------------------ */
    123 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS.  There is nothing */
    124 /* in here of use to end-users -- skip to the next section.           */
    125 /* ------------------------------------------------------------------ */
    126 
    127 #if defined(NVALGRIND)
    128 
    129 /* Define NVALGRIND to completely remove the Valgrind magic sequence
    130    from the compiled code (analogous to NDEBUG's effects on
    131    assert()) */
    132 #define VALGRIND_DO_CLIENT_REQUEST(                               \
    133         _zzq_rlval, _zzq_default, _zzq_request,                   \
    134         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
    135    {                                                              \
    136       (_zzq_rlval) = (_zzq_default);                              \
    137    }
    138 
    139 #else  /* ! NVALGRIND */
    140 
    141 /* The following defines the magic code sequences which the JITter
    142    spots and handles magically.  Don't look too closely at them as
    143    they will rot your brain.
    144 
    145    The assembly code sequences for all architectures is in this one
    146    file.  This is because this file must be stand-alone, and we don't
    147    want to have multiple files.
    148 
    149    For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
    150    value gets put in the return slot, so that everything works when
    151    this is executed not under Valgrind.  Args are passed in a memory
    152    block, and so there's no intrinsic limit to the number that could
    153    be passed, but it's currently five.
    154 
    155    The macro args are:
    156       _zzq_rlval    result lvalue
    157       _zzq_default  default value (result returned when running on real CPU)
    158       _zzq_request  request code
    159       _zzq_arg1..5  request params
    160 
    161    The other two macros are used to support function wrapping, and are
    162    a lot simpler.  VALGRIND_GET_NR_CONTEXT returns the value of the
    163    guest's NRADDR pseudo-register and whatever other information is
    164    needed to safely run the call original from the wrapper: on
    165    ppc64-linux, the R2 value at the divert point is also needed.  This
    166    information is abstracted into a user-visible type, OrigFn.
    167 
    168    VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
    169    guest, but guarantees that the branch instruction will not be
    170    redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
    171    branch-and-link-to-r11.  VALGRIND_CALL_NOREDIR is just text, not a
    172    complete inline asm, since it needs to be combined with more magic
    173    inline asm stuff to be useful.
    174 */
    175 
    176 /* ------------------------- x86-linux ------------------------- */
    177 
    178 #if defined(PLAT_x86_linux)
    179 
    180 typedef
    181    struct {
    182       unsigned int nraddr; /* where's the code? */
    183    }
    184    OrigFn;
    185 
    186 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
    187                      "roll $3,  %%edi ; roll $13, %%edi\n\t"      \
    188                      "roll $29, %%edi ; roll $19, %%edi\n\t"
    189 
    190 #define VALGRIND_DO_CLIENT_REQUEST(                               \
    191         _zzq_rlval, _zzq_default, _zzq_request,                   \
    192         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
    193   { volatile unsigned int _zzq_args[6];                           \
    194     volatile unsigned int _zzq_result;                            \
    195     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
    196     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
    197     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
    198     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
    199     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
    200     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
    201     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    202                      /* %EDX = client_request ( %EAX ) */         \
    203                      "xchgl %%ebx,%%ebx"                          \
    204                      : "=d" (_zzq_result)                         \
    205                      : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
    206                      : "cc", "memory"                             \
    207                     );                                            \
    208     _zzq_rlval = _zzq_result;                                     \
    209   }
    210 
    211 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
    212   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
    213     volatile unsigned int __addr;                                 \
    214     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    215                      /* %EAX = guest_NRADDR */                    \
    216                      "xchgl %%ecx,%%ecx"                          \
    217                      : "=a" (__addr)                              \
    218                      :                                            \
    219                      : "cc", "memory"                             \
    220                     );                                            \
    221     _zzq_orig->nraddr = __addr;                                   \
    222   }
    223 
    224 #define VALGRIND_CALL_NOREDIR_EAX                                 \
    225                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    226                      /* call-noredir *%EAX */                     \
    227                      "xchgl %%edx,%%edx\n\t"
    228 #endif /* PLAT_x86_linux */
    229 
    230 /* ------------------------ amd64-linux ------------------------ */
    231 
    232 #if defined(PLAT_amd64_linux)
    233 
    234 typedef
    235    struct {
    236       uint64_t nraddr; /* where's the code? */
    237    }
    238    OrigFn;
    239 
    240 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
    241                      "rolq $3,  %%rdi ; rolq $13, %%rdi\n\t"      \
    242                      "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
    243 
    244 #define VALGRIND_DO_CLIENT_REQUEST(                               \
    245         _zzq_rlval, _zzq_default, _zzq_request,                   \
    246         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
    247   { volatile uint64_t _zzq_args[6];                 \
    248     volatile uint64_t _zzq_result;                  \
    249     _zzq_args[0] = (uint64_t)(_zzq_request);        \
    250     _zzq_args[1] = (uint64_t)(_zzq_arg1);           \
    251     _zzq_args[2] = (uint64_t)(_zzq_arg2);           \
    252     _zzq_args[3] = (uint64_t)(_zzq_arg3);           \
    253     _zzq_args[4] = (uint64_t)(_zzq_arg4);           \
    254     _zzq_args[5] = (uint64_t)(_zzq_arg5);           \
    255     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    256                      /* %RDX = client_request ( %RAX ) */         \
    257                      "xchgq %%rbx,%%rbx"                          \
    258                      : "=d" (_zzq_result)                         \
    259                      : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
    260                      : "cc", "memory"                             \
    261                     );                                            \
    262     _zzq_rlval = _zzq_result;                                     \
    263   }
    264 
    265 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
    266   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
    267     volatile uint64_t __addr;                       \
    268     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    269                      /* %RAX = guest_NRADDR */                    \
    270                      "xchgq %%rcx,%%rcx"                          \
    271                      : "=a" (__addr)                              \
    272                      :                                            \
    273                      : "cc", "memory"                             \
    274                     );                                            \
    275     _zzq_orig->nraddr = __addr;                                   \
    276   }
    277 
    278 #define VALGRIND_CALL_NOREDIR_RAX                                 \
    279                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    280                      /* call-noredir *%RAX */                     \
    281                      "xchgq %%rdx,%%rdx\n\t"
    282 #endif /* PLAT_amd64_linux */
    283 
    284 /* ------------------------ ppc32-linux ------------------------ */
    285 
    286 #if defined(PLAT_ppc32_linux)
    287 
    288 typedef
    289    struct {
    290       unsigned int nraddr; /* where's the code? */
    291    }
    292    OrigFn;
    293 
    294 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
    295                      "rlwinm 0,0,3,0,0  ; rlwinm 0,0,13,0,0\n\t"  \
    296                      "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
    297 
    298 #define VALGRIND_DO_CLIENT_REQUEST(                               \
    299         _zzq_rlval, _zzq_default, _zzq_request,                   \
    300         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
    301                                                                   \
    302   {          unsigned int  _zzq_args[6];                          \
    303              unsigned int  _zzq_result;                           \
    304              unsigned int* _zzq_ptr;                              \
    305     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
    306     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
    307     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
    308     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
    309     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
    310     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
    311     _zzq_ptr = _zzq_args;                                         \
    312     __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
    313                      "mr 4,%2\n\t" /*ptr*/                        \
    314                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    315                      /* %R3 = client_request ( %R4 ) */           \
    316                      "or 1,1,1\n\t"                               \
    317                      "mr %0,3"     /*result*/                     \
    318                      : "=b" (_zzq_result)                         \
    319                      : "b" (_zzq_default), "b" (_zzq_ptr)         \
    320                      : "cc", "memory", "r3", "r4");               \
    321     _zzq_rlval = _zzq_result;                                     \
    322   }
    323 
    324 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
    325   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
    326     unsigned int __addr;                                          \
    327     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    328                      /* %R3 = guest_NRADDR */                     \
    329                      "or 2,2,2\n\t"                               \
    330                      "mr %0,3"                                    \
    331                      : "=b" (__addr)                              \
    332                      :                                            \
    333                      : "cc", "memory", "r3"                       \
    334                     );                                            \
    335     _zzq_orig->nraddr = __addr;                                   \
    336   }
    337 
    338 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
    339                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    340                      /* branch-and-link-to-noredir *%R11 */       \
    341                      "or 3,3,3\n\t"
    342 #endif /* PLAT_ppc32_linux */
    343 
    344 /* ------------------------ ppc64-linux ------------------------ */
    345 
    346 #if defined(PLAT_ppc64_linux)
    347 
    348 typedef
    349    struct {
    350       uint64_t nraddr; /* where's the code? */
    351       uint64_t r2;  /* what tocptr do we need? */
    352    }
    353    OrigFn;
    354 
    355 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
    356                      "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
    357                      "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
    358 
    359 #define VALGRIND_DO_CLIENT_REQUEST(                               \
    360         _zzq_rlval, _zzq_default, _zzq_request,                   \
    361         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
    362                                                                   \
    363   {          uint64_t  _zzq_args[6];                \
    364     register uint64_t  _zzq_result __asm__("r3");   \
    365     register uint64_t* _zzq_ptr __asm__("r4");      \
    366     _zzq_args[0] = (uint64_t)(_zzq_request);        \
    367     _zzq_args[1] = (uint64_t)(_zzq_arg1);           \
    368     _zzq_args[2] = (uint64_t)(_zzq_arg2);           \
    369     _zzq_args[3] = (uint64_t)(_zzq_arg3);           \
    370     _zzq_args[4] = (uint64_t)(_zzq_arg4);           \
    371     _zzq_args[5] = (uint64_t)(_zzq_arg5);           \
    372     _zzq_ptr = _zzq_args;                                         \
    373     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    374                      /* %R3 = client_request ( %R4 ) */           \
    375                      "or 1,1,1"                                   \
    376                      : "=r" (_zzq_result)                         \
    377                      : "0" (_zzq_default), "r" (_zzq_ptr)         \
    378                      : "cc", "memory");                           \
    379     _zzq_rlval = _zzq_result;                                     \
    380   }
    381 
    382 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
    383   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
    384     register uint64_t __addr __asm__("r3");         \
    385     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    386                      /* %R3 = guest_NRADDR */                     \
    387                      "or 2,2,2"                                   \
    388                      : "=r" (__addr)                              \
    389                      :                                            \
    390                      : "cc", "memory"                             \
    391                     );                                            \
    392     _zzq_orig->nraddr = __addr;                                   \
    393     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    394                      /* %R3 = guest_NRADDR_GPR2 */                \
    395                      "or 4,4,4"                                   \
    396                      : "=r" (__addr)                              \
    397                      :                                            \
    398                      : "cc", "memory"                             \
    399                     );                                            \
    400     _zzq_orig->r2 = __addr;                                       \
    401   }
    402 
    403 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
    404                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    405                      /* branch-and-link-to-noredir *%R11 */       \
    406                      "or 3,3,3\n\t"
    407 
    408 #endif /* PLAT_ppc64_linux */
    409 
    410 /* ------------------------ ppc32-aix5 ------------------------- */
    411 
    412 #if defined(PLAT_ppc32_aix5)
    413 
    414 typedef
    415    struct {
    416       unsigned int nraddr; /* where's the code? */
    417       unsigned int r2;  /* what tocptr do we need? */
    418    }
    419    OrigFn;
    420 
    421 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
    422                      "rlwinm 0,0,3,0,0  ; rlwinm 0,0,13,0,0\n\t"  \
    423                      "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
    424 
    425 #define VALGRIND_DO_CLIENT_REQUEST(                               \
    426         _zzq_rlval, _zzq_default, _zzq_request,                   \
    427         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
    428                                                                   \
    429   {          unsigned int  _zzq_args[7];                          \
    430     register unsigned int  _zzq_result;                           \
    431     register unsigned int* _zzq_ptr;                              \
    432     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
    433     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
    434     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
    435     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
    436     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
    437     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
    438     _zzq_args[6] = (unsigned int)(_zzq_default);                  \
    439     _zzq_ptr = _zzq_args;                                         \
    440     __asm__ volatile("mr 4,%1\n\t"                                \
    441                      "lwz 3, 24(4)\n\t"                           \
    442                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    443                      /* %R3 = client_request ( %R4 ) */           \
    444                      "or 1,1,1\n\t"                               \
    445                      "mr %0,3"                                    \
    446                      : "=b" (_zzq_result)                         \
    447                      : "b" (_zzq_ptr)                             \
    448                      : "r3", "r4", "cc", "memory");               \
    449     _zzq_rlval = _zzq_result;                                     \
    450   }
    451 
    452 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
    453   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
    454     register unsigned int __addr;                                 \
    455     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    456                      /* %R3 = guest_NRADDR */                     \
    457                      "or 2,2,2\n\t"                               \
    458                      "mr %0,3"                                    \
    459                      : "=b" (__addr)                              \
    460                      :                                            \
    461                      : "r3", "cc", "memory"                       \
    462                     );                                            \
    463     _zzq_orig->nraddr = __addr;                                   \
    464     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    465                      /* %R3 = guest_NRADDR_GPR2 */                \
    466                      "or 4,4,4\n\t"                               \
    467                      "mr %0,3"                                    \
    468                      : "=b" (__addr)                              \
    469                      :                                            \
    470                      : "r3", "cc", "memory"                       \
    471                     );                                            \
    472     _zzq_orig->r2 = __addr;                                       \
    473   }
    474 
    475 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
    476                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    477                      /* branch-and-link-to-noredir *%R11 */       \
    478                      "or 3,3,3\n\t"
    479 
    480 #endif /* PLAT_ppc32_aix5 */
    481 
    482 /* ------------------------ ppc64-aix5 ------------------------- */
    483 
    484 #if defined(PLAT_ppc64_aix5)
    485 
    486 typedef
    487    struct {
    488       uint64_t nraddr; /* where's the code? */
    489       uint64_t r2;  /* what tocptr do we need? */
    490    }
    491    OrigFn;
    492 
    493 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
    494                      "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
    495                      "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
    496 
    497 #define VALGRIND_DO_CLIENT_REQUEST(                               \
    498         _zzq_rlval, _zzq_default, _zzq_request,                   \
    499         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
    500                                                                   \
    501   {          uint64_t  _zzq_args[7];                \
    502     register uint64_t  _zzq_result;                 \
    503     register uint64_t* _zzq_ptr;                    \
    504     _zzq_args[0] = (unsigned int long long)(_zzq_request);        \
    505     _zzq_args[1] = (unsigned int long long)(_zzq_arg1);           \
    506     _zzq_args[2] = (unsigned int long long)(_zzq_arg2);           \
    507     _zzq_args[3] = (unsigned int long long)(_zzq_arg3);           \
    508     _zzq_args[4] = (unsigned int long long)(_zzq_arg4);           \
    509     _zzq_args[5] = (unsigned int long long)(_zzq_arg5);           \
    510     _zzq_args[6] = (unsigned int long long)(_zzq_default);        \
    511     _zzq_ptr = _zzq_args;                                         \
    512     __asm__ volatile("mr 4,%1\n\t"                                \
    513                      "ld 3, 48(4)\n\t"                            \
    514                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    515                      /* %R3 = client_request ( %R4 ) */           \
    516                      "or 1,1,1\n\t"                               \
    517                      "mr %0,3"                                    \
    518                      : "=b" (_zzq_result)                         \
    519                      : "b" (_zzq_ptr)                             \
    520                      : "r3", "r4", "cc", "memory");               \
    521     _zzq_rlval = _zzq_result;                                     \
    522   }
    523 
    524 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
    525   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
    526     register uint64_t __addr;                       \
    527     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    528                      /* %R3 = guest_NRADDR */                     \
    529                      "or 2,2,2\n\t"                               \
    530                      "mr %0,3"                                    \
    531                      : "=b" (__addr)                              \
    532                      :                                            \
    533                      : "r3", "cc", "memory"                       \
    534                     );                                            \
    535     _zzq_orig->nraddr = __addr;                                   \
    536     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
    537                      /* %R3 = guest_NRADDR_GPR2 */                \
    538                      "or 4,4,4\n\t"                               \
    539                      "mr %0,3"                                    \
    540                      : "=b" (__addr)                              \
    541                      :                                            \
    542                      : "r3", "cc", "memory"                       \
    543                     );                                            \
    544     _zzq_orig->r2 = __addr;                                       \
    545   }
    546 
    547 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
    548                      __SPECIAL_INSTRUCTION_PREAMBLE               \
    549                      /* branch-and-link-to-noredir *%R11 */       \
    550                      "or 3,3,3\n\t"
    551 
    552 #endif /* PLAT_ppc64_aix5 */
    553 
    554 /* Insert assembly code for other platforms here... */
    555 
    556 #endif /* NVALGRIND */
    557 
    558 
    559 /* ------------------------------------------------------------------ */
    560 /* PLATFORM SPECIFICS for FUNCTION WRAPPING.  This is all very        */
    561 /* ugly.  It's the least-worst tradeoff I can think of.               */
    562 /* ------------------------------------------------------------------ */
    563 
    564 /* This section defines magic (a.k.a appalling-hack) macros for doing
    565    guaranteed-no-redirection macros, so as to get from function
    566    wrappers to the functions they are wrapping.  The whole point is to
    567    construct standard call sequences, but to do the call itself with a
    568    special no-redirect call pseudo-instruction that the JIT
    569    understands and handles specially.  This section is long and
    570    repetitious, and I can't see a way to make it shorter.
    571 
    572    The naming scheme is as follows:
    573 
    574       CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
    575 
    576    'W' stands for "word" and 'v' for "void".  Hence there are
    577    different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
    578    and for each, the possibility of returning a word-typed result, or
    579    no result.
    580 */
    581 
    582 /* Use these to write the name of your wrapper.  NOTE: duplicates
    583    VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
    584 
    585 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname)                    \
    586    _vgwZU_##soname##_##fnname
    587 
    588 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname)                    \
    589    _vgwZZ_##soname##_##fnname
    590 
    591 /* Use this macro from within a wrapper function to collect the
    592    context (address and possibly other info) of the original function.
    593    Once you have that you can then use it in one of the CALL_FN_
    594    macros.  The type of the argument _lval is OrigFn. */
    595 #define VALGRIND_GET_ORIG_FN(_lval)  VALGRIND_GET_NR_CONTEXT(_lval)
    596 
    597 /* Derivatives of the main macros below, for calling functions
    598    returning void. */
    599 
    600 #define CALL_FN_v_v(fnptr)                                        \
    601    do { volatile unsigned long _junk;                             \
    602         CALL_FN_W_v(_junk,fnptr); } while (0)
    603 
    604 #define CALL_FN_v_W(fnptr, arg1)                                  \
    605    do { volatile unsigned long _junk;                             \
    606         CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
    607 
    608 #define CALL_FN_v_WW(fnptr, arg1,arg2)                            \
    609    do { volatile unsigned long _junk;                             \
    610         CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
    611 
    612 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3)                      \
    613    do { volatile unsigned long _junk;                             \
    614         CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
    615 
    616 /* ------------------------- x86-linux ------------------------- */
    617 
    618 #if defined(PLAT_x86_linux)
    619 
    620 /* These regs are trashed by the hidden call.  No need to mention eax
    621    as gcc can already see that, plus causes gcc to bomb. */
    622 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
    623 
    624 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
    625    long) == 4. */
    626 
    627 #define CALL_FN_W_v(lval, orig)                                   \
    628    do {                                                           \
    629       volatile OrigFn        _orig = (orig);                      \
    630       volatile unsigned long _argvec[1];                          \
    631       volatile unsigned long _res;                                \
    632       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    633       __asm__ volatile(                                           \
    634          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    635          VALGRIND_CALL_NOREDIR_EAX                                \
    636          : /*out*/   "=a" (_res)                                  \
    637          : /*in*/    "a" (&_argvec[0])                            \
    638          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    639       );                                                          \
    640       lval = (__typeof__(lval)) _res;                             \
    641    } while (0)
    642 
    643 #define CALL_FN_W_W(lval, orig, arg1)                             \
    644    do {                                                           \
    645       volatile OrigFn        _orig = (orig);                      \
    646       volatile unsigned long _argvec[2];                          \
    647       volatile unsigned long _res;                                \
    648       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    649       _argvec[1] = (unsigned long)(arg1);                         \
    650       __asm__ volatile(                                           \
    651          "pushl 4(%%eax)\n\t"                                     \
    652          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    653          VALGRIND_CALL_NOREDIR_EAX                                \
    654          "addl $4, %%esp\n"                                       \
    655          : /*out*/   "=a" (_res)                                  \
    656          : /*in*/    "a" (&_argvec[0])                            \
    657          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    658       );                                                          \
    659       lval = (__typeof__(lval)) _res;                             \
    660    } while (0)
    661 
    662 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
    663    do {                                                           \
    664       volatile OrigFn        _orig = (orig);                      \
    665       volatile unsigned long _argvec[3];                          \
    666       volatile unsigned long _res;                                \
    667       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    668       _argvec[1] = (unsigned long)(arg1);                         \
    669       _argvec[2] = (unsigned long)(arg2);                         \
    670       __asm__ volatile(                                           \
    671          "pushl 8(%%eax)\n\t"                                     \
    672          "pushl 4(%%eax)\n\t"                                     \
    673          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    674          VALGRIND_CALL_NOREDIR_EAX                                \
    675          "addl $8, %%esp\n"                                       \
    676          : /*out*/   "=a" (_res)                                  \
    677          : /*in*/    "a" (&_argvec[0])                            \
    678          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    679       );                                                          \
    680       lval = (__typeof__(lval)) _res;                             \
    681    } while (0)
    682 
    683 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
    684    do {                                                           \
    685       volatile OrigFn        _orig = (orig);                      \
    686       volatile unsigned long _argvec[4];                          \
    687       volatile unsigned long _res;                                \
    688       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    689       _argvec[1] = (unsigned long)(arg1);                         \
    690       _argvec[2] = (unsigned long)(arg2);                         \
    691       _argvec[3] = (unsigned long)(arg3);                         \
    692       __asm__ volatile(                                           \
    693          "pushl 12(%%eax)\n\t"                                    \
    694          "pushl 8(%%eax)\n\t"                                     \
    695          "pushl 4(%%eax)\n\t"                                     \
    696          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    697          VALGRIND_CALL_NOREDIR_EAX                                \
    698          "addl $12, %%esp\n"                                      \
    699          : /*out*/   "=a" (_res)                                  \
    700          : /*in*/    "a" (&_argvec[0])                            \
    701          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    702       );                                                          \
    703       lval = (__typeof__(lval)) _res;                             \
    704    } while (0)
    705 
    706 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
    707    do {                                                           \
    708       volatile OrigFn        _orig = (orig);                      \
    709       volatile unsigned long _argvec[5];                          \
    710       volatile unsigned long _res;                                \
    711       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    712       _argvec[1] = (unsigned long)(arg1);                         \
    713       _argvec[2] = (unsigned long)(arg2);                         \
    714       _argvec[3] = (unsigned long)(arg3);                         \
    715       _argvec[4] = (unsigned long)(arg4);                         \
    716       __asm__ volatile(                                           \
    717          "pushl 16(%%eax)\n\t"                                    \
    718          "pushl 12(%%eax)\n\t"                                    \
    719          "pushl 8(%%eax)\n\t"                                     \
    720          "pushl 4(%%eax)\n\t"                                     \
    721          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    722          VALGRIND_CALL_NOREDIR_EAX                                \
    723          "addl $16, %%esp\n"                                      \
    724          : /*out*/   "=a" (_res)                                  \
    725          : /*in*/    "a" (&_argvec[0])                            \
    726          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    727       );                                                          \
    728       lval = (__typeof__(lval)) _res;                             \
    729    } while (0)
    730 
    731 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
    732    do {                                                           \
    733       volatile OrigFn        _orig = (orig);                      \
    734       volatile unsigned long _argvec[6];                          \
    735       volatile unsigned long _res;                                \
    736       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    737       _argvec[1] = (unsigned long)(arg1);                         \
    738       _argvec[2] = (unsigned long)(arg2);                         \
    739       _argvec[3] = (unsigned long)(arg3);                         \
    740       _argvec[4] = (unsigned long)(arg4);                         \
    741       _argvec[5] = (unsigned long)(arg5);                         \
    742       __asm__ volatile(                                           \
    743          "pushl 20(%%eax)\n\t"                                    \
    744          "pushl 16(%%eax)\n\t"                                    \
    745          "pushl 12(%%eax)\n\t"                                    \
    746          "pushl 8(%%eax)\n\t"                                     \
    747          "pushl 4(%%eax)\n\t"                                     \
    748          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    749          VALGRIND_CALL_NOREDIR_EAX                                \
    750          "addl $20, %%esp\n"                                      \
    751          : /*out*/   "=a" (_res)                                  \
    752          : /*in*/    "a" (&_argvec[0])                            \
    753          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    754       );                                                          \
    755       lval = (__typeof__(lval)) _res;                             \
    756    } while (0)
    757 
    758 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
    759    do {                                                           \
    760       volatile OrigFn        _orig = (orig);                      \
    761       volatile unsigned long _argvec[7];                          \
    762       volatile unsigned long _res;                                \
    763       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    764       _argvec[1] = (unsigned long)(arg1);                         \
    765       _argvec[2] = (unsigned long)(arg2);                         \
    766       _argvec[3] = (unsigned long)(arg3);                         \
    767       _argvec[4] = (unsigned long)(arg4);                         \
    768       _argvec[5] = (unsigned long)(arg5);                         \
    769       _argvec[6] = (unsigned long)(arg6);                         \
    770       __asm__ volatile(                                           \
    771          "pushl 24(%%eax)\n\t"                                    \
    772          "pushl 20(%%eax)\n\t"                                    \
    773          "pushl 16(%%eax)\n\t"                                    \
    774          "pushl 12(%%eax)\n\t"                                    \
    775          "pushl 8(%%eax)\n\t"                                     \
    776          "pushl 4(%%eax)\n\t"                                     \
    777          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    778          VALGRIND_CALL_NOREDIR_EAX                                \
    779          "addl $24, %%esp\n"                                      \
    780          : /*out*/   "=a" (_res)                                  \
    781          : /*in*/    "a" (&_argvec[0])                            \
    782          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    783       );                                                          \
    784       lval = (__typeof__(lval)) _res;                             \
    785    } while (0)
    786 
    787 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
    788                                  arg7)                            \
    789    do {                                                           \
    790       volatile OrigFn        _orig = (orig);                      \
    791       volatile unsigned long _argvec[8];                          \
    792       volatile unsigned long _res;                                \
    793       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    794       _argvec[1] = (unsigned long)(arg1);                         \
    795       _argvec[2] = (unsigned long)(arg2);                         \
    796       _argvec[3] = (unsigned long)(arg3);                         \
    797       _argvec[4] = (unsigned long)(arg4);                         \
    798       _argvec[5] = (unsigned long)(arg5);                         \
    799       _argvec[6] = (unsigned long)(arg6);                         \
    800       _argvec[7] = (unsigned long)(arg7);                         \
    801       __asm__ volatile(                                           \
    802          "pushl 28(%%eax)\n\t"                                    \
    803          "pushl 24(%%eax)\n\t"                                    \
    804          "pushl 20(%%eax)\n\t"                                    \
    805          "pushl 16(%%eax)\n\t"                                    \
    806          "pushl 12(%%eax)\n\t"                                    \
    807          "pushl 8(%%eax)\n\t"                                     \
    808          "pushl 4(%%eax)\n\t"                                     \
    809          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    810          VALGRIND_CALL_NOREDIR_EAX                                \
    811          "addl $28, %%esp\n"                                      \
    812          : /*out*/   "=a" (_res)                                  \
    813          : /*in*/    "a" (&_argvec[0])                            \
    814          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    815       );                                                          \
    816       lval = (__typeof__(lval)) _res;                             \
    817    } while (0)
    818 
    819 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
    820                                  arg7,arg8)                       \
    821    do {                                                           \
    822       volatile OrigFn        _orig = (orig);                      \
    823       volatile unsigned long _argvec[9];                          \
    824       volatile unsigned long _res;                                \
    825       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    826       _argvec[1] = (unsigned long)(arg1);                         \
    827       _argvec[2] = (unsigned long)(arg2);                         \
    828       _argvec[3] = (unsigned long)(arg3);                         \
    829       _argvec[4] = (unsigned long)(arg4);                         \
    830       _argvec[5] = (unsigned long)(arg5);                         \
    831       _argvec[6] = (unsigned long)(arg6);                         \
    832       _argvec[7] = (unsigned long)(arg7);                         \
    833       _argvec[8] = (unsigned long)(arg8);                         \
    834       __asm__ volatile(                                           \
    835          "pushl 32(%%eax)\n\t"                                    \
    836          "pushl 28(%%eax)\n\t"                                    \
    837          "pushl 24(%%eax)\n\t"                                    \
    838          "pushl 20(%%eax)\n\t"                                    \
    839          "pushl 16(%%eax)\n\t"                                    \
    840          "pushl 12(%%eax)\n\t"                                    \
    841          "pushl 8(%%eax)\n\t"                                     \
    842          "pushl 4(%%eax)\n\t"                                     \
    843          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    844          VALGRIND_CALL_NOREDIR_EAX                                \
    845          "addl $32, %%esp\n"                                      \
    846          : /*out*/   "=a" (_res)                                  \
    847          : /*in*/    "a" (&_argvec[0])                            \
    848          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    849       );                                                          \
    850       lval = (__typeof__(lval)) _res;                             \
    851    } while (0)
    852 
    853 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
    854                                  arg7,arg8,arg9)                  \
    855    do {                                                           \
    856       volatile OrigFn        _orig = (orig);                      \
    857       volatile unsigned long _argvec[10];                         \
    858       volatile unsigned long _res;                                \
    859       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    860       _argvec[1] = (unsigned long)(arg1);                         \
    861       _argvec[2] = (unsigned long)(arg2);                         \
    862       _argvec[3] = (unsigned long)(arg3);                         \
    863       _argvec[4] = (unsigned long)(arg4);                         \
    864       _argvec[5] = (unsigned long)(arg5);                         \
    865       _argvec[6] = (unsigned long)(arg6);                         \
    866       _argvec[7] = (unsigned long)(arg7);                         \
    867       _argvec[8] = (unsigned long)(arg8);                         \
    868       _argvec[9] = (unsigned long)(arg9);                         \
    869       __asm__ volatile(                                           \
    870          "pushl 36(%%eax)\n\t"                                    \
    871          "pushl 32(%%eax)\n\t"                                    \
    872          "pushl 28(%%eax)\n\t"                                    \
    873          "pushl 24(%%eax)\n\t"                                    \
    874          "pushl 20(%%eax)\n\t"                                    \
    875          "pushl 16(%%eax)\n\t"                                    \
    876          "pushl 12(%%eax)\n\t"                                    \
    877          "pushl 8(%%eax)\n\t"                                     \
    878          "pushl 4(%%eax)\n\t"                                     \
    879          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    880          VALGRIND_CALL_NOREDIR_EAX                                \
    881          "addl $36, %%esp\n"                                      \
    882          : /*out*/   "=a" (_res)                                  \
    883          : /*in*/    "a" (&_argvec[0])                            \
    884          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    885       );                                                          \
    886       lval = (__typeof__(lval)) _res;                             \
    887    } while (0)
    888 
    889 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
    890                                   arg7,arg8,arg9,arg10)           \
    891    do {                                                           \
    892       volatile OrigFn        _orig = (orig);                      \
    893       volatile unsigned long _argvec[11];                         \
    894       volatile unsigned long _res;                                \
    895       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    896       _argvec[1] = (unsigned long)(arg1);                         \
    897       _argvec[2] = (unsigned long)(arg2);                         \
    898       _argvec[3] = (unsigned long)(arg3);                         \
    899       _argvec[4] = (unsigned long)(arg4);                         \
    900       _argvec[5] = (unsigned long)(arg5);                         \
    901       _argvec[6] = (unsigned long)(arg6);                         \
    902       _argvec[7] = (unsigned long)(arg7);                         \
    903       _argvec[8] = (unsigned long)(arg8);                         \
    904       _argvec[9] = (unsigned long)(arg9);                         \
    905       _argvec[10] = (unsigned long)(arg10);                       \
    906       __asm__ volatile(                                           \
    907          "pushl 40(%%eax)\n\t"                                    \
    908          "pushl 36(%%eax)\n\t"                                    \
    909          "pushl 32(%%eax)\n\t"                                    \
    910          "pushl 28(%%eax)\n\t"                                    \
    911          "pushl 24(%%eax)\n\t"                                    \
    912          "pushl 20(%%eax)\n\t"                                    \
    913          "pushl 16(%%eax)\n\t"                                    \
    914          "pushl 12(%%eax)\n\t"                                    \
    915          "pushl 8(%%eax)\n\t"                                     \
    916          "pushl 4(%%eax)\n\t"                                     \
    917          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    918          VALGRIND_CALL_NOREDIR_EAX                                \
    919          "addl $40, %%esp\n"                                      \
    920          : /*out*/   "=a" (_res)                                  \
    921          : /*in*/    "a" (&_argvec[0])                            \
    922          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    923       );                                                          \
    924       lval = (__typeof__(lval)) _res;                             \
    925    } while (0)
    926 
    927 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
    928                                   arg6,arg7,arg8,arg9,arg10,      \
    929                                   arg11)                          \
    930    do {                                                           \
    931       volatile OrigFn        _orig = (orig);                      \
    932       volatile unsigned long _argvec[12];                         \
    933       volatile unsigned long _res;                                \
    934       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    935       _argvec[1] = (unsigned long)(arg1);                         \
    936       _argvec[2] = (unsigned long)(arg2);                         \
    937       _argvec[3] = (unsigned long)(arg3);                         \
    938       _argvec[4] = (unsigned long)(arg4);                         \
    939       _argvec[5] = (unsigned long)(arg5);                         \
    940       _argvec[6] = (unsigned long)(arg6);                         \
    941       _argvec[7] = (unsigned long)(arg7);                         \
    942       _argvec[8] = (unsigned long)(arg8);                         \
    943       _argvec[9] = (unsigned long)(arg9);                         \
    944       _argvec[10] = (unsigned long)(arg10);                       \
    945       _argvec[11] = (unsigned long)(arg11);                       \
    946       __asm__ volatile(                                           \
    947          "pushl 44(%%eax)\n\t"                                    \
    948          "pushl 40(%%eax)\n\t"                                    \
    949          "pushl 36(%%eax)\n\t"                                    \
    950          "pushl 32(%%eax)\n\t"                                    \
    951          "pushl 28(%%eax)\n\t"                                    \
    952          "pushl 24(%%eax)\n\t"                                    \
    953          "pushl 20(%%eax)\n\t"                                    \
    954          "pushl 16(%%eax)\n\t"                                    \
    955          "pushl 12(%%eax)\n\t"                                    \
    956          "pushl 8(%%eax)\n\t"                                     \
    957          "pushl 4(%%eax)\n\t"                                     \
    958          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
    959          VALGRIND_CALL_NOREDIR_EAX                                \
    960          "addl $44, %%esp\n"                                      \
    961          : /*out*/   "=a" (_res)                                  \
    962          : /*in*/    "a" (&_argvec[0])                            \
    963          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
    964       );                                                          \
    965       lval = (__typeof__(lval)) _res;                             \
    966    } while (0)
    967 
    968 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
    969                                   arg6,arg7,arg8,arg9,arg10,      \
    970                                   arg11,arg12)                    \
    971    do {                                                           \
    972       volatile OrigFn        _orig = (orig);                      \
    973       volatile unsigned long _argvec[13];                         \
    974       volatile unsigned long _res;                                \
    975       _argvec[0] = (unsigned long)_orig.nraddr;                   \
    976       _argvec[1] = (unsigned long)(arg1);                         \
    977       _argvec[2] = (unsigned long)(arg2);                         \
    978       _argvec[3] = (unsigned long)(arg3);                         \
    979       _argvec[4] = (unsigned long)(arg4);                         \
    980       _argvec[5] = (unsigned long)(arg5);                         \
    981       _argvec[6] = (unsigned long)(arg6);                         \
    982       _argvec[7] = (unsigned long)(arg7);                         \
    983       _argvec[8] = (unsigned long)(arg8);                         \
    984       _argvec[9] = (unsigned long)(arg9);                         \
    985       _argvec[10] = (unsigned long)(arg10);                       \
    986       _argvec[11] = (unsigned long)(arg11);                       \
    987       _argvec[12] = (unsigned long)(arg12);                       \
    988       __asm__ volatile(                                           \
    989          "pushl 48(%%eax)\n\t"                                    \
    990          "pushl 44(%%eax)\n\t"                                    \
    991          "pushl 40(%%eax)\n\t"                                    \
    992          "pushl 36(%%eax)\n\t"                                    \
    993          "pushl 32(%%eax)\n\t"                                    \
    994          "pushl 28(%%eax)\n\t"                                    \
    995          "pushl 24(%%eax)\n\t"                                    \
    996          "pushl 20(%%eax)\n\t"                                    \
    997          "pushl 16(%%eax)\n\t"                                    \
    998          "pushl 12(%%eax)\n\t"                                    \
    999          "pushl 8(%%eax)\n\t"                                     \
   1000          "pushl 4(%%eax)\n\t"                                     \
   1001          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
   1002          VALGRIND_CALL_NOREDIR_EAX                                \
   1003          "addl $48, %%esp\n"                                      \
   1004          : /*out*/   "=a" (_res)                                  \
   1005          : /*in*/    "a" (&_argvec[0])                            \
   1006          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1007       );                                                          \
   1008       lval = (__typeof__(lval)) _res;                             \
   1009    } while (0)
   1010 
   1011 #endif /* PLAT_x86_linux */
   1012 
   1013 /* ------------------------ amd64-linux ------------------------ */
   1014 
   1015 #if defined(PLAT_amd64_linux)
   1016 
   1017 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
   1018 
   1019 /* These regs are trashed by the hidden call. */
   1020 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi",       \
   1021                             "rdi", "r8", "r9", "r10", "r11"
   1022 
   1023 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
   1024    long) == 8. */
   1025 
   1026 /* NB 9 Sept 07.  There is a nasty kludge here in all these CALL_FN_
   1027    macros.  In order not to trash the stack redzone, we need to drop
   1028    %rsp by 128 before the hidden call, and restore afterwards.  The
   1029    nastyness is that it is only by luck that the stack still appears
   1030    to be unwindable during the hidden call - since then the behaviour
   1031    of any routine using this macro does not match what the CFI data
   1032    says.  Sigh.
   1033 
   1034    Why is this important?  Imagine that a wrapper has a stack
   1035    allocated local, and passes to the hidden call, a pointer to it.
   1036    Because gcc does not know about the hidden call, it may allocate
   1037    that local in the redzone.  Unfortunately the hidden call may then
   1038    trash it before it comes to use it.  So we must step clear of the
   1039    redzone, for the duration of the hidden call, to make it safe.
   1040 
   1041    Probably the same problem afflicts the other redzone-style ABIs too
   1042    (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
   1043    self describing (none of this CFI nonsense) so at least messing
   1044    with the stack pointer doesn't give a danger of non-unwindable
   1045    stack. */
   1046 
   1047 #define CALL_FN_W_v(lval, orig)                                   \
   1048    do {                                                           \
   1049       volatile OrigFn        _orig = (orig);                      \
   1050       volatile unsigned long _argvec[1];                          \
   1051       volatile unsigned long _res;                                \
   1052       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1053       __asm__ volatile(                                           \
   1054          "subq $128,%%rsp\n\t"                                    \
   1055          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1056          VALGRIND_CALL_NOREDIR_RAX                                \
   1057          "addq $128,%%rsp\n\t"                                    \
   1058          : /*out*/   "=a" (_res)                                  \
   1059          : /*in*/    "a" (&_argvec[0])                            \
   1060          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1061       );                                                          \
   1062       lval = (__typeof__(lval)) _res;                             \
   1063    } while (0)
   1064 
   1065 #define CALL_FN_W_W(lval, orig, arg1)                             \
   1066    do {                                                           \
   1067       volatile OrigFn        _orig = (orig);                      \
   1068       volatile unsigned long _argvec[2];                          \
   1069       volatile unsigned long _res;                                \
   1070       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1071       _argvec[1] = (unsigned long)(arg1);                         \
   1072       __asm__ volatile(                                           \
   1073          "subq $128,%%rsp\n\t"                                    \
   1074          "movq 8(%%rax), %%rdi\n\t"                               \
   1075          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1076          VALGRIND_CALL_NOREDIR_RAX                                \
   1077          "addq $128,%%rsp\n\t"                                    \
   1078          : /*out*/   "=a" (_res)                                  \
   1079          : /*in*/    "a" (&_argvec[0])                            \
   1080          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1081       );                                                          \
   1082       lval = (__typeof__(lval)) _res;                             \
   1083    } while (0)
   1084 
   1085 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
   1086    do {                                                           \
   1087       volatile OrigFn        _orig = (orig);                      \
   1088       volatile unsigned long _argvec[3];                          \
   1089       volatile unsigned long _res;                                \
   1090       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1091       _argvec[1] = (unsigned long)(arg1);                         \
   1092       _argvec[2] = (unsigned long)(arg2);                         \
   1093       __asm__ volatile(                                           \
   1094          "subq $128,%%rsp\n\t"                                    \
   1095          "movq 16(%%rax), %%rsi\n\t"                              \
   1096          "movq 8(%%rax), %%rdi\n\t"                               \
   1097          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1098          VALGRIND_CALL_NOREDIR_RAX                                \
   1099          "addq $128,%%rsp\n\t"                                    \
   1100          : /*out*/   "=a" (_res)                                  \
   1101          : /*in*/    "a" (&_argvec[0])                            \
   1102          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1103       );                                                          \
   1104       lval = (__typeof__(lval)) _res;                             \
   1105    } while (0)
   1106 
   1107 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
   1108    do {                                                           \
   1109       volatile OrigFn        _orig = (orig);                      \
   1110       volatile unsigned long _argvec[4];                          \
   1111       volatile unsigned long _res;                                \
   1112       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1113       _argvec[1] = (unsigned long)(arg1);                         \
   1114       _argvec[2] = (unsigned long)(arg2);                         \
   1115       _argvec[3] = (unsigned long)(arg3);                         \
   1116       __asm__ volatile(                                           \
   1117          "subq $128,%%rsp\n\t"                                    \
   1118          "movq 24(%%rax), %%rdx\n\t"                              \
   1119          "movq 16(%%rax), %%rsi\n\t"                              \
   1120          "movq 8(%%rax), %%rdi\n\t"                               \
   1121          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1122          VALGRIND_CALL_NOREDIR_RAX                                \
   1123          "addq $128,%%rsp\n\t"                                    \
   1124          : /*out*/   "=a" (_res)                                  \
   1125          : /*in*/    "a" (&_argvec[0])                            \
   1126          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1127       );                                                          \
   1128       lval = (__typeof__(lval)) _res;                             \
   1129    } while (0)
   1130 
   1131 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
   1132    do {                                                           \
   1133       volatile OrigFn        _orig = (orig);                      \
   1134       volatile unsigned long _argvec[5];                          \
   1135       volatile unsigned long _res;                                \
   1136       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1137       _argvec[1] = (unsigned long)(arg1);                         \
   1138       _argvec[2] = (unsigned long)(arg2);                         \
   1139       _argvec[3] = (unsigned long)(arg3);                         \
   1140       _argvec[4] = (unsigned long)(arg4);                         \
   1141       __asm__ volatile(                                           \
   1142          "subq $128,%%rsp\n\t"                                    \
   1143          "movq 32(%%rax), %%rcx\n\t"                              \
   1144          "movq 24(%%rax), %%rdx\n\t"                              \
   1145          "movq 16(%%rax), %%rsi\n\t"                              \
   1146          "movq 8(%%rax), %%rdi\n\t"                               \
   1147          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1148          VALGRIND_CALL_NOREDIR_RAX                                \
   1149          "addq $128,%%rsp\n\t"                                    \
   1150          : /*out*/   "=a" (_res)                                  \
   1151          : /*in*/    "a" (&_argvec[0])                            \
   1152          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1153       );                                                          \
   1154       lval = (__typeof__(lval)) _res;                             \
   1155    } while (0)
   1156 
   1157 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
   1158    do {                                                           \
   1159       volatile OrigFn        _orig = (orig);                      \
   1160       volatile unsigned long _argvec[6];                          \
   1161       volatile unsigned long _res;                                \
   1162       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1163       _argvec[1] = (unsigned long)(arg1);                         \
   1164       _argvec[2] = (unsigned long)(arg2);                         \
   1165       _argvec[3] = (unsigned long)(arg3);                         \
   1166       _argvec[4] = (unsigned long)(arg4);                         \
   1167       _argvec[5] = (unsigned long)(arg5);                         \
   1168       __asm__ volatile(                                           \
   1169          "subq $128,%%rsp\n\t"                                    \
   1170          "movq 40(%%rax), %%r8\n\t"                               \
   1171          "movq 32(%%rax), %%rcx\n\t"                              \
   1172          "movq 24(%%rax), %%rdx\n\t"                              \
   1173          "movq 16(%%rax), %%rsi\n\t"                              \
   1174          "movq 8(%%rax), %%rdi\n\t"                               \
   1175          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1176          VALGRIND_CALL_NOREDIR_RAX                                \
   1177          "addq $128,%%rsp\n\t"                                    \
   1178          : /*out*/   "=a" (_res)                                  \
   1179          : /*in*/    "a" (&_argvec[0])                            \
   1180          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1181       );                                                          \
   1182       lval = (__typeof__(lval)) _res;                             \
   1183    } while (0)
   1184 
   1185 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
   1186    do {                                                           \
   1187       volatile OrigFn        _orig = (orig);                      \
   1188       volatile unsigned long _argvec[7];                          \
   1189       volatile unsigned long _res;                                \
   1190       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1191       _argvec[1] = (unsigned long)(arg1);                         \
   1192       _argvec[2] = (unsigned long)(arg2);                         \
   1193       _argvec[3] = (unsigned long)(arg3);                         \
   1194       _argvec[4] = (unsigned long)(arg4);                         \
   1195       _argvec[5] = (unsigned long)(arg5);                         \
   1196       _argvec[6] = (unsigned long)(arg6);                         \
   1197       __asm__ volatile(                                           \
   1198          "subq $128,%%rsp\n\t"                                    \
   1199          "movq 48(%%rax), %%r9\n\t"                               \
   1200          "movq 40(%%rax), %%r8\n\t"                               \
   1201          "movq 32(%%rax), %%rcx\n\t"                              \
   1202          "movq 24(%%rax), %%rdx\n\t"                              \
   1203          "movq 16(%%rax), %%rsi\n\t"                              \
   1204          "movq 8(%%rax), %%rdi\n\t"                               \
   1205          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1206          "addq $128,%%rsp\n\t"                                    \
   1207          VALGRIND_CALL_NOREDIR_RAX                                \
   1208          : /*out*/   "=a" (_res)                                  \
   1209          : /*in*/    "a" (&_argvec[0])                            \
   1210          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1211       );                                                          \
   1212       lval = (__typeof__(lval)) _res;                             \
   1213    } while (0)
   1214 
   1215 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   1216                                  arg7)                            \
   1217    do {                                                           \
   1218       volatile OrigFn        _orig = (orig);                      \
   1219       volatile unsigned long _argvec[8];                          \
   1220       volatile unsigned long _res;                                \
   1221       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1222       _argvec[1] = (unsigned long)(arg1);                         \
   1223       _argvec[2] = (unsigned long)(arg2);                         \
   1224       _argvec[3] = (unsigned long)(arg3);                         \
   1225       _argvec[4] = (unsigned long)(arg4);                         \
   1226       _argvec[5] = (unsigned long)(arg5);                         \
   1227       _argvec[6] = (unsigned long)(arg6);                         \
   1228       _argvec[7] = (unsigned long)(arg7);                         \
   1229       __asm__ volatile(                                           \
   1230          "subq $128,%%rsp\n\t"                                    \
   1231          "pushq 56(%%rax)\n\t"                                    \
   1232          "movq 48(%%rax), %%r9\n\t"                               \
   1233          "movq 40(%%rax), %%r8\n\t"                               \
   1234          "movq 32(%%rax), %%rcx\n\t"                              \
   1235          "movq 24(%%rax), %%rdx\n\t"                              \
   1236          "movq 16(%%rax), %%rsi\n\t"                              \
   1237          "movq 8(%%rax), %%rdi\n\t"                               \
   1238          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1239          VALGRIND_CALL_NOREDIR_RAX                                \
   1240          "addq $8, %%rsp\n"                                       \
   1241          "addq $128,%%rsp\n\t"                                    \
   1242          : /*out*/   "=a" (_res)                                  \
   1243          : /*in*/    "a" (&_argvec[0])                            \
   1244          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1245       );                                                          \
   1246       lval = (__typeof__(lval)) _res;                             \
   1247    } while (0)
   1248 
   1249 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   1250                                  arg7,arg8)                       \
   1251    do {                                                           \
   1252       volatile OrigFn        _orig = (orig);                      \
   1253       volatile unsigned long _argvec[9];                          \
   1254       volatile unsigned long _res;                                \
   1255       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1256       _argvec[1] = (unsigned long)(arg1);                         \
   1257       _argvec[2] = (unsigned long)(arg2);                         \
   1258       _argvec[3] = (unsigned long)(arg3);                         \
   1259       _argvec[4] = (unsigned long)(arg4);                         \
   1260       _argvec[5] = (unsigned long)(arg5);                         \
   1261       _argvec[6] = (unsigned long)(arg6);                         \
   1262       _argvec[7] = (unsigned long)(arg7);                         \
   1263       _argvec[8] = (unsigned long)(arg8);                         \
   1264       __asm__ volatile(                                           \
   1265          "subq $128,%%rsp\n\t"                                    \
   1266          "pushq 64(%%rax)\n\t"                                    \
   1267          "pushq 56(%%rax)\n\t"                                    \
   1268          "movq 48(%%rax), %%r9\n\t"                               \
   1269          "movq 40(%%rax), %%r8\n\t"                               \
   1270          "movq 32(%%rax), %%rcx\n\t"                              \
   1271          "movq 24(%%rax), %%rdx\n\t"                              \
   1272          "movq 16(%%rax), %%rsi\n\t"                              \
   1273          "movq 8(%%rax), %%rdi\n\t"                               \
   1274          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1275          VALGRIND_CALL_NOREDIR_RAX                                \
   1276          "addq $16, %%rsp\n"                                      \
   1277          "addq $128,%%rsp\n\t"                                    \
   1278          : /*out*/   "=a" (_res)                                  \
   1279          : /*in*/    "a" (&_argvec[0])                            \
   1280          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1281       );                                                          \
   1282       lval = (__typeof__(lval)) _res;                             \
   1283    } while (0)
   1284 
   1285 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   1286                                  arg7,arg8,arg9)                  \
   1287    do {                                                           \
   1288       volatile OrigFn        _orig = (orig);                      \
   1289       volatile unsigned long _argvec[10];                         \
   1290       volatile unsigned long _res;                                \
   1291       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1292       _argvec[1] = (unsigned long)(arg1);                         \
   1293       _argvec[2] = (unsigned long)(arg2);                         \
   1294       _argvec[3] = (unsigned long)(arg3);                         \
   1295       _argvec[4] = (unsigned long)(arg4);                         \
   1296       _argvec[5] = (unsigned long)(arg5);                         \
   1297       _argvec[6] = (unsigned long)(arg6);                         \
   1298       _argvec[7] = (unsigned long)(arg7);                         \
   1299       _argvec[8] = (unsigned long)(arg8);                         \
   1300       _argvec[9] = (unsigned long)(arg9);                         \
   1301       __asm__ volatile(                                           \
   1302          "subq $128,%%rsp\n\t"                                    \
   1303          "pushq 72(%%rax)\n\t"                                    \
   1304          "pushq 64(%%rax)\n\t"                                    \
   1305          "pushq 56(%%rax)\n\t"                                    \
   1306          "movq 48(%%rax), %%r9\n\t"                               \
   1307          "movq 40(%%rax), %%r8\n\t"                               \
   1308          "movq 32(%%rax), %%rcx\n\t"                              \
   1309          "movq 24(%%rax), %%rdx\n\t"                              \
   1310          "movq 16(%%rax), %%rsi\n\t"                              \
   1311          "movq 8(%%rax), %%rdi\n\t"                               \
   1312          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1313          VALGRIND_CALL_NOREDIR_RAX                                \
   1314          "addq $24, %%rsp\n"                                      \
   1315          "addq $128,%%rsp\n\t"                                    \
   1316          : /*out*/   "=a" (_res)                                  \
   1317          : /*in*/    "a" (&_argvec[0])                            \
   1318          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1319       );                                                          \
   1320       lval = (__typeof__(lval)) _res;                             \
   1321    } while (0)
   1322 
   1323 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   1324                                   arg7,arg8,arg9,arg10)           \
   1325    do {                                                           \
   1326       volatile OrigFn        _orig = (orig);                      \
   1327       volatile unsigned long _argvec[11];                         \
   1328       volatile unsigned long _res;                                \
   1329       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1330       _argvec[1] = (unsigned long)(arg1);                         \
   1331       _argvec[2] = (unsigned long)(arg2);                         \
   1332       _argvec[3] = (unsigned long)(arg3);                         \
   1333       _argvec[4] = (unsigned long)(arg4);                         \
   1334       _argvec[5] = (unsigned long)(arg5);                         \
   1335       _argvec[6] = (unsigned long)(arg6);                         \
   1336       _argvec[7] = (unsigned long)(arg7);                         \
   1337       _argvec[8] = (unsigned long)(arg8);                         \
   1338       _argvec[9] = (unsigned long)(arg9);                         \
   1339       _argvec[10] = (unsigned long)(arg10);                       \
   1340       __asm__ volatile(                                           \
   1341          "subq $128,%%rsp\n\t"                                    \
   1342          "pushq 80(%%rax)\n\t"                                    \
   1343          "pushq 72(%%rax)\n\t"                                    \
   1344          "pushq 64(%%rax)\n\t"                                    \
   1345          "pushq 56(%%rax)\n\t"                                    \
   1346          "movq 48(%%rax), %%r9\n\t"                               \
   1347          "movq 40(%%rax), %%r8\n\t"                               \
   1348          "movq 32(%%rax), %%rcx\n\t"                              \
   1349          "movq 24(%%rax), %%rdx\n\t"                              \
   1350          "movq 16(%%rax), %%rsi\n\t"                              \
   1351          "movq 8(%%rax), %%rdi\n\t"                               \
   1352          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1353          VALGRIND_CALL_NOREDIR_RAX                                \
   1354          "addq $32, %%rsp\n"                                      \
   1355          "addq $128,%%rsp\n\t"                                    \
   1356          : /*out*/   "=a" (_res)                                  \
   1357          : /*in*/    "a" (&_argvec[0])                            \
   1358          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1359       );                                                          \
   1360       lval = (__typeof__(lval)) _res;                             \
   1361    } while (0)
   1362 
   1363 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   1364                                   arg7,arg8,arg9,arg10,arg11)     \
   1365    do {                                                           \
   1366       volatile OrigFn        _orig = (orig);                      \
   1367       volatile unsigned long _argvec[12];                         \
   1368       volatile unsigned long _res;                                \
   1369       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1370       _argvec[1] = (unsigned long)(arg1);                         \
   1371       _argvec[2] = (unsigned long)(arg2);                         \
   1372       _argvec[3] = (unsigned long)(arg3);                         \
   1373       _argvec[4] = (unsigned long)(arg4);                         \
   1374       _argvec[5] = (unsigned long)(arg5);                         \
   1375       _argvec[6] = (unsigned long)(arg6);                         \
   1376       _argvec[7] = (unsigned long)(arg7);                         \
   1377       _argvec[8] = (unsigned long)(arg8);                         \
   1378       _argvec[9] = (unsigned long)(arg9);                         \
   1379       _argvec[10] = (unsigned long)(arg10);                       \
   1380       _argvec[11] = (unsigned long)(arg11);                       \
   1381       __asm__ volatile(                                           \
   1382          "subq $128,%%rsp\n\t"                                    \
   1383          "pushq 88(%%rax)\n\t"                                    \
   1384          "pushq 80(%%rax)\n\t"                                    \
   1385          "pushq 72(%%rax)\n\t"                                    \
   1386          "pushq 64(%%rax)\n\t"                                    \
   1387          "pushq 56(%%rax)\n\t"                                    \
   1388          "movq 48(%%rax), %%r9\n\t"                               \
   1389          "movq 40(%%rax), %%r8\n\t"                               \
   1390          "movq 32(%%rax), %%rcx\n\t"                              \
   1391          "movq 24(%%rax), %%rdx\n\t"                              \
   1392          "movq 16(%%rax), %%rsi\n\t"                              \
   1393          "movq 8(%%rax), %%rdi\n\t"                               \
   1394          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1395          VALGRIND_CALL_NOREDIR_RAX                                \
   1396          "addq $40, %%rsp\n"                                      \
   1397          "addq $128,%%rsp\n\t"                                    \
   1398          : /*out*/   "=a" (_res)                                  \
   1399          : /*in*/    "a" (&_argvec[0])                            \
   1400          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1401       );                                                          \
   1402       lval = (__typeof__(lval)) _res;                             \
   1403    } while (0)
   1404 
   1405 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   1406                                 arg7,arg8,arg9,arg10,arg11,arg12) \
   1407    do {                                                           \
   1408       volatile OrigFn        _orig = (orig);                      \
   1409       volatile unsigned long _argvec[13];                         \
   1410       volatile unsigned long _res;                                \
   1411       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1412       _argvec[1] = (unsigned long)(arg1);                         \
   1413       _argvec[2] = (unsigned long)(arg2);                         \
   1414       _argvec[3] = (unsigned long)(arg3);                         \
   1415       _argvec[4] = (unsigned long)(arg4);                         \
   1416       _argvec[5] = (unsigned long)(arg5);                         \
   1417       _argvec[6] = (unsigned long)(arg6);                         \
   1418       _argvec[7] = (unsigned long)(arg7);                         \
   1419       _argvec[8] = (unsigned long)(arg8);                         \
   1420       _argvec[9] = (unsigned long)(arg9);                         \
   1421       _argvec[10] = (unsigned long)(arg10);                       \
   1422       _argvec[11] = (unsigned long)(arg11);                       \
   1423       _argvec[12] = (unsigned long)(arg12);                       \
   1424       __asm__ volatile(                                           \
   1425          "subq $128,%%rsp\n\t"                                    \
   1426          "pushq 96(%%rax)\n\t"                                    \
   1427          "pushq 88(%%rax)\n\t"                                    \
   1428          "pushq 80(%%rax)\n\t"                                    \
   1429          "pushq 72(%%rax)\n\t"                                    \
   1430          "pushq 64(%%rax)\n\t"                                    \
   1431          "pushq 56(%%rax)\n\t"                                    \
   1432          "movq 48(%%rax), %%r9\n\t"                               \
   1433          "movq 40(%%rax), %%r8\n\t"                               \
   1434          "movq 32(%%rax), %%rcx\n\t"                              \
   1435          "movq 24(%%rax), %%rdx\n\t"                              \
   1436          "movq 16(%%rax), %%rsi\n\t"                              \
   1437          "movq 8(%%rax), %%rdi\n\t"                               \
   1438          "movq (%%rax), %%rax\n\t"  /* target->%rax */            \
   1439          VALGRIND_CALL_NOREDIR_RAX                                \
   1440          "addq $48, %%rsp\n"                                      \
   1441          "addq $128,%%rsp\n\t"                                    \
   1442          : /*out*/   "=a" (_res)                                  \
   1443          : /*in*/    "a" (&_argvec[0])                            \
   1444          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1445       );                                                          \
   1446       lval = (__typeof__(lval)) _res;                             \
   1447    } while (0)
   1448 
   1449 #endif /* PLAT_amd64_linux */
   1450 
   1451 /* ------------------------ ppc32-linux ------------------------ */
   1452 
   1453 #if defined(PLAT_ppc32_linux)
   1454 
   1455 /* This is useful for finding out about the on-stack stuff:
   1456 
   1457    extern int f9  ( int,int,int,int,int,int,int,int,int );
   1458    extern int f10 ( int,int,int,int,int,int,int,int,int,int );
   1459    extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
   1460    extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
   1461 
   1462    int g9 ( void ) {
   1463       return f9(11,22,33,44,55,66,77,88,99);
   1464    }
   1465    int g10 ( void ) {
   1466       return f10(11,22,33,44,55,66,77,88,99,110);
   1467    }
   1468    int g11 ( void ) {
   1469       return f11(11,22,33,44,55,66,77,88,99,110,121);
   1470    }
   1471    int g12 ( void ) {
   1472       return f12(11,22,33,44,55,66,77,88,99,110,121,132);
   1473    }
   1474 */
   1475 
   1476 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
   1477 
   1478 /* These regs are trashed by the hidden call. */
   1479 #define __CALLER_SAVED_REGS                                       \
   1480    "lr", "ctr", "xer",                                            \
   1481    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
   1482    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
   1483    "r11", "r12", "r13"
   1484 
   1485 /* These CALL_FN_ macros assume that on ppc32-linux,
   1486    sizeof(unsigned long) == 4. */
   1487 
   1488 #define CALL_FN_W_v(lval, orig)                                   \
   1489    do {                                                           \
   1490       volatile OrigFn        _orig = (orig);                      \
   1491       volatile unsigned long _argvec[1];                          \
   1492       volatile unsigned long _res;                                \
   1493       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1494       __asm__ volatile(                                           \
   1495          "mr 11,%1\n\t"                                           \
   1496          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1497          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1498          "mr %0,3"                                                \
   1499          : /*out*/   "=r" (_res)                                  \
   1500          : /*in*/    "r" (&_argvec[0])                            \
   1501          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1502       );                                                          \
   1503       lval = (__typeof__(lval)) _res;                             \
   1504    } while (0)
   1505 
   1506 #define CALL_FN_W_W(lval, orig, arg1)                             \
   1507    do {                                                           \
   1508       volatile OrigFn        _orig = (orig);                      \
   1509       volatile unsigned long _argvec[2];                          \
   1510       volatile unsigned long _res;                                \
   1511       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1512       _argvec[1] = (unsigned long)arg1;                           \
   1513       __asm__ volatile(                                           \
   1514          "mr 11,%1\n\t"                                           \
   1515          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1516          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1517          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1518          "mr %0,3"                                                \
   1519          : /*out*/   "=r" (_res)                                  \
   1520          : /*in*/    "r" (&_argvec[0])                            \
   1521          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1522       );                                                          \
   1523       lval = (__typeof__(lval)) _res;                             \
   1524    } while (0)
   1525 
   1526 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
   1527    do {                                                           \
   1528       volatile OrigFn        _orig = (orig);                      \
   1529       volatile unsigned long _argvec[3];                          \
   1530       volatile unsigned long _res;                                \
   1531       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1532       _argvec[1] = (unsigned long)arg1;                           \
   1533       _argvec[2] = (unsigned long)arg2;                           \
   1534       __asm__ volatile(                                           \
   1535          "mr 11,%1\n\t"                                           \
   1536          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1537          "lwz 4,8(11)\n\t"                                        \
   1538          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1539          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1540          "mr %0,3"                                                \
   1541          : /*out*/   "=r" (_res)                                  \
   1542          : /*in*/    "r" (&_argvec[0])                            \
   1543          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1544       );                                                          \
   1545       lval = (__typeof__(lval)) _res;                             \
   1546    } while (0)
   1547 
   1548 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
   1549    do {                                                           \
   1550       volatile OrigFn        _orig = (orig);                      \
   1551       volatile unsigned long _argvec[4];                          \
   1552       volatile unsigned long _res;                                \
   1553       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1554       _argvec[1] = (unsigned long)arg1;                           \
   1555       _argvec[2] = (unsigned long)arg2;                           \
   1556       _argvec[3] = (unsigned long)arg3;                           \
   1557       __asm__ volatile(                                           \
   1558          "mr 11,%1\n\t"                                           \
   1559          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1560          "lwz 4,8(11)\n\t"                                        \
   1561          "lwz 5,12(11)\n\t"                                       \
   1562          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1563          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1564          "mr %0,3"                                                \
   1565          : /*out*/   "=r" (_res)                                  \
   1566          : /*in*/    "r" (&_argvec[0])                            \
   1567          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1568       );                                                          \
   1569       lval = (__typeof__(lval)) _res;                             \
   1570    } while (0)
   1571 
   1572 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
   1573    do {                                                           \
   1574       volatile OrigFn        _orig = (orig);                      \
   1575       volatile unsigned long _argvec[5];                          \
   1576       volatile unsigned long _res;                                \
   1577       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1578       _argvec[1] = (unsigned long)arg1;                           \
   1579       _argvec[2] = (unsigned long)arg2;                           \
   1580       _argvec[3] = (unsigned long)arg3;                           \
   1581       _argvec[4] = (unsigned long)arg4;                           \
   1582       __asm__ volatile(                                           \
   1583          "mr 11,%1\n\t"                                           \
   1584          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1585          "lwz 4,8(11)\n\t"                                        \
   1586          "lwz 5,12(11)\n\t"                                       \
   1587          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1588          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1589          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1590          "mr %0,3"                                                \
   1591          : /*out*/   "=r" (_res)                                  \
   1592          : /*in*/    "r" (&_argvec[0])                            \
   1593          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1594       );                                                          \
   1595       lval = (__typeof__(lval)) _res;                             \
   1596    } while (0)
   1597 
   1598 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
   1599    do {                                                           \
   1600       volatile OrigFn        _orig = (orig);                      \
   1601       volatile unsigned long _argvec[6];                          \
   1602       volatile unsigned long _res;                                \
   1603       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1604       _argvec[1] = (unsigned long)arg1;                           \
   1605       _argvec[2] = (unsigned long)arg2;                           \
   1606       _argvec[3] = (unsigned long)arg3;                           \
   1607       _argvec[4] = (unsigned long)arg4;                           \
   1608       _argvec[5] = (unsigned long)arg5;                           \
   1609       __asm__ volatile(                                           \
   1610          "mr 11,%1\n\t"                                           \
   1611          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1612          "lwz 4,8(11)\n\t"                                        \
   1613          "lwz 5,12(11)\n\t"                                       \
   1614          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1615          "lwz 7,20(11)\n\t"                                       \
   1616          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1617          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1618          "mr %0,3"                                                \
   1619          : /*out*/   "=r" (_res)                                  \
   1620          : /*in*/    "r" (&_argvec[0])                            \
   1621          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1622       );                                                          \
   1623       lval = (__typeof__(lval)) _res;                             \
   1624    } while (0)
   1625 
   1626 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
   1627    do {                                                           \
   1628       volatile OrigFn        _orig = (orig);                      \
   1629       volatile unsigned long _argvec[7];                          \
   1630       volatile unsigned long _res;                                \
   1631       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1632       _argvec[1] = (unsigned long)arg1;                           \
   1633       _argvec[2] = (unsigned long)arg2;                           \
   1634       _argvec[3] = (unsigned long)arg3;                           \
   1635       _argvec[4] = (unsigned long)arg4;                           \
   1636       _argvec[5] = (unsigned long)arg5;                           \
   1637       _argvec[6] = (unsigned long)arg6;                           \
   1638       __asm__ volatile(                                           \
   1639          "mr 11,%1\n\t"                                           \
   1640          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1641          "lwz 4,8(11)\n\t"                                        \
   1642          "lwz 5,12(11)\n\t"                                       \
   1643          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1644          "lwz 7,20(11)\n\t"                                       \
   1645          "lwz 8,24(11)\n\t"                                       \
   1646          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1647          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1648          "mr %0,3"                                                \
   1649          : /*out*/   "=r" (_res)                                  \
   1650          : /*in*/    "r" (&_argvec[0])                            \
   1651          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1652       );                                                          \
   1653       lval = (__typeof__(lval)) _res;                             \
   1654    } while (0)
   1655 
   1656 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   1657                                  arg7)                            \
   1658    do {                                                           \
   1659       volatile OrigFn        _orig = (orig);                      \
   1660       volatile unsigned long _argvec[8];                          \
   1661       volatile unsigned long _res;                                \
   1662       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1663       _argvec[1] = (unsigned long)arg1;                           \
   1664       _argvec[2] = (unsigned long)arg2;                           \
   1665       _argvec[3] = (unsigned long)arg3;                           \
   1666       _argvec[4] = (unsigned long)arg4;                           \
   1667       _argvec[5] = (unsigned long)arg5;                           \
   1668       _argvec[6] = (unsigned long)arg6;                           \
   1669       _argvec[7] = (unsigned long)arg7;                           \
   1670       __asm__ volatile(                                           \
   1671          "mr 11,%1\n\t"                                           \
   1672          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1673          "lwz 4,8(11)\n\t"                                        \
   1674          "lwz 5,12(11)\n\t"                                       \
   1675          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1676          "lwz 7,20(11)\n\t"                                       \
   1677          "lwz 8,24(11)\n\t"                                       \
   1678          "lwz 9,28(11)\n\t"                                       \
   1679          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1680          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1681          "mr %0,3"                                                \
   1682          : /*out*/   "=r" (_res)                                  \
   1683          : /*in*/    "r" (&_argvec[0])                            \
   1684          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1685       );                                                          \
   1686       lval = (__typeof__(lval)) _res;                             \
   1687    } while (0)
   1688 
   1689 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   1690                                  arg7,arg8)                       \
   1691    do {                                                           \
   1692       volatile OrigFn        _orig = (orig);                      \
   1693       volatile unsigned long _argvec[9];                          \
   1694       volatile unsigned long _res;                                \
   1695       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1696       _argvec[1] = (unsigned long)arg1;                           \
   1697       _argvec[2] = (unsigned long)arg2;                           \
   1698       _argvec[3] = (unsigned long)arg3;                           \
   1699       _argvec[4] = (unsigned long)arg4;                           \
   1700       _argvec[5] = (unsigned long)arg5;                           \
   1701       _argvec[6] = (unsigned long)arg6;                           \
   1702       _argvec[7] = (unsigned long)arg7;                           \
   1703       _argvec[8] = (unsigned long)arg8;                           \
   1704       __asm__ volatile(                                           \
   1705          "mr 11,%1\n\t"                                           \
   1706          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1707          "lwz 4,8(11)\n\t"                                        \
   1708          "lwz 5,12(11)\n\t"                                       \
   1709          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1710          "lwz 7,20(11)\n\t"                                       \
   1711          "lwz 8,24(11)\n\t"                                       \
   1712          "lwz 9,28(11)\n\t"                                       \
   1713          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
   1714          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1715          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1716          "mr %0,3"                                                \
   1717          : /*out*/   "=r" (_res)                                  \
   1718          : /*in*/    "r" (&_argvec[0])                            \
   1719          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1720       );                                                          \
   1721       lval = (__typeof__(lval)) _res;                             \
   1722    } while (0)
   1723 
   1724 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   1725                                  arg7,arg8,arg9)                  \
   1726    do {                                                           \
   1727       volatile OrigFn        _orig = (orig);                      \
   1728       volatile unsigned long _argvec[10];                         \
   1729       volatile unsigned long _res;                                \
   1730       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1731       _argvec[1] = (unsigned long)arg1;                           \
   1732       _argvec[2] = (unsigned long)arg2;                           \
   1733       _argvec[3] = (unsigned long)arg3;                           \
   1734       _argvec[4] = (unsigned long)arg4;                           \
   1735       _argvec[5] = (unsigned long)arg5;                           \
   1736       _argvec[6] = (unsigned long)arg6;                           \
   1737       _argvec[7] = (unsigned long)arg7;                           \
   1738       _argvec[8] = (unsigned long)arg8;                           \
   1739       _argvec[9] = (unsigned long)arg9;                           \
   1740       __asm__ volatile(                                           \
   1741          "mr 11,%1\n\t"                                           \
   1742          "addi 1,1,-16\n\t"                                       \
   1743          /* arg9 */                                               \
   1744          "lwz 3,36(11)\n\t"                                       \
   1745          "stw 3,8(1)\n\t"                                         \
   1746          /* args1-8 */                                            \
   1747          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1748          "lwz 4,8(11)\n\t"                                        \
   1749          "lwz 5,12(11)\n\t"                                       \
   1750          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1751          "lwz 7,20(11)\n\t"                                       \
   1752          "lwz 8,24(11)\n\t"                                       \
   1753          "lwz 9,28(11)\n\t"                                       \
   1754          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
   1755          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1756          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1757          "addi 1,1,16\n\t"                                        \
   1758          "mr %0,3"                                                \
   1759          : /*out*/   "=r" (_res)                                  \
   1760          : /*in*/    "r" (&_argvec[0])                            \
   1761          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1762       );                                                          \
   1763       lval = (__typeof__(lval)) _res;                             \
   1764    } while (0)
   1765 
   1766 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   1767                                   arg7,arg8,arg9,arg10)           \
   1768    do {                                                           \
   1769       volatile OrigFn        _orig = (orig);                      \
   1770       volatile unsigned long _argvec[11];                         \
   1771       volatile unsigned long _res;                                \
   1772       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1773       _argvec[1] = (unsigned long)arg1;                           \
   1774       _argvec[2] = (unsigned long)arg2;                           \
   1775       _argvec[3] = (unsigned long)arg3;                           \
   1776       _argvec[4] = (unsigned long)arg4;                           \
   1777       _argvec[5] = (unsigned long)arg5;                           \
   1778       _argvec[6] = (unsigned long)arg6;                           \
   1779       _argvec[7] = (unsigned long)arg7;                           \
   1780       _argvec[8] = (unsigned long)arg8;                           \
   1781       _argvec[9] = (unsigned long)arg9;                           \
   1782       _argvec[10] = (unsigned long)arg10;                         \
   1783       __asm__ volatile(                                           \
   1784          "mr 11,%1\n\t"                                           \
   1785          "addi 1,1,-16\n\t"                                       \
   1786          /* arg10 */                                              \
   1787          "lwz 3,40(11)\n\t"                                       \
   1788          "stw 3,12(1)\n\t"                                        \
   1789          /* arg9 */                                               \
   1790          "lwz 3,36(11)\n\t"                                       \
   1791          "stw 3,8(1)\n\t"                                         \
   1792          /* args1-8 */                                            \
   1793          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1794          "lwz 4,8(11)\n\t"                                        \
   1795          "lwz 5,12(11)\n\t"                                       \
   1796          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1797          "lwz 7,20(11)\n\t"                                       \
   1798          "lwz 8,24(11)\n\t"                                       \
   1799          "lwz 9,28(11)\n\t"                                       \
   1800          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
   1801          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1802          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1803          "addi 1,1,16\n\t"                                        \
   1804          "mr %0,3"                                                \
   1805          : /*out*/   "=r" (_res)                                  \
   1806          : /*in*/    "r" (&_argvec[0])                            \
   1807          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1808       );                                                          \
   1809       lval = (__typeof__(lval)) _res;                             \
   1810    } while (0)
   1811 
   1812 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   1813                                   arg7,arg8,arg9,arg10,arg11)     \
   1814    do {                                                           \
   1815       volatile OrigFn        _orig = (orig);                      \
   1816       volatile unsigned long _argvec[12];                         \
   1817       volatile unsigned long _res;                                \
   1818       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1819       _argvec[1] = (unsigned long)arg1;                           \
   1820       _argvec[2] = (unsigned long)arg2;                           \
   1821       _argvec[3] = (unsigned long)arg3;                           \
   1822       _argvec[4] = (unsigned long)arg4;                           \
   1823       _argvec[5] = (unsigned long)arg5;                           \
   1824       _argvec[6] = (unsigned long)arg6;                           \
   1825       _argvec[7] = (unsigned long)arg7;                           \
   1826       _argvec[8] = (unsigned long)arg8;                           \
   1827       _argvec[9] = (unsigned long)arg9;                           \
   1828       _argvec[10] = (unsigned long)arg10;                         \
   1829       _argvec[11] = (unsigned long)arg11;                         \
   1830       __asm__ volatile(                                           \
   1831          "mr 11,%1\n\t"                                           \
   1832          "addi 1,1,-32\n\t"                                       \
   1833          /* arg11 */                                              \
   1834          "lwz 3,44(11)\n\t"                                       \
   1835          "stw 3,16(1)\n\t"                                        \
   1836          /* arg10 */                                              \
   1837          "lwz 3,40(11)\n\t"                                       \
   1838          "stw 3,12(1)\n\t"                                        \
   1839          /* arg9 */                                               \
   1840          "lwz 3,36(11)\n\t"                                       \
   1841          "stw 3,8(1)\n\t"                                         \
   1842          /* args1-8 */                                            \
   1843          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1844          "lwz 4,8(11)\n\t"                                        \
   1845          "lwz 5,12(11)\n\t"                                       \
   1846          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1847          "lwz 7,20(11)\n\t"                                       \
   1848          "lwz 8,24(11)\n\t"                                       \
   1849          "lwz 9,28(11)\n\t"                                       \
   1850          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
   1851          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1852          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1853          "addi 1,1,32\n\t"                                        \
   1854          "mr %0,3"                                                \
   1855          : /*out*/   "=r" (_res)                                  \
   1856          : /*in*/    "r" (&_argvec[0])                            \
   1857          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1858       );                                                          \
   1859       lval = (__typeof__(lval)) _res;                             \
   1860    } while (0)
   1861 
   1862 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   1863                                 arg7,arg8,arg9,arg10,arg11,arg12) \
   1864    do {                                                           \
   1865       volatile OrigFn        _orig = (orig);                      \
   1866       volatile unsigned long _argvec[13];                         \
   1867       volatile unsigned long _res;                                \
   1868       _argvec[0] = (unsigned long)_orig.nraddr;                   \
   1869       _argvec[1] = (unsigned long)arg1;                           \
   1870       _argvec[2] = (unsigned long)arg2;                           \
   1871       _argvec[3] = (unsigned long)arg3;                           \
   1872       _argvec[4] = (unsigned long)arg4;                           \
   1873       _argvec[5] = (unsigned long)arg5;                           \
   1874       _argvec[6] = (unsigned long)arg6;                           \
   1875       _argvec[7] = (unsigned long)arg7;                           \
   1876       _argvec[8] = (unsigned long)arg8;                           \
   1877       _argvec[9] = (unsigned long)arg9;                           \
   1878       _argvec[10] = (unsigned long)arg10;                         \
   1879       _argvec[11] = (unsigned long)arg11;                         \
   1880       _argvec[12] = (unsigned long)arg12;                         \
   1881       __asm__ volatile(                                           \
   1882          "mr 11,%1\n\t"                                           \
   1883          "addi 1,1,-32\n\t"                                       \
   1884          /* arg12 */                                              \
   1885          "lwz 3,48(11)\n\t"                                       \
   1886          "stw 3,20(1)\n\t"                                        \
   1887          /* arg11 */                                              \
   1888          "lwz 3,44(11)\n\t"                                       \
   1889          "stw 3,16(1)\n\t"                                        \
   1890          /* arg10 */                                              \
   1891          "lwz 3,40(11)\n\t"                                       \
   1892          "stw 3,12(1)\n\t"                                        \
   1893          /* arg9 */                                               \
   1894          "lwz 3,36(11)\n\t"                                       \
   1895          "stw 3,8(1)\n\t"                                         \
   1896          /* args1-8 */                                            \
   1897          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
   1898          "lwz 4,8(11)\n\t"                                        \
   1899          "lwz 5,12(11)\n\t"                                       \
   1900          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
   1901          "lwz 7,20(11)\n\t"                                       \
   1902          "lwz 8,24(11)\n\t"                                       \
   1903          "lwz 9,28(11)\n\t"                                       \
   1904          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
   1905          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
   1906          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1907          "addi 1,1,32\n\t"                                        \
   1908          "mr %0,3"                                                \
   1909          : /*out*/   "=r" (_res)                                  \
   1910          : /*in*/    "r" (&_argvec[0])                            \
   1911          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1912       );                                                          \
   1913       lval = (__typeof__(lval)) _res;                             \
   1914    } while (0)
   1915 
   1916 #endif /* PLAT_ppc32_linux */
   1917 
   1918 /* ------------------------ ppc64-linux ------------------------ */
   1919 
   1920 #if defined(PLAT_ppc64_linux)
   1921 
   1922 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
   1923 
   1924 /* These regs are trashed by the hidden call. */
   1925 #define __CALLER_SAVED_REGS                                       \
   1926    "lr", "ctr", "xer",                                            \
   1927    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
   1928    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
   1929    "r11", "r12", "r13"
   1930 
   1931 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
   1932    long) == 8. */
   1933 
   1934 #define CALL_FN_W_v(lval, orig)                                   \
   1935    do {                                                           \
   1936       volatile OrigFn        _orig = (orig);                      \
   1937       volatile unsigned long _argvec[3+0];                        \
   1938       volatile unsigned long _res;                                \
   1939       /* _argvec[0] holds current r2 across the call */           \
   1940       _argvec[1] = (unsigned long)_orig.r2;                       \
   1941       _argvec[2] = (unsigned long)_orig.nraddr;                   \
   1942       __asm__ volatile(                                           \
   1943          "mr 11,%1\n\t"                                           \
   1944          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   1945          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   1946          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   1947          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1948          "mr 11,%1\n\t"                                           \
   1949          "mr %0,3\n\t"                                            \
   1950          "ld 2,-16(11)" /* restore tocptr */                      \
   1951          : /*out*/   "=r" (_res)                                  \
   1952          : /*in*/    "r" (&_argvec[2])                            \
   1953          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1954       );                                                          \
   1955       lval = (__typeof__(lval)) _res;                             \
   1956    } while (0)
   1957 
   1958 #define CALL_FN_W_W(lval, orig, arg1)                             \
   1959    do {                                                           \
   1960       volatile OrigFn        _orig = (orig);                      \
   1961       volatile unsigned long _argvec[3+1];                        \
   1962       volatile unsigned long _res;                                \
   1963       /* _argvec[0] holds current r2 across the call */           \
   1964       _argvec[1]   = (unsigned long)_orig.r2;                     \
   1965       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   1966       _argvec[2+1] = (unsigned long)arg1;                         \
   1967       __asm__ volatile(                                           \
   1968          "mr 11,%1\n\t"                                           \
   1969          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   1970          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   1971          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   1972          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   1973          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   1974          "mr 11,%1\n\t"                                           \
   1975          "mr %0,3\n\t"                                            \
   1976          "ld 2,-16(11)" /* restore tocptr */                      \
   1977          : /*out*/   "=r" (_res)                                  \
   1978          : /*in*/    "r" (&_argvec[2])                            \
   1979          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   1980       );                                                          \
   1981       lval = (__typeof__(lval)) _res;                             \
   1982    } while (0)
   1983 
   1984 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
   1985    do {                                                           \
   1986       volatile OrigFn        _orig = (orig);                      \
   1987       volatile unsigned long _argvec[3+2];                        \
   1988       volatile unsigned long _res;                                \
   1989       /* _argvec[0] holds current r2 across the call */           \
   1990       _argvec[1]   = (unsigned long)_orig.r2;                     \
   1991       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   1992       _argvec[2+1] = (unsigned long)arg1;                         \
   1993       _argvec[2+2] = (unsigned long)arg2;                         \
   1994       __asm__ volatile(                                           \
   1995          "mr 11,%1\n\t"                                           \
   1996          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   1997          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   1998          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   1999          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2000          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2001          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2002          "mr 11,%1\n\t"                                           \
   2003          "mr %0,3\n\t"                                            \
   2004          "ld 2,-16(11)" /* restore tocptr */                      \
   2005          : /*out*/   "=r" (_res)                                  \
   2006          : /*in*/    "r" (&_argvec[2])                            \
   2007          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2008       );                                                          \
   2009       lval = (__typeof__(lval)) _res;                             \
   2010    } while (0)
   2011 
   2012 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
   2013    do {                                                           \
   2014       volatile OrigFn        _orig = (orig);                      \
   2015       volatile unsigned long _argvec[3+3];                        \
   2016       volatile unsigned long _res;                                \
   2017       /* _argvec[0] holds current r2 across the call */           \
   2018       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2019       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2020       _argvec[2+1] = (unsigned long)arg1;                         \
   2021       _argvec[2+2] = (unsigned long)arg2;                         \
   2022       _argvec[2+3] = (unsigned long)arg3;                         \
   2023       __asm__ volatile(                                           \
   2024          "mr 11,%1\n\t"                                           \
   2025          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2026          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2027          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2028          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2029          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2030          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2031          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2032          "mr 11,%1\n\t"                                           \
   2033          "mr %0,3\n\t"                                            \
   2034          "ld 2,-16(11)" /* restore tocptr */                      \
   2035          : /*out*/   "=r" (_res)                                  \
   2036          : /*in*/    "r" (&_argvec[2])                            \
   2037          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2038       );                                                          \
   2039       lval = (__typeof__(lval)) _res;                             \
   2040    } while (0)
   2041 
   2042 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
   2043    do {                                                           \
   2044       volatile OrigFn        _orig = (orig);                      \
   2045       volatile unsigned long _argvec[3+4];                        \
   2046       volatile unsigned long _res;                                \
   2047       /* _argvec[0] holds current r2 across the call */           \
   2048       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2049       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2050       _argvec[2+1] = (unsigned long)arg1;                         \
   2051       _argvec[2+2] = (unsigned long)arg2;                         \
   2052       _argvec[2+3] = (unsigned long)arg3;                         \
   2053       _argvec[2+4] = (unsigned long)arg4;                         \
   2054       __asm__ volatile(                                           \
   2055          "mr 11,%1\n\t"                                           \
   2056          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2057          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2058          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2059          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2060          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2061          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2062          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2063          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2064          "mr 11,%1\n\t"                                           \
   2065          "mr %0,3\n\t"                                            \
   2066          "ld 2,-16(11)" /* restore tocptr */                      \
   2067          : /*out*/   "=r" (_res)                                  \
   2068          : /*in*/    "r" (&_argvec[2])                            \
   2069          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2070       );                                                          \
   2071       lval = (__typeof__(lval)) _res;                             \
   2072    } while (0)
   2073 
   2074 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
   2075    do {                                                           \
   2076       volatile OrigFn        _orig = (orig);                      \
   2077       volatile unsigned long _argvec[3+5];                        \
   2078       volatile unsigned long _res;                                \
   2079       /* _argvec[0] holds current r2 across the call */           \
   2080       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2081       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2082       _argvec[2+1] = (unsigned long)arg1;                         \
   2083       _argvec[2+2] = (unsigned long)arg2;                         \
   2084       _argvec[2+3] = (unsigned long)arg3;                         \
   2085       _argvec[2+4] = (unsigned long)arg4;                         \
   2086       _argvec[2+5] = (unsigned long)arg5;                         \
   2087       __asm__ volatile(                                           \
   2088          "mr 11,%1\n\t"                                           \
   2089          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2090          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2091          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2092          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2093          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2094          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2095          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2096          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2097          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2098          "mr 11,%1\n\t"                                           \
   2099          "mr %0,3\n\t"                                            \
   2100          "ld 2,-16(11)" /* restore tocptr */                      \
   2101          : /*out*/   "=r" (_res)                                  \
   2102          : /*in*/    "r" (&_argvec[2])                            \
   2103          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2104       );                                                          \
   2105       lval = (__typeof__(lval)) _res;                             \
   2106    } while (0)
   2107 
   2108 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
   2109    do {                                                           \
   2110       volatile OrigFn        _orig = (orig);                      \
   2111       volatile unsigned long _argvec[3+6];                        \
   2112       volatile unsigned long _res;                                \
   2113       /* _argvec[0] holds current r2 across the call */           \
   2114       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2115       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2116       _argvec[2+1] = (unsigned long)arg1;                         \
   2117       _argvec[2+2] = (unsigned long)arg2;                         \
   2118       _argvec[2+3] = (unsigned long)arg3;                         \
   2119       _argvec[2+4] = (unsigned long)arg4;                         \
   2120       _argvec[2+5] = (unsigned long)arg5;                         \
   2121       _argvec[2+6] = (unsigned long)arg6;                         \
   2122       __asm__ volatile(                                           \
   2123          "mr 11,%1\n\t"                                           \
   2124          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2125          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2126          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2127          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2128          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2129          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2130          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2131          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   2132          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2133          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2134          "mr 11,%1\n\t"                                           \
   2135          "mr %0,3\n\t"                                            \
   2136          "ld 2,-16(11)" /* restore tocptr */                      \
   2137          : /*out*/   "=r" (_res)                                  \
   2138          : /*in*/    "r" (&_argvec[2])                            \
   2139          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2140       );                                                          \
   2141       lval = (__typeof__(lval)) _res;                             \
   2142    } while (0)
   2143 
   2144 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   2145                                  arg7)                            \
   2146    do {                                                           \
   2147       volatile OrigFn        _orig = (orig);                      \
   2148       volatile unsigned long _argvec[3+7];                        \
   2149       volatile unsigned long _res;                                \
   2150       /* _argvec[0] holds current r2 across the call */           \
   2151       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2152       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2153       _argvec[2+1] = (unsigned long)arg1;                         \
   2154       _argvec[2+2] = (unsigned long)arg2;                         \
   2155       _argvec[2+3] = (unsigned long)arg3;                         \
   2156       _argvec[2+4] = (unsigned long)arg4;                         \
   2157       _argvec[2+5] = (unsigned long)arg5;                         \
   2158       _argvec[2+6] = (unsigned long)arg6;                         \
   2159       _argvec[2+7] = (unsigned long)arg7;                         \
   2160       __asm__ volatile(                                           \
   2161          "mr 11,%1\n\t"                                           \
   2162          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2163          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2164          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2165          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2166          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2167          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2168          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2169          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   2170          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   2171          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2172          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2173          "mr 11,%1\n\t"                                           \
   2174          "mr %0,3\n\t"                                            \
   2175          "ld 2,-16(11)" /* restore tocptr */                      \
   2176          : /*out*/   "=r" (_res)                                  \
   2177          : /*in*/    "r" (&_argvec[2])                            \
   2178          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2179       );                                                          \
   2180       lval = (__typeof__(lval)) _res;                             \
   2181    } while (0)
   2182 
   2183 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   2184                                  arg7,arg8)                       \
   2185    do {                                                           \
   2186       volatile OrigFn        _orig = (orig);                      \
   2187       volatile unsigned long _argvec[3+8];                        \
   2188       volatile unsigned long _res;                                \
   2189       /* _argvec[0] holds current r2 across the call */           \
   2190       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2191       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2192       _argvec[2+1] = (unsigned long)arg1;                         \
   2193       _argvec[2+2] = (unsigned long)arg2;                         \
   2194       _argvec[2+3] = (unsigned long)arg3;                         \
   2195       _argvec[2+4] = (unsigned long)arg4;                         \
   2196       _argvec[2+5] = (unsigned long)arg5;                         \
   2197       _argvec[2+6] = (unsigned long)arg6;                         \
   2198       _argvec[2+7] = (unsigned long)arg7;                         \
   2199       _argvec[2+8] = (unsigned long)arg8;                         \
   2200       __asm__ volatile(                                           \
   2201          "mr 11,%1\n\t"                                           \
   2202          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2203          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2204          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2205          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2206          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2207          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2208          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2209          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   2210          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   2211          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   2212          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2213          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2214          "mr 11,%1\n\t"                                           \
   2215          "mr %0,3\n\t"                                            \
   2216          "ld 2,-16(11)" /* restore tocptr */                      \
   2217          : /*out*/   "=r" (_res)                                  \
   2218          : /*in*/    "r" (&_argvec[2])                            \
   2219          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2220       );                                                          \
   2221       lval = (__typeof__(lval)) _res;                             \
   2222    } while (0)
   2223 
   2224 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   2225                                  arg7,arg8,arg9)                  \
   2226    do {                                                           \
   2227       volatile OrigFn        _orig = (orig);                      \
   2228       volatile unsigned long _argvec[3+9];                        \
   2229       volatile unsigned long _res;                                \
   2230       /* _argvec[0] holds current r2 across the call */           \
   2231       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2232       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2233       _argvec[2+1] = (unsigned long)arg1;                         \
   2234       _argvec[2+2] = (unsigned long)arg2;                         \
   2235       _argvec[2+3] = (unsigned long)arg3;                         \
   2236       _argvec[2+4] = (unsigned long)arg4;                         \
   2237       _argvec[2+5] = (unsigned long)arg5;                         \
   2238       _argvec[2+6] = (unsigned long)arg6;                         \
   2239       _argvec[2+7] = (unsigned long)arg7;                         \
   2240       _argvec[2+8] = (unsigned long)arg8;                         \
   2241       _argvec[2+9] = (unsigned long)arg9;                         \
   2242       __asm__ volatile(                                           \
   2243          "mr 11,%1\n\t"                                           \
   2244          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2245          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2246          "addi 1,1,-128\n\t"  /* expand stack frame */            \
   2247          /* arg9 */                                               \
   2248          "ld  3,72(11)\n\t"                                       \
   2249          "std 3,112(1)\n\t"                                       \
   2250          /* args1-8 */                                            \
   2251          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2252          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2253          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2254          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2255          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2256          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   2257          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   2258          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   2259          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2260          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2261          "mr 11,%1\n\t"                                           \
   2262          "mr %0,3\n\t"                                            \
   2263          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
   2264          "addi 1,1,128"     /* restore frame */                   \
   2265          : /*out*/   "=r" (_res)                                  \
   2266          : /*in*/    "r" (&_argvec[2])                            \
   2267          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2268       );                                                          \
   2269       lval = (__typeof__(lval)) _res;                             \
   2270    } while (0)
   2271 
   2272 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   2273                                   arg7,arg8,arg9,arg10)           \
   2274    do {                                                           \
   2275       volatile OrigFn        _orig = (orig);                      \
   2276       volatile unsigned long _argvec[3+10];                       \
   2277       volatile unsigned long _res;                                \
   2278       /* _argvec[0] holds current r2 across the call */           \
   2279       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2280       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2281       _argvec[2+1] = (unsigned long)arg1;                         \
   2282       _argvec[2+2] = (unsigned long)arg2;                         \
   2283       _argvec[2+3] = (unsigned long)arg3;                         \
   2284       _argvec[2+4] = (unsigned long)arg4;                         \
   2285       _argvec[2+5] = (unsigned long)arg5;                         \
   2286       _argvec[2+6] = (unsigned long)arg6;                         \
   2287       _argvec[2+7] = (unsigned long)arg7;                         \
   2288       _argvec[2+8] = (unsigned long)arg8;                         \
   2289       _argvec[2+9] = (unsigned long)arg9;                         \
   2290       _argvec[2+10] = (unsigned long)arg10;                       \
   2291       __asm__ volatile(                                           \
   2292          "mr 11,%1\n\t"                                           \
   2293          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2294          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2295          "addi 1,1,-128\n\t"  /* expand stack frame */            \
   2296          /* arg10 */                                              \
   2297          "ld  3,80(11)\n\t"                                       \
   2298          "std 3,120(1)\n\t"                                       \
   2299          /* arg9 */                                               \
   2300          "ld  3,72(11)\n\t"                                       \
   2301          "std 3,112(1)\n\t"                                       \
   2302          /* args1-8 */                                            \
   2303          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2304          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2305          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2306          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2307          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2308          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   2309          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   2310          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   2311          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2312          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2313          "mr 11,%1\n\t"                                           \
   2314          "mr %0,3\n\t"                                            \
   2315          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
   2316          "addi 1,1,128"     /* restore frame */                   \
   2317          : /*out*/   "=r" (_res)                                  \
   2318          : /*in*/    "r" (&_argvec[2])                            \
   2319          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2320       );                                                          \
   2321       lval = (__typeof__(lval)) _res;                             \
   2322    } while (0)
   2323 
   2324 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   2325                                   arg7,arg8,arg9,arg10,arg11)     \
   2326    do {                                                           \
   2327       volatile OrigFn        _orig = (orig);                      \
   2328       volatile unsigned long _argvec[3+11];                       \
   2329       volatile unsigned long _res;                                \
   2330       /* _argvec[0] holds current r2 across the call */           \
   2331       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2332       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2333       _argvec[2+1] = (unsigned long)arg1;                         \
   2334       _argvec[2+2] = (unsigned long)arg2;                         \
   2335       _argvec[2+3] = (unsigned long)arg3;                         \
   2336       _argvec[2+4] = (unsigned long)arg4;                         \
   2337       _argvec[2+5] = (unsigned long)arg5;                         \
   2338       _argvec[2+6] = (unsigned long)arg6;                         \
   2339       _argvec[2+7] = (unsigned long)arg7;                         \
   2340       _argvec[2+8] = (unsigned long)arg8;                         \
   2341       _argvec[2+9] = (unsigned long)arg9;                         \
   2342       _argvec[2+10] = (unsigned long)arg10;                       \
   2343       _argvec[2+11] = (unsigned long)arg11;                       \
   2344       __asm__ volatile(                                           \
   2345          "mr 11,%1\n\t"                                           \
   2346          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2347          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2348          "addi 1,1,-144\n\t"  /* expand stack frame */            \
   2349          /* arg11 */                                              \
   2350          "ld  3,88(11)\n\t"                                       \
   2351          "std 3,128(1)\n\t"                                       \
   2352          /* arg10 */                                              \
   2353          "ld  3,80(11)\n\t"                                       \
   2354          "std 3,120(1)\n\t"                                       \
   2355          /* arg9 */                                               \
   2356          "ld  3,72(11)\n\t"                                       \
   2357          "std 3,112(1)\n\t"                                       \
   2358          /* args1-8 */                                            \
   2359          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2360          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2361          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2362          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2363          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2364          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   2365          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   2366          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   2367          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2368          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2369          "mr 11,%1\n\t"                                           \
   2370          "mr %0,3\n\t"                                            \
   2371          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
   2372          "addi 1,1,144"     /* restore frame */                   \
   2373          : /*out*/   "=r" (_res)                                  \
   2374          : /*in*/    "r" (&_argvec[2])                            \
   2375          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2376       );                                                          \
   2377       lval = (__typeof__(lval)) _res;                             \
   2378    } while (0)
   2379 
   2380 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   2381                                 arg7,arg8,arg9,arg10,arg11,arg12) \
   2382    do {                                                           \
   2383       volatile OrigFn        _orig = (orig);                      \
   2384       volatile unsigned long _argvec[3+12];                       \
   2385       volatile unsigned long _res;                                \
   2386       /* _argvec[0] holds current r2 across the call */           \
   2387       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2388       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2389       _argvec[2+1] = (unsigned long)arg1;                         \
   2390       _argvec[2+2] = (unsigned long)arg2;                         \
   2391       _argvec[2+3] = (unsigned long)arg3;                         \
   2392       _argvec[2+4] = (unsigned long)arg4;                         \
   2393       _argvec[2+5] = (unsigned long)arg5;                         \
   2394       _argvec[2+6] = (unsigned long)arg6;                         \
   2395       _argvec[2+7] = (unsigned long)arg7;                         \
   2396       _argvec[2+8] = (unsigned long)arg8;                         \
   2397       _argvec[2+9] = (unsigned long)arg9;                         \
   2398       _argvec[2+10] = (unsigned long)arg10;                       \
   2399       _argvec[2+11] = (unsigned long)arg11;                       \
   2400       _argvec[2+12] = (unsigned long)arg12;                       \
   2401       __asm__ volatile(                                           \
   2402          "mr 11,%1\n\t"                                           \
   2403          "std 2,-16(11)\n\t"  /* save tocptr */                   \
   2404          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   2405          "addi 1,1,-144\n\t"  /* expand stack frame */            \
   2406          /* arg12 */                                              \
   2407          "ld  3,96(11)\n\t"                                       \
   2408          "std 3,136(1)\n\t"                                       \
   2409          /* arg11 */                                              \
   2410          "ld  3,88(11)\n\t"                                       \
   2411          "std 3,128(1)\n\t"                                       \
   2412          /* arg10 */                                              \
   2413          "ld  3,80(11)\n\t"                                       \
   2414          "std 3,120(1)\n\t"                                       \
   2415          /* arg9 */                                               \
   2416          "ld  3,72(11)\n\t"                                       \
   2417          "std 3,112(1)\n\t"                                       \
   2418          /* args1-8 */                                            \
   2419          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   2420          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   2421          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   2422          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   2423          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   2424          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   2425          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   2426          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   2427          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   2428          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2429          "mr 11,%1\n\t"                                           \
   2430          "mr %0,3\n\t"                                            \
   2431          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
   2432          "addi 1,1,144"     /* restore frame */                   \
   2433          : /*out*/   "=r" (_res)                                  \
   2434          : /*in*/    "r" (&_argvec[2])                            \
   2435          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2436       );                                                          \
   2437       lval = (__typeof__(lval)) _res;                             \
   2438    } while (0)
   2439 
   2440 #endif /* PLAT_ppc64_linux */
   2441 
   2442 /* ------------------------ ppc32-aix5 ------------------------- */
   2443 
   2444 #if defined(PLAT_ppc32_aix5)
   2445 
   2446 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
   2447 
   2448 /* These regs are trashed by the hidden call. */
   2449 #define __CALLER_SAVED_REGS                                       \
   2450    "lr", "ctr", "xer",                                            \
   2451    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
   2452    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
   2453    "r11", "r12", "r13"
   2454 
   2455 /* Expand the stack frame, copying enough info that unwinding
   2456    still works.  Trashes r3. */
   2457 
   2458 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr)                      \
   2459          "addi 1,1,-" #_n_fr "\n\t"                               \
   2460          "lwz  3," #_n_fr "(1)\n\t"                               \
   2461          "stw  3,0(1)\n\t"
   2462 
   2463 #define VG_CONTRACT_FRAME_BY(_n_fr)                               \
   2464          "addi 1,1," #_n_fr "\n\t"
   2465 
   2466 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
   2467    long) == 4. */
   2468 
   2469 #define CALL_FN_W_v(lval, orig)                                   \
   2470    do {                                                           \
   2471       volatile OrigFn        _orig = (orig);                      \
   2472       volatile unsigned long _argvec[3+0];                        \
   2473       volatile unsigned long _res;                                \
   2474       /* _argvec[0] holds current r2 across the call */           \
   2475       _argvec[1] = (unsigned long)_orig.r2;                       \
   2476       _argvec[2] = (unsigned long)_orig.nraddr;                   \
   2477       __asm__ volatile(                                           \
   2478          "mr 11,%1\n\t"                                           \
   2479          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2480          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2481          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2482          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2483          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2484          "mr 11,%1\n\t"                                           \
   2485          "mr %0,3\n\t"                                            \
   2486          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2487          VG_CONTRACT_FRAME_BY(512)                                \
   2488          : /*out*/   "=r" (_res)                                  \
   2489          : /*in*/    "r" (&_argvec[2])                            \
   2490          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2491       );                                                          \
   2492       lval = (__typeof__(lval)) _res;                             \
   2493    } while (0)
   2494 
   2495 #define CALL_FN_W_W(lval, orig, arg1)                             \
   2496    do {                                                           \
   2497       volatile OrigFn        _orig = (orig);                      \
   2498       volatile unsigned long _argvec[3+1];                        \
   2499       volatile unsigned long _res;                                \
   2500       /* _argvec[0] holds current r2 across the call */           \
   2501       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2502       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2503       _argvec[2+1] = (unsigned long)arg1;                         \
   2504       __asm__ volatile(                                           \
   2505          "mr 11,%1\n\t"                                           \
   2506          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2507          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2508          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2509          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2510          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2511          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2512          "mr 11,%1\n\t"                                           \
   2513          "mr %0,3\n\t"                                            \
   2514          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2515          VG_CONTRACT_FRAME_BY(512)                                \
   2516          : /*out*/   "=r" (_res)                                  \
   2517          : /*in*/    "r" (&_argvec[2])                            \
   2518          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2519       );                                                          \
   2520       lval = (__typeof__(lval)) _res;                             \
   2521    } while (0)
   2522 
   2523 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
   2524    do {                                                           \
   2525       volatile OrigFn        _orig = (orig);                      \
   2526       volatile unsigned long _argvec[3+2];                        \
   2527       volatile unsigned long _res;                                \
   2528       /* _argvec[0] holds current r2 across the call */           \
   2529       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2530       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2531       _argvec[2+1] = (unsigned long)arg1;                         \
   2532       _argvec[2+2] = (unsigned long)arg2;                         \
   2533       __asm__ volatile(                                           \
   2534          "mr 11,%1\n\t"                                           \
   2535          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2536          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2537          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2538          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2539          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2540          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2541          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2542          "mr 11,%1\n\t"                                           \
   2543          "mr %0,3\n\t"                                            \
   2544          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2545          VG_CONTRACT_FRAME_BY(512)                                \
   2546          : /*out*/   "=r" (_res)                                  \
   2547          : /*in*/    "r" (&_argvec[2])                            \
   2548          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2549       );                                                          \
   2550       lval = (__typeof__(lval)) _res;                             \
   2551    } while (0)
   2552 
   2553 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
   2554    do {                                                           \
   2555       volatile OrigFn        _orig = (orig);                      \
   2556       volatile unsigned long _argvec[3+3];                        \
   2557       volatile unsigned long _res;                                \
   2558       /* _argvec[0] holds current r2 across the call */           \
   2559       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2560       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2561       _argvec[2+1] = (unsigned long)arg1;                         \
   2562       _argvec[2+2] = (unsigned long)arg2;                         \
   2563       _argvec[2+3] = (unsigned long)arg3;                         \
   2564       __asm__ volatile(                                           \
   2565          "mr 11,%1\n\t"                                           \
   2566          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2567          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2568          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2569          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2570          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2571          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2572          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2573          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2574          "mr 11,%1\n\t"                                           \
   2575          "mr %0,3\n\t"                                            \
   2576          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2577          VG_CONTRACT_FRAME_BY(512)                                \
   2578          : /*out*/   "=r" (_res)                                  \
   2579          : /*in*/    "r" (&_argvec[2])                            \
   2580          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2581       );                                                          \
   2582       lval = (__typeof__(lval)) _res;                             \
   2583    } while (0)
   2584 
   2585 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
   2586    do {                                                           \
   2587       volatile OrigFn        _orig = (orig);                      \
   2588       volatile unsigned long _argvec[3+4];                        \
   2589       volatile unsigned long _res;                                \
   2590       /* _argvec[0] holds current r2 across the call */           \
   2591       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2592       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2593       _argvec[2+1] = (unsigned long)arg1;                         \
   2594       _argvec[2+2] = (unsigned long)arg2;                         \
   2595       _argvec[2+3] = (unsigned long)arg3;                         \
   2596       _argvec[2+4] = (unsigned long)arg4;                         \
   2597       __asm__ volatile(                                           \
   2598          "mr 11,%1\n\t"                                           \
   2599          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2600          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2601          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2602          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2603          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2604          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2605          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2606          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2607          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2608          "mr 11,%1\n\t"                                           \
   2609          "mr %0,3\n\t"                                            \
   2610          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2611          VG_CONTRACT_FRAME_BY(512)                                \
   2612          : /*out*/   "=r" (_res)                                  \
   2613          : /*in*/    "r" (&_argvec[2])                            \
   2614          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2615       );                                                          \
   2616       lval = (__typeof__(lval)) _res;                             \
   2617    } while (0)
   2618 
   2619 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
   2620    do {                                                           \
   2621       volatile OrigFn        _orig = (orig);                      \
   2622       volatile unsigned long _argvec[3+5];                        \
   2623       volatile unsigned long _res;                                \
   2624       /* _argvec[0] holds current r2 across the call */           \
   2625       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2626       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2627       _argvec[2+1] = (unsigned long)arg1;                         \
   2628       _argvec[2+2] = (unsigned long)arg2;                         \
   2629       _argvec[2+3] = (unsigned long)arg3;                         \
   2630       _argvec[2+4] = (unsigned long)arg4;                         \
   2631       _argvec[2+5] = (unsigned long)arg5;                         \
   2632       __asm__ volatile(                                           \
   2633          "mr 11,%1\n\t"                                           \
   2634          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2635          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2636          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2637          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2638          "lwz  4, 8(11)\n\t" /* arg2->r4 */                       \
   2639          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2640          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2641          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2642          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2643          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2644          "mr 11,%1\n\t"                                           \
   2645          "mr %0,3\n\t"                                            \
   2646          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2647          VG_CONTRACT_FRAME_BY(512)                                \
   2648          : /*out*/   "=r" (_res)                                  \
   2649          : /*in*/    "r" (&_argvec[2])                            \
   2650          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2651       );                                                          \
   2652       lval = (__typeof__(lval)) _res;                             \
   2653    } while (0)
   2654 
   2655 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
   2656    do {                                                           \
   2657       volatile OrigFn        _orig = (orig);                      \
   2658       volatile unsigned long _argvec[3+6];                        \
   2659       volatile unsigned long _res;                                \
   2660       /* _argvec[0] holds current r2 across the call */           \
   2661       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2662       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2663       _argvec[2+1] = (unsigned long)arg1;                         \
   2664       _argvec[2+2] = (unsigned long)arg2;                         \
   2665       _argvec[2+3] = (unsigned long)arg3;                         \
   2666       _argvec[2+4] = (unsigned long)arg4;                         \
   2667       _argvec[2+5] = (unsigned long)arg5;                         \
   2668       _argvec[2+6] = (unsigned long)arg6;                         \
   2669       __asm__ volatile(                                           \
   2670          "mr 11,%1\n\t"                                           \
   2671          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2672          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2673          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2674          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2675          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2676          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2677          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2678          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2679          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
   2680          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2681          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2682          "mr 11,%1\n\t"                                           \
   2683          "mr %0,3\n\t"                                            \
   2684          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2685          VG_CONTRACT_FRAME_BY(512)                                \
   2686          : /*out*/   "=r" (_res)                                  \
   2687          : /*in*/    "r" (&_argvec[2])                            \
   2688          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2689       );                                                          \
   2690       lval = (__typeof__(lval)) _res;                             \
   2691    } while (0)
   2692 
   2693 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   2694                                  arg7)                            \
   2695    do {                                                           \
   2696       volatile OrigFn        _orig = (orig);                      \
   2697       volatile unsigned long _argvec[3+7];                        \
   2698       volatile unsigned long _res;                                \
   2699       /* _argvec[0] holds current r2 across the call */           \
   2700       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2701       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2702       _argvec[2+1] = (unsigned long)arg1;                         \
   2703       _argvec[2+2] = (unsigned long)arg2;                         \
   2704       _argvec[2+3] = (unsigned long)arg3;                         \
   2705       _argvec[2+4] = (unsigned long)arg4;                         \
   2706       _argvec[2+5] = (unsigned long)arg5;                         \
   2707       _argvec[2+6] = (unsigned long)arg6;                         \
   2708       _argvec[2+7] = (unsigned long)arg7;                         \
   2709       __asm__ volatile(                                           \
   2710          "mr 11,%1\n\t"                                           \
   2711          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2712          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2713          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2714          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2715          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2716          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2717          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2718          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2719          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
   2720          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
   2721          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2722          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2723          "mr 11,%1\n\t"                                           \
   2724          "mr %0,3\n\t"                                            \
   2725          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2726          VG_CONTRACT_FRAME_BY(512)                                \
   2727          : /*out*/   "=r" (_res)                                  \
   2728          : /*in*/    "r" (&_argvec[2])                            \
   2729          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2730       );                                                          \
   2731       lval = (__typeof__(lval)) _res;                             \
   2732    } while (0)
   2733 
   2734 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   2735                                  arg7,arg8)                       \
   2736    do {                                                           \
   2737       volatile OrigFn        _orig = (orig);                      \
   2738       volatile unsigned long _argvec[3+8];                        \
   2739       volatile unsigned long _res;                                \
   2740       /* _argvec[0] holds current r2 across the call */           \
   2741       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2742       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2743       _argvec[2+1] = (unsigned long)arg1;                         \
   2744       _argvec[2+2] = (unsigned long)arg2;                         \
   2745       _argvec[2+3] = (unsigned long)arg3;                         \
   2746       _argvec[2+4] = (unsigned long)arg4;                         \
   2747       _argvec[2+5] = (unsigned long)arg5;                         \
   2748       _argvec[2+6] = (unsigned long)arg6;                         \
   2749       _argvec[2+7] = (unsigned long)arg7;                         \
   2750       _argvec[2+8] = (unsigned long)arg8;                         \
   2751       __asm__ volatile(                                           \
   2752          "mr 11,%1\n\t"                                           \
   2753          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2754          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2755          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2756          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2757          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2758          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2759          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2760          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2761          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
   2762          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
   2763          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
   2764          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2765          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2766          "mr 11,%1\n\t"                                           \
   2767          "mr %0,3\n\t"                                            \
   2768          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2769          VG_CONTRACT_FRAME_BY(512)                                \
   2770          : /*out*/   "=r" (_res)                                  \
   2771          : /*in*/    "r" (&_argvec[2])                            \
   2772          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2773       );                                                          \
   2774       lval = (__typeof__(lval)) _res;                             \
   2775    } while (0)
   2776 
   2777 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   2778                                  arg7,arg8,arg9)                  \
   2779    do {                                                           \
   2780       volatile OrigFn        _orig = (orig);                      \
   2781       volatile unsigned long _argvec[3+9];                        \
   2782       volatile unsigned long _res;                                \
   2783       /* _argvec[0] holds current r2 across the call */           \
   2784       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2785       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2786       _argvec[2+1] = (unsigned long)arg1;                         \
   2787       _argvec[2+2] = (unsigned long)arg2;                         \
   2788       _argvec[2+3] = (unsigned long)arg3;                         \
   2789       _argvec[2+4] = (unsigned long)arg4;                         \
   2790       _argvec[2+5] = (unsigned long)arg5;                         \
   2791       _argvec[2+6] = (unsigned long)arg6;                         \
   2792       _argvec[2+7] = (unsigned long)arg7;                         \
   2793       _argvec[2+8] = (unsigned long)arg8;                         \
   2794       _argvec[2+9] = (unsigned long)arg9;                         \
   2795       __asm__ volatile(                                           \
   2796          "mr 11,%1\n\t"                                           \
   2797          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2798          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2799          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2800          VG_EXPAND_FRAME_BY_trashes_r3(64)                        \
   2801          /* arg9 */                                               \
   2802          "lwz 3,36(11)\n\t"                                       \
   2803          "stw 3,56(1)\n\t"                                        \
   2804          /* args1-8 */                                            \
   2805          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2806          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2807          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2808          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2809          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2810          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
   2811          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
   2812          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
   2813          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2814          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2815          "mr 11,%1\n\t"                                           \
   2816          "mr %0,3\n\t"                                            \
   2817          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2818          VG_CONTRACT_FRAME_BY(64)                                 \
   2819          VG_CONTRACT_FRAME_BY(512)                                \
   2820          : /*out*/   "=r" (_res)                                  \
   2821          : /*in*/    "r" (&_argvec[2])                            \
   2822          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2823       );                                                          \
   2824       lval = (__typeof__(lval)) _res;                             \
   2825    } while (0)
   2826 
   2827 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   2828                                   arg7,arg8,arg9,arg10)           \
   2829    do {                                                           \
   2830       volatile OrigFn        _orig = (orig);                      \
   2831       volatile unsigned long _argvec[3+10];                       \
   2832       volatile unsigned long _res;                                \
   2833       /* _argvec[0] holds current r2 across the call */           \
   2834       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2835       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2836       _argvec[2+1] = (unsigned long)arg1;                         \
   2837       _argvec[2+2] = (unsigned long)arg2;                         \
   2838       _argvec[2+3] = (unsigned long)arg3;                         \
   2839       _argvec[2+4] = (unsigned long)arg4;                         \
   2840       _argvec[2+5] = (unsigned long)arg5;                         \
   2841       _argvec[2+6] = (unsigned long)arg6;                         \
   2842       _argvec[2+7] = (unsigned long)arg7;                         \
   2843       _argvec[2+8] = (unsigned long)arg8;                         \
   2844       _argvec[2+9] = (unsigned long)arg9;                         \
   2845       _argvec[2+10] = (unsigned long)arg10;                       \
   2846       __asm__ volatile(                                           \
   2847          "mr 11,%1\n\t"                                           \
   2848          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2849          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2850          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2851          VG_EXPAND_FRAME_BY_trashes_r3(64)                        \
   2852          /* arg10 */                                              \
   2853          "lwz 3,40(11)\n\t"                                       \
   2854          "stw 3,60(1)\n\t"                                        \
   2855          /* arg9 */                                               \
   2856          "lwz 3,36(11)\n\t"                                       \
   2857          "stw 3,56(1)\n\t"                                        \
   2858          /* args1-8 */                                            \
   2859          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2860          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2861          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2862          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2863          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2864          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
   2865          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
   2866          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
   2867          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2868          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2869          "mr 11,%1\n\t"                                           \
   2870          "mr %0,3\n\t"                                            \
   2871          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2872          VG_CONTRACT_FRAME_BY(64)                                 \
   2873          VG_CONTRACT_FRAME_BY(512)                                \
   2874          : /*out*/   "=r" (_res)                                  \
   2875          : /*in*/    "r" (&_argvec[2])                            \
   2876          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2877       );                                                          \
   2878       lval = (__typeof__(lval)) _res;                             \
   2879    } while (0)
   2880 
   2881 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   2882                                   arg7,arg8,arg9,arg10,arg11)     \
   2883    do {                                                           \
   2884       volatile OrigFn        _orig = (orig);                      \
   2885       volatile unsigned long _argvec[3+11];                       \
   2886       volatile unsigned long _res;                                \
   2887       /* _argvec[0] holds current r2 across the call */           \
   2888       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2889       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2890       _argvec[2+1] = (unsigned long)arg1;                         \
   2891       _argvec[2+2] = (unsigned long)arg2;                         \
   2892       _argvec[2+3] = (unsigned long)arg3;                         \
   2893       _argvec[2+4] = (unsigned long)arg4;                         \
   2894       _argvec[2+5] = (unsigned long)arg5;                         \
   2895       _argvec[2+6] = (unsigned long)arg6;                         \
   2896       _argvec[2+7] = (unsigned long)arg7;                         \
   2897       _argvec[2+8] = (unsigned long)arg8;                         \
   2898       _argvec[2+9] = (unsigned long)arg9;                         \
   2899       _argvec[2+10] = (unsigned long)arg10;                       \
   2900       _argvec[2+11] = (unsigned long)arg11;                       \
   2901       __asm__ volatile(                                           \
   2902          "mr 11,%1\n\t"                                           \
   2903          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2904          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2905          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2906          VG_EXPAND_FRAME_BY_trashes_r3(72)                        \
   2907          /* arg11 */                                              \
   2908          "lwz 3,44(11)\n\t"                                       \
   2909          "stw 3,64(1)\n\t"                                        \
   2910          /* arg10 */                                              \
   2911          "lwz 3,40(11)\n\t"                                       \
   2912          "stw 3,60(1)\n\t"                                        \
   2913          /* arg9 */                                               \
   2914          "lwz 3,36(11)\n\t"                                       \
   2915          "stw 3,56(1)\n\t"                                        \
   2916          /* args1-8 */                                            \
   2917          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2918          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2919          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2920          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2921          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2922          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
   2923          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
   2924          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
   2925          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2926          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2927          "mr 11,%1\n\t"                                           \
   2928          "mr %0,3\n\t"                                            \
   2929          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2930          VG_CONTRACT_FRAME_BY(72)                                 \
   2931          VG_CONTRACT_FRAME_BY(512)                                \
   2932          : /*out*/   "=r" (_res)                                  \
   2933          : /*in*/    "r" (&_argvec[2])                            \
   2934          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2935       );                                                          \
   2936       lval = (__typeof__(lval)) _res;                             \
   2937    } while (0)
   2938 
   2939 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   2940                                 arg7,arg8,arg9,arg10,arg11,arg12) \
   2941    do {                                                           \
   2942       volatile OrigFn        _orig = (orig);                      \
   2943       volatile unsigned long _argvec[3+12];                       \
   2944       volatile unsigned long _res;                                \
   2945       /* _argvec[0] holds current r2 across the call */           \
   2946       _argvec[1]   = (unsigned long)_orig.r2;                     \
   2947       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   2948       _argvec[2+1] = (unsigned long)arg1;                         \
   2949       _argvec[2+2] = (unsigned long)arg2;                         \
   2950       _argvec[2+3] = (unsigned long)arg3;                         \
   2951       _argvec[2+4] = (unsigned long)arg4;                         \
   2952       _argvec[2+5] = (unsigned long)arg5;                         \
   2953       _argvec[2+6] = (unsigned long)arg6;                         \
   2954       _argvec[2+7] = (unsigned long)arg7;                         \
   2955       _argvec[2+8] = (unsigned long)arg8;                         \
   2956       _argvec[2+9] = (unsigned long)arg9;                         \
   2957       _argvec[2+10] = (unsigned long)arg10;                       \
   2958       _argvec[2+11] = (unsigned long)arg11;                       \
   2959       _argvec[2+12] = (unsigned long)arg12;                       \
   2960       __asm__ volatile(                                           \
   2961          "mr 11,%1\n\t"                                           \
   2962          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   2963          "stw  2,-8(11)\n\t"  /* save tocptr */                   \
   2964          "lwz  2,-4(11)\n\t"  /* use nraddr's tocptr */           \
   2965          VG_EXPAND_FRAME_BY_trashes_r3(72)                        \
   2966          /* arg12 */                                              \
   2967          "lwz 3,48(11)\n\t"                                       \
   2968          "stw 3,68(1)\n\t"                                        \
   2969          /* arg11 */                                              \
   2970          "lwz 3,44(11)\n\t"                                       \
   2971          "stw 3,64(1)\n\t"                                        \
   2972          /* arg10 */                                              \
   2973          "lwz 3,40(11)\n\t"                                       \
   2974          "stw 3,60(1)\n\t"                                        \
   2975          /* arg9 */                                               \
   2976          "lwz 3,36(11)\n\t"                                       \
   2977          "stw 3,56(1)\n\t"                                        \
   2978          /* args1-8 */                                            \
   2979          "lwz  3, 4(11)\n\t"  /* arg1->r3 */                      \
   2980          "lwz  4, 8(11)\n\t"  /* arg2->r4 */                      \
   2981          "lwz  5, 12(11)\n\t" /* arg3->r5 */                      \
   2982          "lwz  6, 16(11)\n\t" /* arg4->r6 */                      \
   2983          "lwz  7, 20(11)\n\t" /* arg5->r7 */                      \
   2984          "lwz  8, 24(11)\n\t" /* arg6->r8 */                      \
   2985          "lwz  9, 28(11)\n\t" /* arg7->r9 */                      \
   2986          "lwz 10, 32(11)\n\t" /* arg8->r10 */                     \
   2987          "lwz 11, 0(11)\n\t"  /* target->r11 */                   \
   2988          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   2989          "mr 11,%1\n\t"                                           \
   2990          "mr %0,3\n\t"                                            \
   2991          "lwz 2,-8(11)\n\t" /* restore tocptr */                  \
   2992          VG_CONTRACT_FRAME_BY(72)                                 \
   2993          VG_CONTRACT_FRAME_BY(512)                                \
   2994          : /*out*/   "=r" (_res)                                  \
   2995          : /*in*/    "r" (&_argvec[2])                            \
   2996          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   2997       );                                                          \
   2998       lval = (__typeof__(lval)) _res;                             \
   2999    } while (0)
   3000 
   3001 #endif /* PLAT_ppc32_aix5 */
   3002 
   3003 /* ------------------------ ppc64-aix5 ------------------------- */
   3004 
   3005 #if defined(PLAT_ppc64_aix5)
   3006 
   3007 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
   3008 
   3009 /* These regs are trashed by the hidden call. */
   3010 #define __CALLER_SAVED_REGS                                       \
   3011    "lr", "ctr", "xer",                                            \
   3012    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
   3013    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
   3014    "r11", "r12", "r13"
   3015 
   3016 /* Expand the stack frame, copying enough info that unwinding
   3017    still works.  Trashes r3. */
   3018 
   3019 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr)                      \
   3020          "addi 1,1,-" #_n_fr "\n\t"                               \
   3021          "ld   3," #_n_fr "(1)\n\t"                               \
   3022          "std  3,0(1)\n\t"
   3023 
   3024 #define VG_CONTRACT_FRAME_BY(_n_fr)                               \
   3025          "addi 1,1," #_n_fr "\n\t"
   3026 
   3027 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
   3028    long) == 8. */
   3029 
   3030 #define CALL_FN_W_v(lval, orig)                                   \
   3031    do {                                                           \
   3032       volatile OrigFn        _orig = (orig);                      \
   3033       volatile unsigned long _argvec[3+0];                        \
   3034       volatile unsigned long _res;                                \
   3035       /* _argvec[0] holds current r2 across the call */           \
   3036       _argvec[1] = (unsigned long)_orig.r2;                       \
   3037       _argvec[2] = (unsigned long)_orig.nraddr;                   \
   3038       __asm__ volatile(                                           \
   3039          "mr 11,%1\n\t"                                           \
   3040          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3041          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3042          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3043          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3044          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3045          "mr 11,%1\n\t"                                           \
   3046          "mr %0,3\n\t"                                            \
   3047          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
   3048          VG_CONTRACT_FRAME_BY(512)                                \
   3049          : /*out*/   "=r" (_res)                                  \
   3050          : /*in*/    "r" (&_argvec[2])                            \
   3051          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3052       );                                                          \
   3053       lval = (__typeof__(lval)) _res;                             \
   3054    } while (0)
   3055 
   3056 #define CALL_FN_W_W(lval, orig, arg1)                             \
   3057    do {                                                           \
   3058       volatile OrigFn        _orig = (orig);                      \
   3059       volatile unsigned long _argvec[3+1];                        \
   3060       volatile unsigned long _res;                                \
   3061       /* _argvec[0] holds current r2 across the call */           \
   3062       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3063       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3064       _argvec[2+1] = (unsigned long)arg1;                         \
   3065       __asm__ volatile(                                           \
   3066          "mr 11,%1\n\t"                                           \
   3067          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3068          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3069          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3070          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3071          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3072          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3073          "mr 11,%1\n\t"                                           \
   3074          "mr %0,3\n\t"                                            \
   3075          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
   3076          VG_CONTRACT_FRAME_BY(512)                                \
   3077          : /*out*/   "=r" (_res)                                  \
   3078          : /*in*/    "r" (&_argvec[2])                            \
   3079          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3080       );                                                          \
   3081       lval = (__typeof__(lval)) _res;                             \
   3082    } while (0)
   3083 
   3084 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
   3085    do {                                                           \
   3086       volatile OrigFn        _orig = (orig);                      \
   3087       volatile unsigned long _argvec[3+2];                        \
   3088       volatile unsigned long _res;                                \
   3089       /* _argvec[0] holds current r2 across the call */           \
   3090       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3091       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3092       _argvec[2+1] = (unsigned long)arg1;                         \
   3093       _argvec[2+2] = (unsigned long)arg2;                         \
   3094       __asm__ volatile(                                           \
   3095          "mr 11,%1\n\t"                                           \
   3096          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3097          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3098          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3099          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3100          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3101          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3102          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3103          "mr 11,%1\n\t"                                           \
   3104          "mr %0,3\n\t"                                            \
   3105          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3106          VG_CONTRACT_FRAME_BY(512)                                \
   3107          : /*out*/   "=r" (_res)                                  \
   3108          : /*in*/    "r" (&_argvec[2])                            \
   3109          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3110       );                                                          \
   3111       lval = (__typeof__(lval)) _res;                             \
   3112    } while (0)
   3113 
   3114 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
   3115    do {                                                           \
   3116       volatile OrigFn        _orig = (orig);                      \
   3117       volatile unsigned long _argvec[3+3];                        \
   3118       volatile unsigned long _res;                                \
   3119       /* _argvec[0] holds current r2 across the call */           \
   3120       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3121       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3122       _argvec[2+1] = (unsigned long)arg1;                         \
   3123       _argvec[2+2] = (unsigned long)arg2;                         \
   3124       _argvec[2+3] = (unsigned long)arg3;                         \
   3125       __asm__ volatile(                                           \
   3126          "mr 11,%1\n\t"                                           \
   3127          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3128          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3129          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3130          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3131          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3132          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3133          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3134          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3135          "mr 11,%1\n\t"                                           \
   3136          "mr %0,3\n\t"                                            \
   3137          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3138          VG_CONTRACT_FRAME_BY(512)                                \
   3139          : /*out*/   "=r" (_res)                                  \
   3140          : /*in*/    "r" (&_argvec[2])                            \
   3141          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3142       );                                                          \
   3143       lval = (__typeof__(lval)) _res;                             \
   3144    } while (0)
   3145 
   3146 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
   3147    do {                                                           \
   3148       volatile OrigFn        _orig = (orig);                      \
   3149       volatile unsigned long _argvec[3+4];                        \
   3150       volatile unsigned long _res;                                \
   3151       /* _argvec[0] holds current r2 across the call */           \
   3152       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3153       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3154       _argvec[2+1] = (unsigned long)arg1;                         \
   3155       _argvec[2+2] = (unsigned long)arg2;                         \
   3156       _argvec[2+3] = (unsigned long)arg3;                         \
   3157       _argvec[2+4] = (unsigned long)arg4;                         \
   3158       __asm__ volatile(                                           \
   3159          "mr 11,%1\n\t"                                           \
   3160          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3161          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3162          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3163          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3164          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3165          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3166          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3167          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3168          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3169          "mr 11,%1\n\t"                                           \
   3170          "mr %0,3\n\t"                                            \
   3171          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3172          VG_CONTRACT_FRAME_BY(512)                                \
   3173          : /*out*/   "=r" (_res)                                  \
   3174          : /*in*/    "r" (&_argvec[2])                            \
   3175          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3176       );                                                          \
   3177       lval = (__typeof__(lval)) _res;                             \
   3178    } while (0)
   3179 
   3180 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
   3181    do {                                                           \
   3182       volatile OrigFn        _orig = (orig);                      \
   3183       volatile unsigned long _argvec[3+5];                        \
   3184       volatile unsigned long _res;                                \
   3185       /* _argvec[0] holds current r2 across the call */           \
   3186       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3187       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3188       _argvec[2+1] = (unsigned long)arg1;                         \
   3189       _argvec[2+2] = (unsigned long)arg2;                         \
   3190       _argvec[2+3] = (unsigned long)arg3;                         \
   3191       _argvec[2+4] = (unsigned long)arg4;                         \
   3192       _argvec[2+5] = (unsigned long)arg5;                         \
   3193       __asm__ volatile(                                           \
   3194          "mr 11,%1\n\t"                                           \
   3195          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3196          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3197          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3198          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3199          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3200          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3201          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3202          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3203          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3204          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3205          "mr 11,%1\n\t"                                           \
   3206          "mr %0,3\n\t"                                            \
   3207          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3208          VG_CONTRACT_FRAME_BY(512)                                \
   3209          : /*out*/   "=r" (_res)                                  \
   3210          : /*in*/    "r" (&_argvec[2])                            \
   3211          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3212       );                                                          \
   3213       lval = (__typeof__(lval)) _res;                             \
   3214    } while (0)
   3215 
   3216 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
   3217    do {                                                           \
   3218       volatile OrigFn        _orig = (orig);                      \
   3219       volatile unsigned long _argvec[3+6];                        \
   3220       volatile unsigned long _res;                                \
   3221       /* _argvec[0] holds current r2 across the call */           \
   3222       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3223       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3224       _argvec[2+1] = (unsigned long)arg1;                         \
   3225       _argvec[2+2] = (unsigned long)arg2;                         \
   3226       _argvec[2+3] = (unsigned long)arg3;                         \
   3227       _argvec[2+4] = (unsigned long)arg4;                         \
   3228       _argvec[2+5] = (unsigned long)arg5;                         \
   3229       _argvec[2+6] = (unsigned long)arg6;                         \
   3230       __asm__ volatile(                                           \
   3231          "mr 11,%1\n\t"                                           \
   3232          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3233          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3234          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3235          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3236          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3237          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3238          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3239          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3240          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   3241          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3242          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3243          "mr 11,%1\n\t"                                           \
   3244          "mr %0,3\n\t"                                            \
   3245          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3246          VG_CONTRACT_FRAME_BY(512)                                \
   3247          : /*out*/   "=r" (_res)                                  \
   3248          : /*in*/    "r" (&_argvec[2])                            \
   3249          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3250       );                                                          \
   3251       lval = (__typeof__(lval)) _res;                             \
   3252    } while (0)
   3253 
   3254 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   3255                                  arg7)                            \
   3256    do {                                                           \
   3257       volatile OrigFn        _orig = (orig);                      \
   3258       volatile unsigned long _argvec[3+7];                        \
   3259       volatile unsigned long _res;                                \
   3260       /* _argvec[0] holds current r2 across the call */           \
   3261       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3262       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3263       _argvec[2+1] = (unsigned long)arg1;                         \
   3264       _argvec[2+2] = (unsigned long)arg2;                         \
   3265       _argvec[2+3] = (unsigned long)arg3;                         \
   3266       _argvec[2+4] = (unsigned long)arg4;                         \
   3267       _argvec[2+5] = (unsigned long)arg5;                         \
   3268       _argvec[2+6] = (unsigned long)arg6;                         \
   3269       _argvec[2+7] = (unsigned long)arg7;                         \
   3270       __asm__ volatile(                                           \
   3271          "mr 11,%1\n\t"                                           \
   3272          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3273          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3274          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3275          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3276          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3277          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3278          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3279          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3280          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   3281          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   3282          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3283          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3284          "mr 11,%1\n\t"                                           \
   3285          "mr %0,3\n\t"                                            \
   3286          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3287          VG_CONTRACT_FRAME_BY(512)                                \
   3288          : /*out*/   "=r" (_res)                                  \
   3289          : /*in*/    "r" (&_argvec[2])                            \
   3290          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3291       );                                                          \
   3292       lval = (__typeof__(lval)) _res;                             \
   3293    } while (0)
   3294 
   3295 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   3296                                  arg7,arg8)                       \
   3297    do {                                                           \
   3298       volatile OrigFn        _orig = (orig);                      \
   3299       volatile unsigned long _argvec[3+8];                        \
   3300       volatile unsigned long _res;                                \
   3301       /* _argvec[0] holds current r2 across the call */           \
   3302       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3303       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3304       _argvec[2+1] = (unsigned long)arg1;                         \
   3305       _argvec[2+2] = (unsigned long)arg2;                         \
   3306       _argvec[2+3] = (unsigned long)arg3;                         \
   3307       _argvec[2+4] = (unsigned long)arg4;                         \
   3308       _argvec[2+5] = (unsigned long)arg5;                         \
   3309       _argvec[2+6] = (unsigned long)arg6;                         \
   3310       _argvec[2+7] = (unsigned long)arg7;                         \
   3311       _argvec[2+8] = (unsigned long)arg8;                         \
   3312       __asm__ volatile(                                           \
   3313          "mr 11,%1\n\t"                                           \
   3314          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3315          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3316          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3317          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3318          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3319          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3320          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3321          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3322          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   3323          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   3324          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   3325          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3326          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3327          "mr 11,%1\n\t"                                           \
   3328          "mr %0,3\n\t"                                            \
   3329          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3330          VG_CONTRACT_FRAME_BY(512)                                \
   3331          : /*out*/   "=r" (_res)                                  \
   3332          : /*in*/    "r" (&_argvec[2])                            \
   3333          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3334       );                                                          \
   3335       lval = (__typeof__(lval)) _res;                             \
   3336    } while (0)
   3337 
   3338 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
   3339                                  arg7,arg8,arg9)                  \
   3340    do {                                                           \
   3341       volatile OrigFn        _orig = (orig);                      \
   3342       volatile unsigned long _argvec[3+9];                        \
   3343       volatile unsigned long _res;                                \
   3344       /* _argvec[0] holds current r2 across the call */           \
   3345       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3346       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3347       _argvec[2+1] = (unsigned long)arg1;                         \
   3348       _argvec[2+2] = (unsigned long)arg2;                         \
   3349       _argvec[2+3] = (unsigned long)arg3;                         \
   3350       _argvec[2+4] = (unsigned long)arg4;                         \
   3351       _argvec[2+5] = (unsigned long)arg5;                         \
   3352       _argvec[2+6] = (unsigned long)arg6;                         \
   3353       _argvec[2+7] = (unsigned long)arg7;                         \
   3354       _argvec[2+8] = (unsigned long)arg8;                         \
   3355       _argvec[2+9] = (unsigned long)arg9;                         \
   3356       __asm__ volatile(                                           \
   3357          "mr 11,%1\n\t"                                           \
   3358          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3359          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3360          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3361          VG_EXPAND_FRAME_BY_trashes_r3(128)                       \
   3362          /* arg9 */                                               \
   3363          "ld  3,72(11)\n\t"                                       \
   3364          "std 3,112(1)\n\t"                                       \
   3365          /* args1-8 */                                            \
   3366          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3367          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3368          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3369          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3370          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3371          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   3372          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   3373          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   3374          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3375          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3376          "mr 11,%1\n\t"                                           \
   3377          "mr %0,3\n\t"                                            \
   3378          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3379          VG_CONTRACT_FRAME_BY(128)                                \
   3380          VG_CONTRACT_FRAME_BY(512)                                \
   3381          : /*out*/   "=r" (_res)                                  \
   3382          : /*in*/    "r" (&_argvec[2])                            \
   3383          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3384       );                                                          \
   3385       lval = (__typeof__(lval)) _res;                             \
   3386    } while (0)
   3387 
   3388 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   3389                                   arg7,arg8,arg9,arg10)           \
   3390    do {                                                           \
   3391       volatile OrigFn        _orig = (orig);                      \
   3392       volatile unsigned long _argvec[3+10];                       \
   3393       volatile unsigned long _res;                                \
   3394       /* _argvec[0] holds current r2 across the call */           \
   3395       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3396       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3397       _argvec[2+1] = (unsigned long)arg1;                         \
   3398       _argvec[2+2] = (unsigned long)arg2;                         \
   3399       _argvec[2+3] = (unsigned long)arg3;                         \
   3400       _argvec[2+4] = (unsigned long)arg4;                         \
   3401       _argvec[2+5] = (unsigned long)arg5;                         \
   3402       _argvec[2+6] = (unsigned long)arg6;                         \
   3403       _argvec[2+7] = (unsigned long)arg7;                         \
   3404       _argvec[2+8] = (unsigned long)arg8;                         \
   3405       _argvec[2+9] = (unsigned long)arg9;                         \
   3406       _argvec[2+10] = (unsigned long)arg10;                       \
   3407       __asm__ volatile(                                           \
   3408          "mr 11,%1\n\t"                                           \
   3409          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3410          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3411          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3412          VG_EXPAND_FRAME_BY_trashes_r3(128)                       \
   3413          /* arg10 */                                              \
   3414          "ld  3,80(11)\n\t"                                       \
   3415          "std 3,120(1)\n\t"                                       \
   3416          /* arg9 */                                               \
   3417          "ld  3,72(11)\n\t"                                       \
   3418          "std 3,112(1)\n\t"                                       \
   3419          /* args1-8 */                                            \
   3420          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3421          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3422          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3423          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3424          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3425          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   3426          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   3427          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   3428          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3429          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3430          "mr 11,%1\n\t"                                           \
   3431          "mr %0,3\n\t"                                            \
   3432          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3433          VG_CONTRACT_FRAME_BY(128)                                \
   3434          VG_CONTRACT_FRAME_BY(512)                                \
   3435          : /*out*/   "=r" (_res)                                  \
   3436          : /*in*/    "r" (&_argvec[2])                            \
   3437          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3438       );                                                          \
   3439       lval = (__typeof__(lval)) _res;                             \
   3440    } while (0)
   3441 
   3442 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   3443                                   arg7,arg8,arg9,arg10,arg11)     \
   3444    do {                                                           \
   3445       volatile OrigFn        _orig = (orig);                      \
   3446       volatile unsigned long _argvec[3+11];                       \
   3447       volatile unsigned long _res;                                \
   3448       /* _argvec[0] holds current r2 across the call */           \
   3449       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3450       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3451       _argvec[2+1] = (unsigned long)arg1;                         \
   3452       _argvec[2+2] = (unsigned long)arg2;                         \
   3453       _argvec[2+3] = (unsigned long)arg3;                         \
   3454       _argvec[2+4] = (unsigned long)arg4;                         \
   3455       _argvec[2+5] = (unsigned long)arg5;                         \
   3456       _argvec[2+6] = (unsigned long)arg6;                         \
   3457       _argvec[2+7] = (unsigned long)arg7;                         \
   3458       _argvec[2+8] = (unsigned long)arg8;                         \
   3459       _argvec[2+9] = (unsigned long)arg9;                         \
   3460       _argvec[2+10] = (unsigned long)arg10;                       \
   3461       _argvec[2+11] = (unsigned long)arg11;                       \
   3462       __asm__ volatile(                                           \
   3463          "mr 11,%1\n\t"                                           \
   3464          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3465          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3466          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3467          VG_EXPAND_FRAME_BY_trashes_r3(144)                       \
   3468          /* arg11 */                                              \
   3469          "ld  3,88(11)\n\t"                                       \
   3470          "std 3,128(1)\n\t"                                       \
   3471          /* arg10 */                                              \
   3472          "ld  3,80(11)\n\t"                                       \
   3473          "std 3,120(1)\n\t"                                       \
   3474          /* arg9 */                                               \
   3475          "ld  3,72(11)\n\t"                                       \
   3476          "std 3,112(1)\n\t"                                       \
   3477          /* args1-8 */                                            \
   3478          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3479          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3480          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3481          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3482          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3483          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   3484          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   3485          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   3486          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3487          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3488          "mr 11,%1\n\t"                                           \
   3489          "mr %0,3\n\t"                                            \
   3490          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3491          VG_CONTRACT_FRAME_BY(144)                                \
   3492          VG_CONTRACT_FRAME_BY(512)                                \
   3493          : /*out*/   "=r" (_res)                                  \
   3494          : /*in*/    "r" (&_argvec[2])                            \
   3495          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3496       );                                                          \
   3497       lval = (__typeof__(lval)) _res;                             \
   3498    } while (0)
   3499 
   3500 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
   3501                                 arg7,arg8,arg9,arg10,arg11,arg12) \
   3502    do {                                                           \
   3503       volatile OrigFn        _orig = (orig);                      \
   3504       volatile unsigned long _argvec[3+12];                       \
   3505       volatile unsigned long _res;                                \
   3506       /* _argvec[0] holds current r2 across the call */           \
   3507       _argvec[1]   = (unsigned long)_orig.r2;                     \
   3508       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
   3509       _argvec[2+1] = (unsigned long)arg1;                         \
   3510       _argvec[2+2] = (unsigned long)arg2;                         \
   3511       _argvec[2+3] = (unsigned long)arg3;                         \
   3512       _argvec[2+4] = (unsigned long)arg4;                         \
   3513       _argvec[2+5] = (unsigned long)arg5;                         \
   3514       _argvec[2+6] = (unsigned long)arg6;                         \
   3515       _argvec[2+7] = (unsigned long)arg7;                         \
   3516       _argvec[2+8] = (unsigned long)arg8;                         \
   3517       _argvec[2+9] = (unsigned long)arg9;                         \
   3518       _argvec[2+10] = (unsigned long)arg10;                       \
   3519       _argvec[2+11] = (unsigned long)arg11;                       \
   3520       _argvec[2+12] = (unsigned long)arg12;                       \
   3521       __asm__ volatile(                                           \
   3522          "mr 11,%1\n\t"                                           \
   3523          VG_EXPAND_FRAME_BY_trashes_r3(512)                       \
   3524          "std  2,-16(11)\n\t" /* save tocptr */                   \
   3525          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
   3526          VG_EXPAND_FRAME_BY_trashes_r3(144)                       \
   3527          /* arg12 */                                              \
   3528          "ld  3,96(11)\n\t"                                       \
   3529          "std 3,136(1)\n\t"                                       \
   3530          /* arg11 */                                              \
   3531          "ld  3,88(11)\n\t"                                       \
   3532          "std 3,128(1)\n\t"                                       \
   3533          /* arg10 */                                              \
   3534          "ld  3,80(11)\n\t"                                       \
   3535          "std 3,120(1)\n\t"                                       \
   3536          /* arg9 */                                               \
   3537          "ld  3,72(11)\n\t"                                       \
   3538          "std 3,112(1)\n\t"                                       \
   3539          /* args1-8 */                                            \
   3540          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
   3541          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
   3542          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
   3543          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
   3544          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
   3545          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
   3546          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
   3547          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
   3548          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
   3549          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
   3550          "mr 11,%1\n\t"                                           \
   3551          "mr %0,3\n\t"                                            \
   3552          "ld  2,-16(11)\n\t" /* restore tocptr */                 \
   3553          VG_CONTRACT_FRAME_BY(144)                                \
   3554          VG_CONTRACT_FRAME_BY(512)                                \
   3555          : /*out*/   "=r" (_res)                                  \
   3556          : /*in*/    "r" (&_argvec[2])                            \
   3557          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS          \
   3558       );                                                          \
   3559       lval = (__typeof__(lval)) _res;                             \
   3560    } while (0)
   3561 
   3562 #endif /* PLAT_ppc64_aix5 */
   3563 
   3564 
   3565 /* ------------------------------------------------------------------ */
   3566 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
   3567 /*                                                                    */
   3568 /* ------------------------------------------------------------------ */
   3569 
   3570 /* Some request codes.  There are many more of these, but most are not
   3571    exposed to end-user view.  These are the public ones, all of the
   3572    form 0x1000 + small_number.
   3573 
   3574    Core ones are in the range 0x00000000--0x0000ffff.  The non-public
   3575    ones start at 0x2000.
   3576 */
   3577 
   3578 /* These macros are used by tools -- they must be public, but don't
   3579    embed them into other programs. */
   3580 #define VG_USERREQ_TOOL_BASE(a,b) \
   3581    ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
   3582 #define VG_IS_TOOL_USERREQ(a, b, v) \
   3583    (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
   3584 
   3585 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
   3586    This enum comprises an ABI exported by Valgrind to programs
   3587    which use client requests.  DO NOT CHANGE THE ORDER OF THESE
   3588    ENTRIES, NOR DELETE ANY -- add new ones at the end. */
   3589 typedef
   3590    enum { VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
   3591           VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
   3592 
   3593           /* These allow any function to be called from the simulated
   3594              CPU but run on the real CPU.  Nb: the first arg passed to
   3595              the function is always the ThreadId of the running
   3596              thread!  So CLIENT_CALL0 actually requires a 1 arg
   3597              function, etc. */
   3598           VG_USERREQ__CLIENT_CALL0 = 0x1101,
   3599           VG_USERREQ__CLIENT_CALL1 = 0x1102,
   3600           VG_USERREQ__CLIENT_CALL2 = 0x1103,
   3601           VG_USERREQ__CLIENT_CALL3 = 0x1104,
   3602 
   3603           /* Can be useful in regression testing suites -- eg. can
   3604              send Valgrind's output to /dev/null and still count
   3605              errors. */
   3606           VG_USERREQ__COUNT_ERRORS = 0x1201,
   3607 
   3608           /* These are useful and can be interpreted by any tool that
   3609              tracks malloc() et al, by using vg_replace_malloc.c. */
   3610           VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
   3611           VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
   3612           /* Memory pool support. */
   3613           VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
   3614           VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
   3615           VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
   3616           VG_USERREQ__MEMPOOL_FREE     = 0x1306,
   3617           VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
   3618           VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
   3619           VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
   3620           VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
   3621 
   3622           /* Allow printfs to valgrind log. */
   3623           VG_USERREQ__PRINTF           = 0x1401,
   3624           VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
   3625 
   3626           /* Stack support. */
   3627           VG_USERREQ__STACK_REGISTER   = 0x1501,
   3628           VG_USERREQ__STACK_DEREGISTER = 0x1502,
   3629           VG_USERREQ__STACK_CHANGE     = 0x1503
   3630    } Vg_ClientRequest;
   3631 
   3632 #if !defined(__GNUC__)
   3633 #  define __extension__ /* */
   3634 #endif
   3635 
   3636 /* Returns the number of Valgrinds this code is running under.  That
   3637    is, 0 if running natively, 1 if running under Valgrind, 2 if
   3638    running under Valgrind which is running under another Valgrind,
   3639    etc. */
   3640 #define RUNNING_ON_VALGRIND  __extension__                        \
   3641    ({unsigned int _qzz_res;                                       \
   3642     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */,          \
   3643                                VG_USERREQ__RUNNING_ON_VALGRIND,   \
   3644                                0, 0, 0, 0, 0);                    \
   3645     _qzz_res;                                                     \
   3646    })
   3647 
   3648 
   3649 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
   3650    _qzz_len - 1].  Useful if you are debugging a JITter or some such,
   3651    since it provides a way to make sure valgrind will retranslate the
   3652    invalidated area.  Returns no value. */
   3653 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len)         \
   3654    {unsigned int _qzz_res;                                        \
   3655     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3656                                VG_USERREQ__DISCARD_TRANSLATIONS,  \
   3657                                _qzz_addr, _qzz_len, 0, 0, 0);     \
   3658    }
   3659 
   3660 
   3661 /* These requests are for getting Valgrind itself to print something.
   3662    Possibly with a backtrace.  This is a really ugly hack. */
   3663 
   3664 #if defined(NVALGRIND)
   3665 
   3666 #  define VALGRIND_PRINTF(...)
   3667 #  define VALGRIND_PRINTF_BACKTRACE(...)
   3668 
   3669 #else /* NVALGRIND */
   3670 
   3671 /* Modern GCC will optimize the static routine out if unused,
   3672    and unused attribute will shut down warnings about it.  */
   3673 static int VALGRIND_PRINTF(const char *format, ...)
   3674    __attribute__((format(__printf__, 1, 2), __unused__));
   3675 static int
   3676 VALGRIND_PRINTF(const char *format, ...)
   3677 {
   3678    unsigned long _qzz_res;
   3679    va_list vargs;
   3680    va_start(vargs, format);
   3681    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
   3682                               (unsigned long)format, (unsigned long)vargs,
   3683                               0, 0, 0);
   3684    va_end(vargs);
   3685    return (int)_qzz_res;
   3686 }
   3687 
   3688 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
   3689    __attribute__((format(__printf__, 1, 2), __unused__));
   3690 static int
   3691 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
   3692 {
   3693    unsigned long _qzz_res;
   3694    va_list vargs;
   3695    va_start(vargs, format);
   3696    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
   3697                               (unsigned long)format, (unsigned long)vargs,
   3698                               0, 0, 0);
   3699    va_end(vargs);
   3700    return (int)_qzz_res;
   3701 }
   3702 
   3703 #endif /* NVALGRIND */
   3704 
   3705 
   3706 /* These requests allow control to move from the simulated CPU to the
   3707    real CPU, calling an arbitary function.
   3708 
   3709    Note that the current ThreadId is inserted as the first argument.
   3710    So this call:
   3711 
   3712      VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
   3713 
   3714    requires f to have this signature:
   3715 
   3716      Word f(Word tid, Word arg1, Word arg2)
   3717 
   3718    where "Word" is a word-sized type.
   3719 
   3720    Note that these client requests are not entirely reliable.  For example,
   3721    if you call a function with them that subsequently calls printf(),
   3722    there's a high chance Valgrind will crash.  Generally, your prospects of
   3723    these working are made higher if the called function does not refer to
   3724    any global variables, and does not refer to any libc or other functions
   3725    (printf et al).  Any kind of entanglement with libc or dynamic linking is
   3726    likely to have a bad outcome, for tricky reasons which we've grappled
   3727    with a lot in the past.
   3728 */
   3729 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn)                          \
   3730    __extension__                                                  \
   3731    ({unsigned long _qyy_res;                                      \
   3732     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
   3733                                VG_USERREQ__CLIENT_CALL0,          \
   3734                                _qyy_fn,                           \
   3735                                0, 0, 0, 0);                       \
   3736     _qyy_res;                                                     \
   3737    })
   3738 
   3739 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1)               \
   3740    __extension__                                                  \
   3741    ({unsigned long _qyy_res;                                      \
   3742     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
   3743                                VG_USERREQ__CLIENT_CALL1,          \
   3744                                _qyy_fn,                           \
   3745                                _qyy_arg1, 0, 0, 0);               \
   3746     _qyy_res;                                                     \
   3747    })
   3748 
   3749 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2)    \
   3750    __extension__                                                  \
   3751    ({unsigned long _qyy_res;                                      \
   3752     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
   3753                                VG_USERREQ__CLIENT_CALL2,          \
   3754                                _qyy_fn,                           \
   3755                                _qyy_arg1, _qyy_arg2, 0, 0);       \
   3756     _qyy_res;                                                     \
   3757    })
   3758 
   3759 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
   3760    __extension__                                                  \
   3761    ({unsigned long _qyy_res;                                      \
   3762     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
   3763                                VG_USERREQ__CLIENT_CALL3,          \
   3764                                _qyy_fn,                           \
   3765                                _qyy_arg1, _qyy_arg2,              \
   3766                                _qyy_arg3, 0);                     \
   3767     _qyy_res;                                                     \
   3768    })
   3769 
   3770 
   3771 /* Counts the number of errors that have been recorded by a tool.  Nb:
   3772    the tool must record the errors with VG_(maybe_record_error)() or
   3773    VG_(unique_error)() for them to be counted. */
   3774 #define VALGRIND_COUNT_ERRORS                                     \
   3775    __extension__                                                  \
   3776    ({unsigned int _qyy_res;                                       \
   3777     VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */,  \
   3778                                VG_USERREQ__COUNT_ERRORS,          \
   3779                                0, 0, 0, 0, 0);                    \
   3780     _qyy_res;                                                     \
   3781    })
   3782 
   3783 /* Mark a block of memory as having been allocated by a malloc()-like
   3784    function.  `addr' is the start of the usable block (ie. after any
   3785    redzone) `rzB' is redzone size if the allocator can apply redzones;
   3786    use '0' if not.  Adding redzones makes it more likely Valgrind will spot
   3787    block overruns.  `is_zeroed' indicates if the memory is zeroed, as it is
   3788    for calloc().  Put it immediately after the point where a block is
   3789    allocated.
   3790 
   3791    If you're using Memcheck: If you're allocating memory via superblocks,
   3792    and then handing out small chunks of each superblock, if you don't have
   3793    redzones on your small blocks, it's worth marking the superblock with
   3794    VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
   3795    detected.  But if you can put redzones on, it's probably better to not do
   3796    this, so that messages for small overruns are described in terms of the
   3797    small block rather than the superblock (but if you have a big overrun
   3798    that skips over a redzone, you could miss an error this way).  See
   3799    memcheck/tests/custom_alloc.c for an example.
   3800 
   3801    WARNING: if your allocator uses malloc() or 'new' to allocate
   3802    superblocks, rather than mmap() or brk(), this will not work properly --
   3803    you'll likely get assertion failures during leak detection.  This is
   3804    because Valgrind doesn't like seeing overlapping heap blocks.  Sorry.
   3805 
   3806    Nb: block must be freed via a free()-like function specified
   3807    with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
   3808 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)    \
   3809    {unsigned int _qzz_res;                                        \
   3810     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3811                                VG_USERREQ__MALLOCLIKE_BLOCK,      \
   3812                                addr, sizeB, rzB, is_zeroed, 0);   \
   3813    }
   3814 
   3815 /* Mark a block of memory as having been freed by a free()-like function.
   3816    `rzB' is redzone size;  it must match that given to
   3817    VALGRIND_MALLOCLIKE_BLOCK.  Memory not freed will be detected by the leak
   3818    checker.  Put it immediately after the point where the block is freed. */
   3819 #define VALGRIND_FREELIKE_BLOCK(addr, rzB)                        \
   3820    {unsigned int _qzz_res;                                        \
   3821     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3822                                VG_USERREQ__FREELIKE_BLOCK,        \
   3823                                addr, rzB, 0, 0, 0);               \
   3824    }
   3825 
   3826 /* Create a memory pool. */
   3827 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)             \
   3828    {unsigned int _qzz_res;                                        \
   3829     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3830                                VG_USERREQ__CREATE_MEMPOOL,        \
   3831                                pool, rzB, is_zeroed, 0, 0);       \
   3832    }
   3833 
   3834 /* Destroy a memory pool. */
   3835 #define VALGRIND_DESTROY_MEMPOOL(pool)                            \
   3836    {unsigned int _qzz_res;                                        \
   3837     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3838                                VG_USERREQ__DESTROY_MEMPOOL,       \
   3839                                pool, 0, 0, 0, 0);                 \
   3840    }
   3841 
   3842 /* Associate a piece of memory with a memory pool. */
   3843 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)                  \
   3844    {unsigned int _qzz_res;                                        \
   3845     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3846                                VG_USERREQ__MEMPOOL_ALLOC,         \
   3847                                pool, addr, size, 0, 0);           \
   3848    }
   3849 
   3850 /* Disassociate a piece of memory from a memory pool. */
   3851 #define VALGRIND_MEMPOOL_FREE(pool, addr)                         \
   3852    {unsigned int _qzz_res;                                        \
   3853     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3854                                VG_USERREQ__MEMPOOL_FREE,          \
   3855                                pool, addr, 0, 0, 0);              \
   3856    }
   3857 
   3858 /* Disassociate any pieces outside a particular range. */
   3859 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size)                   \
   3860    {unsigned int _qzz_res;                                        \
   3861     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3862                                VG_USERREQ__MEMPOOL_TRIM,          \
   3863                                pool, addr, size, 0, 0);           \
   3864    }
   3865 
   3866 /* Resize and/or move a piece associated with a memory pool. */
   3867 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB)                       \
   3868    {unsigned int _qzz_res;                                        \
   3869     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3870                                VG_USERREQ__MOVE_MEMPOOL,          \
   3871                                poolA, poolB, 0, 0, 0);            \
   3872    }
   3873 
   3874 /* Resize and/or move a piece associated with a memory pool. */
   3875 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size)         \
   3876    {unsigned int _qzz_res;                                        \
   3877     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3878                                VG_USERREQ__MEMPOOL_CHANGE,        \
   3879                                pool, addrA, addrB, size, 0);      \
   3880    }
   3881 
   3882 /* Return 1 if a mempool exists, else 0. */
   3883 #define VALGRIND_MEMPOOL_EXISTS(pool)                             \
   3884    ({unsigned int _qzz_res;                                       \
   3885     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3886                                VG_USERREQ__MEMPOOL_EXISTS,        \
   3887                                pool, 0, 0, 0, 0);                 \
   3888     _qzz_res;                                                     \
   3889    })
   3890 
   3891 /* Mark a piece of memory as being a stack. Returns a stack id. */
   3892 #define VALGRIND_STACK_REGISTER(start, end)                       \
   3893    ({unsigned int _qzz_res;                                       \
   3894     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3895                                VG_USERREQ__STACK_REGISTER,        \
   3896                                start, end, 0, 0, 0);              \
   3897     _qzz_res;                                                     \
   3898    })
   3899 
   3900 /* Unmark the piece of memory associated with a stack id as being a
   3901    stack. */
   3902 #define VALGRIND_STACK_DEREGISTER(id)                             \
   3903    {unsigned int _qzz_res;                                        \
   3904     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3905                                VG_USERREQ__STACK_DEREGISTER,      \
   3906                                id, 0, 0, 0, 0);                   \
   3907    }
   3908 
   3909 /* Change the start and end address of the stack id. */
   3910 #define VALGRIND_STACK_CHANGE(id, start, end)                     \
   3911    {unsigned int _qzz_res;                                        \
   3912     VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
   3913                                VG_USERREQ__STACK_CHANGE,          \
   3914                                id, start, end, 0, 0);             \
   3915    }
   3916 
   3917 
   3918 #undef PLAT_x86_linux
   3919 #undef PLAT_amd64_linux
   3920 #undef PLAT_ppc32_linux
   3921 #undef PLAT_ppc64_linux
   3922 #undef PLAT_ppc32_aix5
   3923 #undef PLAT_ppc64_aix5
   3924 
   3925 #endif   /* __VALGRIND_H */
   3926