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