File indexing completed on 2024-04-14 03:49:44

0001 /* -*- c -*-
0002    ----------------------------------------------------------------
0003 
0004    This file is part of Valgrind, a dynamic binary instrumentation
0005    framework.
0006 
0007    SPDX-FileCopyrightText: 2000-2017 Julian Seward. All rights reserved.
0008 
0009    SPDX-License-Identifier: bzip2-1.0.6
0010 
0011    ---------------------------------------------------------------- 
0012 */
0013 
0014 
0015 /* This file is for inclusion into client (your!) code.
0016 
0017    You can use these macros to manipulate and query Valgrind's 
0018    execution inside your own programs.
0019 
0020    The resulting executables will still run without Valgrind, just a
0021    little bit more slowly than they otherwise would, but otherwise
0022    unchanged.  When not running on valgrind, each client request
0023    consumes very few (eg. 7) instructions, so the resulting performance
0024    loss is negligible unless you plan to execute client requests
0025    millions of times per second.  Nevertheless, if that is still a
0026    problem, you can compile with the NVALGRIND symbol defined (gcc
0027    -DNVALGRIND) so that client requests are not even compiled in.  */
0028 
0029 #ifndef __VALGRIND_H
0030 #define __VALGRIND_H
0031 
0032 
0033 /* ------------------------------------------------------------------ */
0034 /* VERSION NUMBER OF VALGRIND                                         */
0035 /* ------------------------------------------------------------------ */
0036 
0037 /* Specify Valgrind's version number, so that user code can
0038    conditionally compile based on our version number.  Note that these
0039    were introduced at version 3.6 and so do not exist in version 3.5
0040    or earlier.  The recommended way to use them to check for "version
0041    X.Y or later" is (eg)
0042 
0043 #if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__)   \
0044     && (__VALGRIND_MAJOR__ > 3                                   \
0045         || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
0046 */
0047 #define __VALGRIND_MAJOR__    3
0048 #define __VALGRIND_MINOR__    14
0049 
0050 
0051 #include <stdarg.h>
0052 
0053 /* Nb: this file might be included in a file compiled with -ansi.  So
0054    we can't use C++ style "//" comments nor the "asm" keyword (instead
0055    use "__asm__"). */
0056 
0057 /* Derive some tags indicating what the target platform is.  Note
0058    that in this file we're using the compiler's CPP symbols for
0059    identifying architectures, which are different to the ones we use
0060    within the rest of Valgrind.  Note, __powerpc__ is active for both
0061    32 and 64-bit PPC, whereas __powerpc64__ is only active for the
0062    latter (on Linux, that is).
0063 
0064    Misc note: how to find out what's predefined in gcc by default:
0065    gcc -Wp,-dM somefile.c
0066 */
0067 #undef PLAT_x86_darwin
0068 #undef PLAT_amd64_darwin
0069 #undef PLAT_x86_win32
0070 #undef PLAT_amd64_win64
0071 #undef PLAT_x86_linux
0072 #undef PLAT_amd64_linux
0073 #undef PLAT_ppc32_linux
0074 #undef PLAT_ppc64be_linux
0075 #undef PLAT_ppc64le_linux
0076 #undef PLAT_arm_linux
0077 #undef PLAT_arm64_linux
0078 #undef PLAT_s390x_linux
0079 #undef PLAT_mips32_linux
0080 #undef PLAT_mips64_linux
0081 #undef PLAT_x86_solaris
0082 #undef PLAT_amd64_solaris
0083 
0084 
0085 #if defined(__APPLE__) && defined(__i386__)
0086 #  define PLAT_x86_darwin 1
0087 #elif defined(__APPLE__) && defined(__x86_64__)
0088 #  define PLAT_amd64_darwin 1
0089 #elif (defined(__MINGW32__) && !defined(__MINGW64__)) \
0090       || defined(__CYGWIN32__) \
0091       || (defined(_WIN32) && defined(_M_IX86))
0092 #  define PLAT_x86_win32 1
0093 #elif defined(__MINGW64__) \
0094       || (defined(_WIN64) && defined(_M_X64))
0095 #  define PLAT_amd64_win64 1
0096 #elif defined(__linux__) && defined(__i386__)
0097 #  define PLAT_x86_linux 1
0098 #elif defined(__linux__) && defined(__x86_64__) && !defined(__ILP32__)
0099 #  define PLAT_amd64_linux 1
0100 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
0101 #  define PLAT_ppc32_linux 1
0102 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
0103 /* Big Endian uses ELF version 1 */
0104 #  define PLAT_ppc64be_linux 1
0105 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2
0106 /* Little Endian uses ELF version 2 */
0107 #  define PLAT_ppc64le_linux 1
0108 #elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
0109 #  define PLAT_arm_linux 1
0110 #elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
0111 #  define PLAT_arm64_linux 1
0112 #elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
0113 #  define PLAT_s390x_linux 1
0114 #elif defined(__linux__) && defined(__mips__) && (__mips==64)
0115 #  define PLAT_mips64_linux 1
0116 #elif defined(__linux__) && defined(__mips__) && (__mips!=64)
0117 #  define PLAT_mips32_linux 1
0118 #elif defined(__sun) && defined(__i386__)
0119 #  define PLAT_x86_solaris 1
0120 #elif defined(__sun) && defined(__x86_64__)
0121 #  define PLAT_amd64_solaris 1
0122 #else
0123 /* If we're not compiling for our target platform, don't generate
0124    any inline asms.  */
0125 #  if !defined(NVALGRIND)
0126 #    define NVALGRIND 1
0127 #  endif
0128 #endif
0129 
0130 
0131 /* ------------------------------------------------------------------ */
0132 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS.  There is nothing */
0133 /* in here of use to end-users -- skip to the next section.           */
0134 /* ------------------------------------------------------------------ */
0135 
0136 /*
0137  * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
0138  * request. Accepts both pointers and integers as arguments.
0139  *
0140  * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
0141  * client request that does not return a value.
0142 
0143  * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
0144  * client request and whose value equals the client request result.  Accepts
0145  * both pointers and integers as arguments.  Note that such calls are not
0146  * necessarily pure functions -- they may have side effects.
0147  */
0148 
0149 #define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default,            \
0150                                    _zzq_request, _zzq_arg1, _zzq_arg2,  \
0151                                    _zzq_arg3, _zzq_arg4, _zzq_arg5)     \
0152   do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default),   \
0153                         (_zzq_request), (_zzq_arg1), (_zzq_arg2),       \
0154                         (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
0155 
0156 #define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1,        \
0157                            _zzq_arg2,  _zzq_arg3, _zzq_arg4, _zzq_arg5) \
0158   do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                        \
0159                     (_zzq_request), (_zzq_arg1), (_zzq_arg2),           \
0160                     (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
0161 
0162 #if defined(NVALGRIND)
0163 
0164 /* Define NVALGRIND to completely remove the Valgrind magic sequence
0165    from the compiled code (analogous to NDEBUG's effects on
0166    assert()) */
0167 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0168         _zzq_default, _zzq_request,                               \
0169         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0170       (_zzq_default)
0171 
0172 #else  /* ! NVALGRIND */
0173 
0174 /* The following defines the magic code sequences which the JITter
0175    spots and handles magically.  Don't look too closely at them as
0176    they will rot your brain.
0177 
0178    The assembly code sequences for all architectures is in this one
0179    file.  This is because this file must be stand-alone, and we don't
0180    want to have multiple files.
0181 
0182    For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
0183    value gets put in the return slot, so that everything works when
0184    this is executed not under Valgrind.  Args are passed in a memory
0185    block, and so there's no intrinsic limit to the number that could
0186    be passed, but it's currently five.
0187    
0188    The macro args are: 
0189       _zzq_rlval    result lvalue
0190       _zzq_default  default value (result returned when running on real CPU)
0191       _zzq_request  request code
0192       _zzq_arg1..5  request params
0193 
0194    The other two macros are used to support function wrapping, and are
0195    a lot simpler.  VALGRIND_GET_NR_CONTEXT returns the value of the
0196    guest's NRADDR pseudo-register and whatever other information is
0197    needed to safely run the call original from the wrapper: on
0198    ppc64-linux, the R2 value at the divert point is also needed.  This
0199    information is abstracted into a user-visible type, OrigFn.
0200 
0201    VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
0202    guest, but guarantees that the branch instruction will not be
0203    redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
0204    branch-and-link-to-r11.  VALGRIND_CALL_NOREDIR is just text, not a
0205    complete inline asm, since it needs to be combined with more magic
0206    inline asm stuff to be useful.
0207 */
0208 
0209 /* ----------------- x86-{linux,darwin,solaris} ---------------- */
0210 
0211 #if defined(PLAT_x86_linux)  ||  defined(PLAT_x86_darwin)  \
0212     ||  (defined(PLAT_x86_win32) && defined(__GNUC__)) \
0213     ||  defined(PLAT_x86_solaris)
0214 
0215 typedef
0216    struct { 
0217       unsigned int nraddr; /* where's the code? */
0218    }
0219    OrigFn;
0220 
0221 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0222                      "roll $3,  %%edi ; roll $13, %%edi\n\t"      \
0223                      "roll $29, %%edi ; roll $19, %%edi\n\t"
0224 
0225 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0226         _zzq_default, _zzq_request,                               \
0227         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0228   __extension__                                                   \
0229   ({volatile unsigned int _zzq_args[6];                           \
0230     volatile unsigned int _zzq_result;                            \
0231     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
0232     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
0233     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
0234     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
0235     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
0236     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
0237     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0238                      /* %EDX = client_request ( %EAX ) */         \
0239                      "xchgl %%ebx,%%ebx"                          \
0240                      : "=d" (_zzq_result)                         \
0241                      : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
0242                      : "cc", "memory"                             \
0243                     );                                            \
0244     _zzq_result;                                                  \
0245   })
0246 
0247 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0248   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0249     volatile unsigned int __addr;                                 \
0250     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0251                      /* %EAX = guest_NRADDR */                    \
0252                      "xchgl %%ecx,%%ecx"                          \
0253                      : "=a" (__addr)                              \
0254                      :                                            \
0255                      : "cc", "memory"                             \
0256                     );                                            \
0257     _zzq_orig->nraddr = __addr;                                   \
0258   }
0259 
0260 #define VALGRIND_CALL_NOREDIR_EAX                                 \
0261                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0262                      /* call-noredir *%EAX */                     \
0263                      "xchgl %%edx,%%edx\n\t"
0264 
0265 #define VALGRIND_VEX_INJECT_IR()                                 \
0266  do {                                                            \
0267     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0268                      "xchgl %%edi,%%edi\n\t"                     \
0269                      : : : "cc", "memory"                        \
0270                     );                                           \
0271  } while (0)
0272 
0273 #endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__)
0274           || PLAT_x86_solaris */
0275 
0276 /* ------------------------- x86-Win32 ------------------------- */
0277 
0278 #if defined(PLAT_x86_win32) && !defined(__GNUC__)
0279 
0280 typedef
0281    struct { 
0282       unsigned int nraddr; /* where's the code? */
0283    }
0284    OrigFn;
0285 
0286 #if defined(_MSC_VER)
0287 
0288 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0289                      __asm rol edi, 3  __asm rol edi, 13          \
0290                      __asm rol edi, 29 __asm rol edi, 19
0291 
0292 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0293         _zzq_default, _zzq_request,                               \
0294         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0295     valgrind_do_client_request_expr((uintptr_t)(_zzq_default),    \
0296         (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1),        \
0297         (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3),           \
0298         (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
0299 
0300 static __inline uintptr_t
0301 valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
0302                                 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
0303                                 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
0304                                 uintptr_t _zzq_arg5)
0305 {
0306     volatile uintptr_t _zzq_args[6];
0307     volatile unsigned int _zzq_result;
0308     _zzq_args[0] = (uintptr_t)(_zzq_request);
0309     _zzq_args[1] = (uintptr_t)(_zzq_arg1);
0310     _zzq_args[2] = (uintptr_t)(_zzq_arg2);
0311     _zzq_args[3] = (uintptr_t)(_zzq_arg3);
0312     _zzq_args[4] = (uintptr_t)(_zzq_arg4);
0313     _zzq_args[5] = (uintptr_t)(_zzq_arg5);
0314     __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
0315             __SPECIAL_INSTRUCTION_PREAMBLE
0316             /* %EDX = client_request ( %EAX ) */
0317             __asm xchg ebx,ebx
0318             __asm mov _zzq_result, edx
0319     }
0320     return _zzq_result;
0321 }
0322 
0323 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0324   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0325     volatile unsigned int __addr;                                 \
0326     __asm { __SPECIAL_INSTRUCTION_PREAMBLE                        \
0327             /* %EAX = guest_NRADDR */                             \
0328             __asm xchg ecx,ecx                                    \
0329             __asm mov __addr, eax                                 \
0330     }                                                             \
0331     _zzq_orig->nraddr = __addr;                                   \
0332   }
0333 
0334 #define VALGRIND_CALL_NOREDIR_EAX ERROR
0335 
0336 #define VALGRIND_VEX_INJECT_IR()                                 \
0337  do {                                                            \
0338     __asm { __SPECIAL_INSTRUCTION_PREAMBLE                       \
0339             __asm xchg edi,edi                                   \
0340     }                                                            \
0341  } while (0)
0342 
0343 #else
0344 #error Unsupported compiler.
0345 #endif
0346 
0347 #endif /* PLAT_x86_win32 */
0348 
0349 /* ----------------- amd64-{linux,darwin,solaris} --------------- */
0350 
0351 #if defined(PLAT_amd64_linux)  ||  defined(PLAT_amd64_darwin) \
0352     ||  defined(PLAT_amd64_solaris) \
0353     ||  (defined(PLAT_amd64_win64) && defined(__GNUC__))
0354 
0355 typedef
0356    struct { 
0357       unsigned long int nraddr; /* where's the code? */
0358    }
0359    OrigFn;
0360 
0361 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0362                      "rolq $3,  %%rdi ; rolq $13, %%rdi\n\t"      \
0363                      "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
0364 
0365 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0366         _zzq_default, _zzq_request,                               \
0367         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0368     __extension__                                                 \
0369     ({ volatile unsigned long int _zzq_args[6];                   \
0370     volatile unsigned long int _zzq_result;                       \
0371     _zzq_args[0] = (unsigned long int)(_zzq_request);             \
0372     _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
0373     _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
0374     _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
0375     _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
0376     _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
0377     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0378                      /* %RDX = client_request ( %RAX ) */         \
0379                      "xchgq %%rbx,%%rbx"                          \
0380                      : "=d" (_zzq_result)                         \
0381                      : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
0382                      : "cc", "memory"                             \
0383                     );                                            \
0384     _zzq_result;                                                  \
0385     })
0386 
0387 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0388   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0389     volatile unsigned long int __addr;                            \
0390     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0391                      /* %RAX = guest_NRADDR */                    \
0392                      "xchgq %%rcx,%%rcx"                          \
0393                      : "=a" (__addr)                              \
0394                      :                                            \
0395                      : "cc", "memory"                             \
0396                     );                                            \
0397     _zzq_orig->nraddr = __addr;                                   \
0398   }
0399 
0400 #define VALGRIND_CALL_NOREDIR_RAX                                 \
0401                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0402                      /* call-noredir *%RAX */                     \
0403                      "xchgq %%rdx,%%rdx\n\t"
0404 
0405 #define VALGRIND_VEX_INJECT_IR()                                 \
0406  do {                                                            \
0407     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0408                      "xchgq %%rdi,%%rdi\n\t"                     \
0409                      : : : "cc", "memory"                        \
0410                     );                                           \
0411  } while (0)
0412 
0413 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
0414 
0415 /* ------------------------- amd64-Win64 ------------------------- */
0416 
0417 #if defined(PLAT_amd64_win64) && !defined(__GNUC__)
0418 
0419 #error Unsupported compiler.
0420 
0421 #endif /* PLAT_amd64_win64 */
0422 
0423 /* ------------------------ ppc32-linux ------------------------ */
0424 
0425 #if defined(PLAT_ppc32_linux)
0426 
0427 typedef
0428    struct { 
0429       unsigned int nraddr; /* where's the code? */
0430    }
0431    OrigFn;
0432 
0433 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0434                     "rlwinm 0,0,3,0,31  ; rlwinm 0,0,13,0,31\n\t" \
0435                     "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
0436 
0437 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0438         _zzq_default, _zzq_request,                               \
0439         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0440                                                                   \
0441     __extension__                                                 \
0442   ({         unsigned int  _zzq_args[6];                          \
0443              unsigned int  _zzq_result;                           \
0444              unsigned int* _zzq_ptr;                              \
0445     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
0446     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
0447     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
0448     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
0449     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
0450     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
0451     _zzq_ptr = _zzq_args;                                         \
0452     __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
0453                      "mr 4,%2\n\t" /*ptr*/                        \
0454                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0455                      /* %R3 = client_request ( %R4 ) */           \
0456                      "or 1,1,1\n\t"                               \
0457                      "mr %0,3"     /*result*/                     \
0458                      : "=b" (_zzq_result)                         \
0459                      : "b" (_zzq_default), "b" (_zzq_ptr)         \
0460                      : "cc", "memory", "r3", "r4");               \
0461     _zzq_result;                                                  \
0462     })
0463 
0464 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0465   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0466     unsigned int __addr;                                          \
0467     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0468                      /* %R3 = guest_NRADDR */                     \
0469                      "or 2,2,2\n\t"                               \
0470                      "mr %0,3"                                    \
0471                      : "=b" (__addr)                              \
0472                      :                                            \
0473                      : "cc", "memory", "r3"                       \
0474                     );                                            \
0475     _zzq_orig->nraddr = __addr;                                   \
0476   }
0477 
0478 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
0479                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0480                      /* branch-and-link-to-noredir *%R11 */       \
0481                      "or 3,3,3\n\t"
0482 
0483 #define VALGRIND_VEX_INJECT_IR()                                 \
0484  do {                                                            \
0485     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0486                      "or 5,5,5\n\t"                              \
0487                     );                                           \
0488  } while (0)
0489 
0490 #endif /* PLAT_ppc32_linux */
0491 
0492 /* ------------------------ ppc64-linux ------------------------ */
0493 
0494 #if defined(PLAT_ppc64be_linux)
0495 
0496 typedef
0497    struct { 
0498       unsigned long int nraddr; /* where's the code? */
0499       unsigned long int r2;  /* what tocptr do we need? */
0500    }
0501    OrigFn;
0502 
0503 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0504                      "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
0505                      "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
0506 
0507 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0508         _zzq_default, _zzq_request,                               \
0509         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0510                                                                   \
0511   __extension__                                                   \
0512   ({         unsigned long int  _zzq_args[6];                     \
0513              unsigned long int  _zzq_result;                      \
0514              unsigned long int* _zzq_ptr;                         \
0515     _zzq_args[0] = (unsigned long int)(_zzq_request);             \
0516     _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
0517     _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
0518     _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
0519     _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
0520     _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
0521     _zzq_ptr = _zzq_args;                                         \
0522     __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
0523                      "mr 4,%2\n\t" /*ptr*/                        \
0524                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0525                      /* %R3 = client_request ( %R4 ) */           \
0526                      "or 1,1,1\n\t"                               \
0527                      "mr %0,3"     /*result*/                     \
0528                      : "=b" (_zzq_result)                         \
0529                      : "b" (_zzq_default), "b" (_zzq_ptr)         \
0530                      : "cc", "memory", "r3", "r4");               \
0531     _zzq_result;                                                  \
0532   })
0533 
0534 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0535   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0536     unsigned long int __addr;                                     \
0537     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0538                      /* %R3 = guest_NRADDR */                     \
0539                      "or 2,2,2\n\t"                               \
0540                      "mr %0,3"                                    \
0541                      : "=b" (__addr)                              \
0542                      :                                            \
0543                      : "cc", "memory", "r3"                       \
0544                     );                                            \
0545     _zzq_orig->nraddr = __addr;                                   \
0546     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0547                      /* %R3 = guest_NRADDR_GPR2 */                \
0548                      "or 4,4,4\n\t"                               \
0549                      "mr %0,3"                                    \
0550                      : "=b" (__addr)                              \
0551                      :                                            \
0552                      : "cc", "memory", "r3"                       \
0553                     );                                            \
0554     _zzq_orig->r2 = __addr;                                       \
0555   }
0556 
0557 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
0558                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0559                      /* branch-and-link-to-noredir *%R11 */       \
0560                      "or 3,3,3\n\t"
0561 
0562 #define VALGRIND_VEX_INJECT_IR()                                 \
0563  do {                                                            \
0564     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0565                      "or 5,5,5\n\t"                              \
0566                     );                                           \
0567  } while (0)
0568 
0569 #endif /* PLAT_ppc64be_linux */
0570 
0571 #if defined(PLAT_ppc64le_linux)
0572 
0573 typedef
0574    struct {
0575       unsigned long int nraddr; /* where's the code? */
0576       unsigned long int r2;     /* what tocptr do we need? */
0577    }
0578    OrigFn;
0579 
0580 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0581                      "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
0582                      "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
0583 
0584 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0585         _zzq_default, _zzq_request,                               \
0586         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0587                                                                   \
0588   __extension__                                                   \
0589   ({         unsigned long int  _zzq_args[6];                     \
0590              unsigned long int  _zzq_result;                      \
0591              unsigned long int* _zzq_ptr;                         \
0592     _zzq_args[0] = (unsigned long int)(_zzq_request);             \
0593     _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
0594     _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
0595     _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
0596     _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
0597     _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
0598     _zzq_ptr = _zzq_args;                                         \
0599     __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
0600                      "mr 4,%2\n\t" /*ptr*/                        \
0601                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0602                      /* %R3 = client_request ( %R4 ) */           \
0603                      "or 1,1,1\n\t"                               \
0604                      "mr %0,3"     /*result*/                     \
0605                      : "=b" (_zzq_result)                         \
0606                      : "b" (_zzq_default), "b" (_zzq_ptr)         \
0607                      : "cc", "memory", "r3", "r4");               \
0608     _zzq_result;                                                  \
0609   })
0610 
0611 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0612   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0613     unsigned long int __addr;                                     \
0614     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0615                      /* %R3 = guest_NRADDR */                     \
0616                      "or 2,2,2\n\t"                               \
0617                      "mr %0,3"                                    \
0618                      : "=b" (__addr)                              \
0619                      :                                            \
0620                      : "cc", "memory", "r3"                       \
0621                     );                                            \
0622     _zzq_orig->nraddr = __addr;                                   \
0623     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0624                      /* %R3 = guest_NRADDR_GPR2 */                \
0625                      "or 4,4,4\n\t"                               \
0626                      "mr %0,3"                                    \
0627                      : "=b" (__addr)                              \
0628                      :                                            \
0629                      : "cc", "memory", "r3"                       \
0630                     );                                            \
0631     _zzq_orig->r2 = __addr;                                       \
0632   }
0633 
0634 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                   \
0635                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0636                      /* branch-and-link-to-noredir *%R12 */       \
0637                      "or 3,3,3\n\t"
0638 
0639 #define VALGRIND_VEX_INJECT_IR()                                 \
0640  do {                                                            \
0641     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0642                      "or 5,5,5\n\t"                              \
0643                     );                                           \
0644  } while (0)
0645 
0646 #endif /* PLAT_ppc64le_linux */
0647 
0648 /* ------------------------- arm-linux ------------------------- */
0649 
0650 #if defined(PLAT_arm_linux)
0651 
0652 typedef
0653    struct { 
0654       unsigned int nraddr; /* where's the code? */
0655    }
0656    OrigFn;
0657 
0658 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0659             "mov r12, r12, ror #3  ; mov r12, r12, ror #13 \n\t"  \
0660             "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
0661 
0662 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0663         _zzq_default, _zzq_request,                               \
0664         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0665                                                                   \
0666   __extension__                                                   \
0667   ({volatile unsigned int  _zzq_args[6];                          \
0668     volatile unsigned int  _zzq_result;                           \
0669     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
0670     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
0671     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
0672     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
0673     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
0674     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
0675     __asm__ volatile("mov r3, %1\n\t" /*default*/                 \
0676                      "mov r4, %2\n\t" /*ptr*/                     \
0677                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0678                      /* R3 = client_request ( R4 ) */             \
0679                      "orr r10, r10, r10\n\t"                      \
0680                      "mov %0, r3"     /*result*/                  \
0681                      : "=r" (_zzq_result)                         \
0682                      : "r" (_zzq_default), "r" (&_zzq_args[0])    \
0683                      : "cc","memory", "r3", "r4");                \
0684     _zzq_result;                                                  \
0685   })
0686 
0687 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0688   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0689     unsigned int __addr;                                          \
0690     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0691                      /* R3 = guest_NRADDR */                      \
0692                      "orr r11, r11, r11\n\t"                      \
0693                      "mov %0, r3"                                 \
0694                      : "=r" (__addr)                              \
0695                      :                                            \
0696                      : "cc", "memory", "r3"                       \
0697                     );                                            \
0698     _zzq_orig->nraddr = __addr;                                   \
0699   }
0700 
0701 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                    \
0702                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0703                      /* branch-and-link-to-noredir *%R4 */        \
0704                      "orr r12, r12, r12\n\t"
0705 
0706 #define VALGRIND_VEX_INJECT_IR()                                 \
0707  do {                                                            \
0708     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0709                      "orr r9, r9, r9\n\t"                        \
0710                      : : : "cc", "memory"                        \
0711                     );                                           \
0712  } while (0)
0713 
0714 #endif /* PLAT_arm_linux */
0715 
0716 /* ------------------------ arm64-linux ------------------------- */
0717 
0718 #if defined(PLAT_arm64_linux)
0719 
0720 typedef
0721    struct { 
0722       unsigned long int nraddr; /* where's the code? */
0723    }
0724    OrigFn;
0725 
0726 #define __SPECIAL_INSTRUCTION_PREAMBLE                            \
0727             "ror x12, x12, #3  ;  ror x12, x12, #13 \n\t"         \
0728             "ror x12, x12, #51 ;  ror x12, x12, #61 \n\t"
0729 
0730 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0731         _zzq_default, _zzq_request,                               \
0732         _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0733                                                                   \
0734   __extension__                                                   \
0735   ({volatile unsigned long int  _zzq_args[6];                     \
0736     volatile unsigned long int  _zzq_result;                      \
0737     _zzq_args[0] = (unsigned long int)(_zzq_request);             \
0738     _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
0739     _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
0740     _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
0741     _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
0742     _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
0743     __asm__ volatile("mov x3, %1\n\t" /*default*/                 \
0744                      "mov x4, %2\n\t" /*ptr*/                     \
0745                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0746                      /* X3 = client_request ( X4 ) */             \
0747                      "orr x10, x10, x10\n\t"                      \
0748                      "mov %0, x3"     /*result*/                  \
0749                      : "=r" (_zzq_result)                         \
0750                      : "r" ((unsigned long int)(_zzq_default)),   \
0751                        "r" (&_zzq_args[0])                        \
0752                      : "cc","memory", "x3", "x4");                \
0753     _zzq_result;                                                  \
0754   })
0755 
0756 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0757   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0758     unsigned long int __addr;                                     \
0759     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0760                      /* X3 = guest_NRADDR */                      \
0761                      "orr x11, x11, x11\n\t"                      \
0762                      "mov %0, x3"                                 \
0763                      : "=r" (__addr)                              \
0764                      :                                            \
0765                      : "cc", "memory", "x3"                       \
0766                     );                                            \
0767     _zzq_orig->nraddr = __addr;                                   \
0768   }
0769 
0770 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                    \
0771                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0772                      /* branch-and-link-to-noredir X8 */          \
0773                      "orr x12, x12, x12\n\t"
0774 
0775 #define VALGRIND_VEX_INJECT_IR()                                 \
0776  do {                                                            \
0777     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0778                      "orr x9, x9, x9\n\t"                        \
0779                      : : : "cc", "memory"                        \
0780                     );                                           \
0781  } while (0)
0782 
0783 #endif /* PLAT_arm64_linux */
0784 
0785 /* ------------------------ s390x-linux ------------------------ */
0786 
0787 #if defined(PLAT_s390x_linux)
0788 
0789 typedef
0790   struct {
0791      unsigned long int nraddr; /* where's the code? */
0792   }
0793   OrigFn;
0794 
0795 /* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
0796  * code. This detection is implemented in platform specific toIR.c
0797  * (e.g. VEX/priv/guest_s390_decoder.c).
0798  */
0799 #define __SPECIAL_INSTRUCTION_PREAMBLE                           \
0800                      "lr 15,15\n\t"                              \
0801                      "lr 1,1\n\t"                                \
0802                      "lr 2,2\n\t"                                \
0803                      "lr 3,3\n\t"
0804 
0805 #define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
0806 #define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
0807 #define __CALL_NO_REDIR_CODE  "lr 4,4\n\t"
0808 #define __VEX_INJECT_IR_CODE  "lr 5,5\n\t"
0809 
0810 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                         \
0811        _zzq_default, _zzq_request,                               \
0812        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
0813   __extension__                                                  \
0814  ({volatile unsigned long int _zzq_args[6];                      \
0815    volatile unsigned long int _zzq_result;                       \
0816    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
0817    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
0818    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
0819    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
0820    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
0821    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
0822    __asm__ volatile(/* r2 = args */                              \
0823                     "lgr 2,%1\n\t"                               \
0824                     /* r3 = default */                           \
0825                     "lgr 3,%2\n\t"                               \
0826                     __SPECIAL_INSTRUCTION_PREAMBLE               \
0827                     __CLIENT_REQUEST_CODE                        \
0828                     /* results = r3 */                           \
0829                     "lgr %0, 3\n\t"                              \
0830                     : "=d" (_zzq_result)                         \
0831                     : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
0832                     : "cc", "2", "3", "memory"                   \
0833                    );                                            \
0834    _zzq_result;                                                  \
0835  })
0836 
0837 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                      \
0838  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0839    volatile unsigned long int __addr;                            \
0840    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0841                     __GET_NR_CONTEXT_CODE                        \
0842                     "lgr %0, 3\n\t"                              \
0843                     : "=a" (__addr)                              \
0844                     :                                            \
0845                     : "cc", "3", "memory"                        \
0846                    );                                            \
0847    _zzq_orig->nraddr = __addr;                                   \
0848  }
0849 
0850 #define VALGRIND_CALL_NOREDIR_R1                                 \
0851                     __SPECIAL_INSTRUCTION_PREAMBLE               \
0852                     __CALL_NO_REDIR_CODE
0853 
0854 #define VALGRIND_VEX_INJECT_IR()                                 \
0855  do {                                                            \
0856     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0857                      __VEX_INJECT_IR_CODE);                      \
0858  } while (0)
0859 
0860 #endif /* PLAT_s390x_linux */
0861 
0862 /* ------------------------- mips32-linux ---------------- */
0863 
0864 #if defined(PLAT_mips32_linux)
0865 
0866 typedef
0867    struct { 
0868       unsigned int nraddr; /* where's the code? */
0869    }
0870    OrigFn;
0871 
0872 /* .word  0x342
0873  * .word  0x742
0874  * .word  0xC2
0875  * .word  0x4C2*/
0876 #define __SPECIAL_INSTRUCTION_PREAMBLE          \
0877                      "srl $0, $0, 13\n\t"       \
0878                      "srl $0, $0, 29\n\t"       \
0879                      "srl $0, $0, 3\n\t"        \
0880                      "srl $0, $0, 19\n\t"
0881                     
0882 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
0883        _zzq_default, _zzq_request,                                \
0884        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)     \
0885   __extension__                                                   \
0886   ({ volatile unsigned int _zzq_args[6];                          \
0887     volatile unsigned int _zzq_result;                            \
0888     _zzq_args[0] = (unsigned int)(_zzq_request);                  \
0889     _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
0890     _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
0891     _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
0892     _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
0893     _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
0894         __asm__ volatile("move $11, %1\n\t" /*default*/           \
0895                      "move $12, %2\n\t" /*ptr*/                   \
0896                      __SPECIAL_INSTRUCTION_PREAMBLE               \
0897                      /* T3 = client_request ( T4 ) */             \
0898                      "or $13, $13, $13\n\t"                       \
0899                      "move %0, $11\n\t"     /*result*/            \
0900                      : "=r" (_zzq_result)                         \
0901                      : "r" (_zzq_default), "r" (&_zzq_args[0])    \
0902                      : "$11", "$12", "memory");                   \
0903     _zzq_result;                                                  \
0904   })
0905 
0906 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
0907   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
0908     volatile unsigned int __addr;                                 \
0909     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
0910                      /* %t9 = guest_NRADDR */                     \
0911                      "or $14, $14, $14\n\t"                       \
0912                      "move %0, $11"     /*result*/                \
0913                      : "=r" (__addr)                              \
0914                      :                                            \
0915                      : "$11"                                      \
0916                     );                                            \
0917     _zzq_orig->nraddr = __addr;                                   \
0918   }
0919 
0920 #define VALGRIND_CALL_NOREDIR_T9                                 \
0921                      __SPECIAL_INSTRUCTION_PREAMBLE              \
0922                      /* call-noredir *%t9 */                     \
0923                      "or $15, $15, $15\n\t"
0924 
0925 #define VALGRIND_VEX_INJECT_IR()                                 \
0926  do {                                                            \
0927     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
0928                      "or $11, $11, $11\n\t"                      \
0929                     );                                           \
0930  } while (0)
0931 
0932 
0933 #endif /* PLAT_mips32_linux */
0934 
0935 /* ------------------------- mips64-linux ---------------- */
0936 
0937 #if defined(PLAT_mips64_linux)
0938 
0939 typedef
0940    struct {
0941       unsigned long nraddr; /* where's the code? */
0942    }
0943    OrigFn;
0944 
0945 /* dsll $0,$0, 3
0946  * dsll $0,$0, 13
0947  * dsll $0,$0, 29
0948  * dsll $0,$0, 19*/
0949 #define __SPECIAL_INSTRUCTION_PREAMBLE                              \
0950                      "dsll $0,$0, 3 ; dsll $0,$0,13\n\t"            \
0951                      "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
0952 
0953 #define VALGRIND_DO_CLIENT_REQUEST_EXPR(                            \
0954        _zzq_default, _zzq_request,                                  \
0955        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)       \
0956   __extension__                                                     \
0957   ({ volatile unsigned long int _zzq_args[6];                       \
0958     volatile unsigned long int _zzq_result;                         \
0959     _zzq_args[0] = (unsigned long int)(_zzq_request);               \
0960     _zzq_args[1] = (unsigned long int)(_zzq_arg1);                  \
0961     _zzq_args[2] = (unsigned long int)(_zzq_arg2);                  \
0962     _zzq_args[3] = (unsigned long int)(_zzq_arg3);                  \
0963     _zzq_args[4] = (unsigned long int)(_zzq_arg4);                  \
0964     _zzq_args[5] = (unsigned long int)(_zzq_arg5);                  \
0965         __asm__ volatile("move $11, %1\n\t" /*default*/             \
0966                          "move $12, %2\n\t" /*ptr*/                 \
0967                          __SPECIAL_INSTRUCTION_PREAMBLE             \
0968                          /* $11 = client_request ( $12 ) */         \
0969                          "or $13, $13, $13\n\t"                     \
0970                          "move %0, $11\n\t"     /*result*/          \
0971                          : "=r" (_zzq_result)                       \
0972                          : "r" (_zzq_default), "r" (&_zzq_args[0])  \
0973                          : "$11", "$12", "memory");                 \
0974     _zzq_result;                                                    \
0975   })
0976 
0977 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                         \
0978   { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                     \
0979     volatile unsigned long int __addr;                              \
0980     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
0981                      /* $11 = guest_NRADDR */                       \
0982                      "or $14, $14, $14\n\t"                         \
0983                      "move %0, $11"     /*result*/                  \
0984                      : "=r" (__addr)                                \
0985                      :                                              \
0986                      : "$11");                                      \
0987     _zzq_orig->nraddr = __addr;                                     \
0988   }
0989 
0990 #define VALGRIND_CALL_NOREDIR_T9                                    \
0991                      __SPECIAL_INSTRUCTION_PREAMBLE                 \
0992                      /* call-noredir $25 */                         \
0993                      "or $15, $15, $15\n\t"
0994 
0995 #define VALGRIND_VEX_INJECT_IR()                                    \
0996  do {                                                               \
0997     __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
0998                      "or $11, $11, $11\n\t"                         \
0999                     );                                              \
1000  } while (0)
1001 
1002 #endif /* PLAT_mips64_linux */
1003 
1004 /* Insert assembly code for other platforms here... */
1005 
1006 #endif /* NVALGRIND */
1007 
1008 
1009 /* ------------------------------------------------------------------ */
1010 /* PLATFORM SPECIFICS for FUNCTION WRAPPING.  This is all very        */
1011 /* ugly.  It's the least-worst tradeoff I can think of.               */
1012 /* ------------------------------------------------------------------ */
1013 
1014 /* This section defines magic (a.k.a appalling-hack) macros for doing
1015    guaranteed-no-redirection macros, so as to get from function
1016    wrappers to the functions they are wrapping.  The whole point is to
1017    construct standard call sequences, but to do the call itself with a
1018    special no-redirect call pseudo-instruction that the JIT
1019    understands and handles specially.  This section is long and
1020    repetitious, and I can't see a way to make it shorter.
1021 
1022    The naming scheme is as follows:
1023 
1024       CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
1025 
1026    'W' stands for "word" and 'v' for "void".  Hence there are
1027    different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
1028    and for each, the possibility of returning a word-typed result, or
1029    no result.
1030 */
1031 
1032 /* Use these to write the name of your wrapper.  NOTE: duplicates
1033    VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h.  NOTE also: inserts
1034    the default behavior equivalence class tag "0000" into the name.
1035    See pub_tool_redir.h for details -- normally you don't need to
1036    think about this, though. */
1037 
1038 /* Use an extra level of macroisation so as to ensure the soname/fnname
1039    args are fully macro-expanded before pasting them together. */
1040 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
1041 
1042 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname)                    \
1043    VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
1044 
1045 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname)                    \
1046    VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
1047 
1048 /* Use this macro from within a wrapper function to collect the
1049    context (address and possibly other info) of the original function.
1050    Once you have that you can then use it in one of the CALL_FN_
1051    macros.  The type of the argument _lval is OrigFn. */
1052 #define VALGRIND_GET_ORIG_FN(_lval)  VALGRIND_GET_NR_CONTEXT(_lval)
1053 
1054 /* Also provide end-user facilities for function replacement, rather
1055    than wrapping.  A replacement function differs from a wrapper in
1056    that it has no way to get hold of the original function being
1057    called, and hence no way to call onwards to it.  In a replacement
1058    function, VALGRIND_GET_ORIG_FN always returns zero. */
1059 
1060 #define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname)                 \
1061    VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1062 
1063 #define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname)                 \
1064    VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1065 
1066 /* Derivatives of the main macros below, for calling functions
1067    returning void. */
1068 
1069 #define CALL_FN_v_v(fnptr)                                        \
1070    do { volatile unsigned long _junk;                             \
1071         CALL_FN_W_v(_junk,fnptr); } while (0)
1072 
1073 #define CALL_FN_v_W(fnptr, arg1)                                  \
1074    do { volatile unsigned long _junk;                             \
1075         CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1076 
1077 #define CALL_FN_v_WW(fnptr, arg1,arg2)                            \
1078    do { volatile unsigned long _junk;                             \
1079         CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1080 
1081 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3)                      \
1082    do { volatile unsigned long _junk;                             \
1083         CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1084 
1085 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4)                \
1086    do { volatile unsigned long _junk;                             \
1087         CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1088 
1089 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5)             \
1090    do { volatile unsigned long _junk;                             \
1091         CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1092 
1093 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6)        \
1094    do { volatile unsigned long _junk;                             \
1095         CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1096 
1097 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7)   \
1098    do { volatile unsigned long _junk;                             \
1099         CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1100 
1101 /* ----------------- x86-{linux,darwin,solaris} ---------------- */
1102 
1103 #if defined(PLAT_x86_linux)  ||  defined(PLAT_x86_darwin) \
1104     ||  defined(PLAT_x86_solaris)
1105 
1106 /* These regs are trashed by the hidden call.  No need to mention eax
1107    as gcc can already see that, plus causes gcc to bomb. */
1108 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1109 
1110 /* Macros to save and align the stack before making a function
1111    call and restore it afterwards as gcc may not keep the stack
1112    pointer aligned if it doesn't realise calls are being made
1113    to other functions. */
1114 
1115 #define VALGRIND_ALIGN_STACK               \
1116       "movl %%esp,%%edi\n\t"               \
1117       "andl $0xfffffff0,%%esp\n\t"
1118 #define VALGRIND_RESTORE_STACK             \
1119       "movl %%edi,%%esp\n\t"
1120 
1121 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1122    long) == 4. */
1123 
1124 #define CALL_FN_W_v(lval, orig)                                   \
1125    do {                                                           \
1126       volatile OrigFn        _orig = (orig);                      \
1127       volatile unsigned long _argvec[1];                          \
1128       volatile unsigned long _res;                                \
1129       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1130       __asm__ volatile(                                           \
1131          VALGRIND_ALIGN_STACK                                     \
1132          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1133          VALGRIND_CALL_NOREDIR_EAX                                \
1134          VALGRIND_RESTORE_STACK                                   \
1135          : /*out*/   "=a" (_res)                                  \
1136          : /*in*/    "a" (&_argvec[0])                            \
1137          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1138       );                                                          \
1139       lval = (__typeof__(lval)) _res;                             \
1140    } while (0)
1141 
1142 #define CALL_FN_W_W(lval, orig, arg1)                             \
1143    do {                                                           \
1144       volatile OrigFn        _orig = (orig);                      \
1145       volatile unsigned long _argvec[2];                          \
1146       volatile unsigned long _res;                                \
1147       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1148       _argvec[1] = (unsigned long)(arg1);                         \
1149       __asm__ volatile(                                           \
1150          VALGRIND_ALIGN_STACK                                     \
1151          "subl $12, %%esp\n\t"                                    \
1152          "pushl 4(%%eax)\n\t"                                     \
1153          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1154          VALGRIND_CALL_NOREDIR_EAX                                \
1155          VALGRIND_RESTORE_STACK                                   \
1156          : /*out*/   "=a" (_res)                                  \
1157          : /*in*/    "a" (&_argvec[0])                            \
1158          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1159       );                                                          \
1160       lval = (__typeof__(lval)) _res;                             \
1161    } while (0)
1162 
1163 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
1164    do {                                                           \
1165       volatile OrigFn        _orig = (orig);                      \
1166       volatile unsigned long _argvec[3];                          \
1167       volatile unsigned long _res;                                \
1168       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1169       _argvec[1] = (unsigned long)(arg1);                         \
1170       _argvec[2] = (unsigned long)(arg2);                         \
1171       __asm__ volatile(                                           \
1172          VALGRIND_ALIGN_STACK                                     \
1173          "subl $8, %%esp\n\t"                                     \
1174          "pushl 8(%%eax)\n\t"                                     \
1175          "pushl 4(%%eax)\n\t"                                     \
1176          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1177          VALGRIND_CALL_NOREDIR_EAX                                \
1178          VALGRIND_RESTORE_STACK                                   \
1179          : /*out*/   "=a" (_res)                                  \
1180          : /*in*/    "a" (&_argvec[0])                            \
1181          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1182       );                                                          \
1183       lval = (__typeof__(lval)) _res;                             \
1184    } while (0)
1185 
1186 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
1187    do {                                                           \
1188       volatile OrigFn        _orig = (orig);                      \
1189       volatile unsigned long _argvec[4];                          \
1190       volatile unsigned long _res;                                \
1191       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1192       _argvec[1] = (unsigned long)(arg1);                         \
1193       _argvec[2] = (unsigned long)(arg2);                         \
1194       _argvec[3] = (unsigned long)(arg3);                         \
1195       __asm__ volatile(                                           \
1196          VALGRIND_ALIGN_STACK                                     \
1197          "subl $4, %%esp\n\t"                                     \
1198          "pushl 12(%%eax)\n\t"                                    \
1199          "pushl 8(%%eax)\n\t"                                     \
1200          "pushl 4(%%eax)\n\t"                                     \
1201          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1202          VALGRIND_CALL_NOREDIR_EAX                                \
1203          VALGRIND_RESTORE_STACK                                   \
1204          : /*out*/   "=a" (_res)                                  \
1205          : /*in*/    "a" (&_argvec[0])                            \
1206          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1207       );                                                          \
1208       lval = (__typeof__(lval)) _res;                             \
1209    } while (0)
1210 
1211 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
1212    do {                                                           \
1213       volatile OrigFn        _orig = (orig);                      \
1214       volatile unsigned long _argvec[5];                          \
1215       volatile unsigned long _res;                                \
1216       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1217       _argvec[1] = (unsigned long)(arg1);                         \
1218       _argvec[2] = (unsigned long)(arg2);                         \
1219       _argvec[3] = (unsigned long)(arg3);                         \
1220       _argvec[4] = (unsigned long)(arg4);                         \
1221       __asm__ volatile(                                           \
1222          VALGRIND_ALIGN_STACK                                     \
1223          "pushl 16(%%eax)\n\t"                                    \
1224          "pushl 12(%%eax)\n\t"                                    \
1225          "pushl 8(%%eax)\n\t"                                     \
1226          "pushl 4(%%eax)\n\t"                                     \
1227          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1228          VALGRIND_CALL_NOREDIR_EAX                                \
1229          VALGRIND_RESTORE_STACK                                   \
1230          : /*out*/   "=a" (_res)                                  \
1231          : /*in*/    "a" (&_argvec[0])                            \
1232          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1233       );                                                          \
1234       lval = (__typeof__(lval)) _res;                             \
1235    } while (0)
1236 
1237 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
1238    do {                                                           \
1239       volatile OrigFn        _orig = (orig);                      \
1240       volatile unsigned long _argvec[6];                          \
1241       volatile unsigned long _res;                                \
1242       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1243       _argvec[1] = (unsigned long)(arg1);                         \
1244       _argvec[2] = (unsigned long)(arg2);                         \
1245       _argvec[3] = (unsigned long)(arg3);                         \
1246       _argvec[4] = (unsigned long)(arg4);                         \
1247       _argvec[5] = (unsigned long)(arg5);                         \
1248       __asm__ volatile(                                           \
1249          VALGRIND_ALIGN_STACK                                     \
1250          "subl $12, %%esp\n\t"                                    \
1251          "pushl 20(%%eax)\n\t"                                    \
1252          "pushl 16(%%eax)\n\t"                                    \
1253          "pushl 12(%%eax)\n\t"                                    \
1254          "pushl 8(%%eax)\n\t"                                     \
1255          "pushl 4(%%eax)\n\t"                                     \
1256          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1257          VALGRIND_CALL_NOREDIR_EAX                                \
1258          VALGRIND_RESTORE_STACK                                   \
1259          : /*out*/   "=a" (_res)                                  \
1260          : /*in*/    "a" (&_argvec[0])                            \
1261          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1262       );                                                          \
1263       lval = (__typeof__(lval)) _res;                             \
1264    } while (0)
1265 
1266 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
1267    do {                                                           \
1268       volatile OrigFn        _orig = (orig);                      \
1269       volatile unsigned long _argvec[7];                          \
1270       volatile unsigned long _res;                                \
1271       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1272       _argvec[1] = (unsigned long)(arg1);                         \
1273       _argvec[2] = (unsigned long)(arg2);                         \
1274       _argvec[3] = (unsigned long)(arg3);                         \
1275       _argvec[4] = (unsigned long)(arg4);                         \
1276       _argvec[5] = (unsigned long)(arg5);                         \
1277       _argvec[6] = (unsigned long)(arg6);                         \
1278       __asm__ volatile(                                           \
1279          VALGRIND_ALIGN_STACK                                     \
1280          "subl $8, %%esp\n\t"                                     \
1281          "pushl 24(%%eax)\n\t"                                    \
1282          "pushl 20(%%eax)\n\t"                                    \
1283          "pushl 16(%%eax)\n\t"                                    \
1284          "pushl 12(%%eax)\n\t"                                    \
1285          "pushl 8(%%eax)\n\t"                                     \
1286          "pushl 4(%%eax)\n\t"                                     \
1287          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1288          VALGRIND_CALL_NOREDIR_EAX                                \
1289          VALGRIND_RESTORE_STACK                                   \
1290          : /*out*/   "=a" (_res)                                  \
1291          : /*in*/    "a" (&_argvec[0])                            \
1292          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1293       );                                                          \
1294       lval = (__typeof__(lval)) _res;                             \
1295    } while (0)
1296 
1297 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1298                                  arg7)                            \
1299    do {                                                           \
1300       volatile OrigFn        _orig = (orig);                      \
1301       volatile unsigned long _argvec[8];                          \
1302       volatile unsigned long _res;                                \
1303       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1304       _argvec[1] = (unsigned long)(arg1);                         \
1305       _argvec[2] = (unsigned long)(arg2);                         \
1306       _argvec[3] = (unsigned long)(arg3);                         \
1307       _argvec[4] = (unsigned long)(arg4);                         \
1308       _argvec[5] = (unsigned long)(arg5);                         \
1309       _argvec[6] = (unsigned long)(arg6);                         \
1310       _argvec[7] = (unsigned long)(arg7);                         \
1311       __asm__ volatile(                                           \
1312          VALGRIND_ALIGN_STACK                                     \
1313          "subl $4, %%esp\n\t"                                     \
1314          "pushl 28(%%eax)\n\t"                                    \
1315          "pushl 24(%%eax)\n\t"                                    \
1316          "pushl 20(%%eax)\n\t"                                    \
1317          "pushl 16(%%eax)\n\t"                                    \
1318          "pushl 12(%%eax)\n\t"                                    \
1319          "pushl 8(%%eax)\n\t"                                     \
1320          "pushl 4(%%eax)\n\t"                                     \
1321          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1322          VALGRIND_CALL_NOREDIR_EAX                                \
1323          VALGRIND_RESTORE_STACK                                   \
1324          : /*out*/   "=a" (_res)                                  \
1325          : /*in*/    "a" (&_argvec[0])                            \
1326          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1327       );                                                          \
1328       lval = (__typeof__(lval)) _res;                             \
1329    } while (0)
1330 
1331 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1332                                  arg7,arg8)                       \
1333    do {                                                           \
1334       volatile OrigFn        _orig = (orig);                      \
1335       volatile unsigned long _argvec[9];                          \
1336       volatile unsigned long _res;                                \
1337       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1338       _argvec[1] = (unsigned long)(arg1);                         \
1339       _argvec[2] = (unsigned long)(arg2);                         \
1340       _argvec[3] = (unsigned long)(arg3);                         \
1341       _argvec[4] = (unsigned long)(arg4);                         \
1342       _argvec[5] = (unsigned long)(arg5);                         \
1343       _argvec[6] = (unsigned long)(arg6);                         \
1344       _argvec[7] = (unsigned long)(arg7);                         \
1345       _argvec[8] = (unsigned long)(arg8);                         \
1346       __asm__ volatile(                                           \
1347          VALGRIND_ALIGN_STACK                                     \
1348          "pushl 32(%%eax)\n\t"                                    \
1349          "pushl 28(%%eax)\n\t"                                    \
1350          "pushl 24(%%eax)\n\t"                                    \
1351          "pushl 20(%%eax)\n\t"                                    \
1352          "pushl 16(%%eax)\n\t"                                    \
1353          "pushl 12(%%eax)\n\t"                                    \
1354          "pushl 8(%%eax)\n\t"                                     \
1355          "pushl 4(%%eax)\n\t"                                     \
1356          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1357          VALGRIND_CALL_NOREDIR_EAX                                \
1358          VALGRIND_RESTORE_STACK                                   \
1359          : /*out*/   "=a" (_res)                                  \
1360          : /*in*/    "a" (&_argvec[0])                            \
1361          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1362       );                                                          \
1363       lval = (__typeof__(lval)) _res;                             \
1364    } while (0)
1365 
1366 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1367                                  arg7,arg8,arg9)                  \
1368    do {                                                           \
1369       volatile OrigFn        _orig = (orig);                      \
1370       volatile unsigned long _argvec[10];                         \
1371       volatile unsigned long _res;                                \
1372       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1373       _argvec[1] = (unsigned long)(arg1);                         \
1374       _argvec[2] = (unsigned long)(arg2);                         \
1375       _argvec[3] = (unsigned long)(arg3);                         \
1376       _argvec[4] = (unsigned long)(arg4);                         \
1377       _argvec[5] = (unsigned long)(arg5);                         \
1378       _argvec[6] = (unsigned long)(arg6);                         \
1379       _argvec[7] = (unsigned long)(arg7);                         \
1380       _argvec[8] = (unsigned long)(arg8);                         \
1381       _argvec[9] = (unsigned long)(arg9);                         \
1382       __asm__ volatile(                                           \
1383          VALGRIND_ALIGN_STACK                                     \
1384          "subl $12, %%esp\n\t"                                    \
1385          "pushl 36(%%eax)\n\t"                                    \
1386          "pushl 32(%%eax)\n\t"                                    \
1387          "pushl 28(%%eax)\n\t"                                    \
1388          "pushl 24(%%eax)\n\t"                                    \
1389          "pushl 20(%%eax)\n\t"                                    \
1390          "pushl 16(%%eax)\n\t"                                    \
1391          "pushl 12(%%eax)\n\t"                                    \
1392          "pushl 8(%%eax)\n\t"                                     \
1393          "pushl 4(%%eax)\n\t"                                     \
1394          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1395          VALGRIND_CALL_NOREDIR_EAX                                \
1396          VALGRIND_RESTORE_STACK                                   \
1397          : /*out*/   "=a" (_res)                                  \
1398          : /*in*/    "a" (&_argvec[0])                            \
1399          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1400       );                                                          \
1401       lval = (__typeof__(lval)) _res;                             \
1402    } while (0)
1403 
1404 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1405                                   arg7,arg8,arg9,arg10)           \
1406    do {                                                           \
1407       volatile OrigFn        _orig = (orig);                      \
1408       volatile unsigned long _argvec[11];                         \
1409       volatile unsigned long _res;                                \
1410       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1411       _argvec[1] = (unsigned long)(arg1);                         \
1412       _argvec[2] = (unsigned long)(arg2);                         \
1413       _argvec[3] = (unsigned long)(arg3);                         \
1414       _argvec[4] = (unsigned long)(arg4);                         \
1415       _argvec[5] = (unsigned long)(arg5);                         \
1416       _argvec[6] = (unsigned long)(arg6);                         \
1417       _argvec[7] = (unsigned long)(arg7);                         \
1418       _argvec[8] = (unsigned long)(arg8);                         \
1419       _argvec[9] = (unsigned long)(arg9);                         \
1420       _argvec[10] = (unsigned long)(arg10);                       \
1421       __asm__ volatile(                                           \
1422          VALGRIND_ALIGN_STACK                                     \
1423          "subl $8, %%esp\n\t"                                     \
1424          "pushl 40(%%eax)\n\t"                                    \
1425          "pushl 36(%%eax)\n\t"                                    \
1426          "pushl 32(%%eax)\n\t"                                    \
1427          "pushl 28(%%eax)\n\t"                                    \
1428          "pushl 24(%%eax)\n\t"                                    \
1429          "pushl 20(%%eax)\n\t"                                    \
1430          "pushl 16(%%eax)\n\t"                                    \
1431          "pushl 12(%%eax)\n\t"                                    \
1432          "pushl 8(%%eax)\n\t"                                     \
1433          "pushl 4(%%eax)\n\t"                                     \
1434          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1435          VALGRIND_CALL_NOREDIR_EAX                                \
1436          VALGRIND_RESTORE_STACK                                   \
1437          : /*out*/   "=a" (_res)                                  \
1438          : /*in*/    "a" (&_argvec[0])                            \
1439          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1440       );                                                          \
1441       lval = (__typeof__(lval)) _res;                             \
1442    } while (0)
1443 
1444 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
1445                                   arg6,arg7,arg8,arg9,arg10,      \
1446                                   arg11)                          \
1447    do {                                                           \
1448       volatile OrigFn        _orig = (orig);                      \
1449       volatile unsigned long _argvec[12];                         \
1450       volatile unsigned long _res;                                \
1451       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1452       _argvec[1] = (unsigned long)(arg1);                         \
1453       _argvec[2] = (unsigned long)(arg2);                         \
1454       _argvec[3] = (unsigned long)(arg3);                         \
1455       _argvec[4] = (unsigned long)(arg4);                         \
1456       _argvec[5] = (unsigned long)(arg5);                         \
1457       _argvec[6] = (unsigned long)(arg6);                         \
1458       _argvec[7] = (unsigned long)(arg7);                         \
1459       _argvec[8] = (unsigned long)(arg8);                         \
1460       _argvec[9] = (unsigned long)(arg9);                         \
1461       _argvec[10] = (unsigned long)(arg10);                       \
1462       _argvec[11] = (unsigned long)(arg11);                       \
1463       __asm__ volatile(                                           \
1464          VALGRIND_ALIGN_STACK                                     \
1465          "subl $4, %%esp\n\t"                                     \
1466          "pushl 44(%%eax)\n\t"                                    \
1467          "pushl 40(%%eax)\n\t"                                    \
1468          "pushl 36(%%eax)\n\t"                                    \
1469          "pushl 32(%%eax)\n\t"                                    \
1470          "pushl 28(%%eax)\n\t"                                    \
1471          "pushl 24(%%eax)\n\t"                                    \
1472          "pushl 20(%%eax)\n\t"                                    \
1473          "pushl 16(%%eax)\n\t"                                    \
1474          "pushl 12(%%eax)\n\t"                                    \
1475          "pushl 8(%%eax)\n\t"                                     \
1476          "pushl 4(%%eax)\n\t"                                     \
1477          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1478          VALGRIND_CALL_NOREDIR_EAX                                \
1479          VALGRIND_RESTORE_STACK                                   \
1480          : /*out*/   "=a" (_res)                                  \
1481          : /*in*/    "a" (&_argvec[0])                            \
1482          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1483       );                                                          \
1484       lval = (__typeof__(lval)) _res;                             \
1485    } while (0)
1486 
1487 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
1488                                   arg6,arg7,arg8,arg9,arg10,      \
1489                                   arg11,arg12)                    \
1490    do {                                                           \
1491       volatile OrigFn        _orig = (orig);                      \
1492       volatile unsigned long _argvec[13];                         \
1493       volatile unsigned long _res;                                \
1494       _argvec[0] = (unsigned long)_orig.nraddr;                   \
1495       _argvec[1] = (unsigned long)(arg1);                         \
1496       _argvec[2] = (unsigned long)(arg2);                         \
1497       _argvec[3] = (unsigned long)(arg3);                         \
1498       _argvec[4] = (unsigned long)(arg4);                         \
1499       _argvec[5] = (unsigned long)(arg5);                         \
1500       _argvec[6] = (unsigned long)(arg6);                         \
1501       _argvec[7] = (unsigned long)(arg7);                         \
1502       _argvec[8] = (unsigned long)(arg8);                         \
1503       _argvec[9] = (unsigned long)(arg9);                         \
1504       _argvec[10] = (unsigned long)(arg10);                       \
1505       _argvec[11] = (unsigned long)(arg11);                       \
1506       _argvec[12] = (unsigned long)(arg12);                       \
1507       __asm__ volatile(                                           \
1508          VALGRIND_ALIGN_STACK                                     \
1509          "pushl 48(%%eax)\n\t"                                    \
1510          "pushl 44(%%eax)\n\t"                                    \
1511          "pushl 40(%%eax)\n\t"                                    \
1512          "pushl 36(%%eax)\n\t"                                    \
1513          "pushl 32(%%eax)\n\t"                                    \
1514          "pushl 28(%%eax)\n\t"                                    \
1515          "pushl 24(%%eax)\n\t"                                    \
1516          "pushl 20(%%eax)\n\t"                                    \
1517          "pushl 16(%%eax)\n\t"                                    \
1518          "pushl 12(%%eax)\n\t"                                    \
1519          "pushl 8(%%eax)\n\t"                                     \
1520          "pushl 4(%%eax)\n\t"                                     \
1521          "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1522          VALGRIND_CALL_NOREDIR_EAX                                \
1523          VALGRIND_RESTORE_STACK                                   \
1524          : /*out*/   "=a" (_res)                                  \
1525          : /*in*/    "a" (&_argvec[0])                            \
1526          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1527       );                                                          \
1528       lval = (__typeof__(lval)) _res;                             \
1529    } while (0)
1530 
1531 #endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_solaris */
1532 
1533 /* ---------------- amd64-{linux,darwin,solaris} --------------- */
1534 
1535 #if defined(PLAT_amd64_linux)  ||  defined(PLAT_amd64_darwin) \
1536     ||  defined(PLAT_amd64_solaris)
1537 
1538 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1539 
1540 /* These regs are trashed by the hidden call. */
1541 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi",       \
1542                             "rdi", "r8", "r9", "r10", "r11"
1543 
1544 /* This is all pretty complex.  It's so as to make stack unwinding
1545    work reliably.  See bug 243270.  The basic problem is the sub and
1546    add of 128 of %rsp in all of the following macros.  If gcc believes
1547    the CFA is in %rsp, then unwinding may fail, because what's at the
1548    CFA is not what gcc "expected" when it constructs the CFIs for the
1549    places where the macros are instantiated.
1550 
1551    But we can't just add a CFI annotation to increase the CFA offset
1552    by 128, to match the sub of 128 from %rsp, because we don't know
1553    whether gcc has chosen %rsp as the CFA at that point, or whether it
1554    has chosen some other register (eg, %rbp).  In the latter case,
1555    adding a CFI annotation to change the CFA offset is simply wrong.
1556 
1557    So the solution is to get hold of the CFA using
1558    __builtin_dwarf_cfa(), put it in a known register, and add a
1559    CFI annotation to say what the register is.  We choose %rbp for
1560    this (perhaps perversely), because:
1561 
1562    (1) %rbp is already subject to unwinding.  If a new register was
1563        chosen then the unwinder would have to unwind it in all stack
1564        traces, which is expensive, and
1565 
1566    (2) %rbp is already subject to precise exception updates in the
1567        JIT.  If a new register was chosen, we'd have to have precise
1568        exceptions for it too, which reduces performance of the
1569        generated code.
1570 
1571    However .. one extra complication.  We can't just whack the result
1572    of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
1573    list of trashed registers at the end of the inline assembly
1574    fragments; gcc won't allow %rbp to appear in that list.  Hence
1575    instead we need to stash %rbp in %r15 for the duration of the asm,
1576    and say that %r15 is trashed instead.  gcc seems happy to go with
1577    that.
1578 
1579    Oh .. and this all needs to be conditionalised so that it is
1580    unchanged from before this commit, when compiled with older gccs
1581    that don't support __builtin_dwarf_cfa.  Furthermore, since
1582    this header file is freestanding, it has to be independent of
1583    config.h, and so the following conditionalisation cannot depend on
1584    configure time checks.
1585 
1586    Although it's not clear from
1587    'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1588    this expression excludes Darwin.
1589    .cfi directives in Darwin assembly appear to be completely
1590    different and I haven't investigated how they work.
1591 
1592    For even more entertainment value, note we have to use the
1593    completely undocumented __builtin_dwarf_cfa(), which appears to
1594    really compute the CFA, whereas __builtin_frame_address(0) claims
1595    to but actually doesn't.  See
1596    https://bugs.kde.org/show_bug.cgi?id=243270#c47
1597 */
1598 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
1599 #  define __FRAME_POINTER                                         \
1600       ,"r"(__builtin_dwarf_cfa())
1601 #  define VALGRIND_CFI_PROLOGUE                                   \
1602       "movq %%rbp, %%r15\n\t"                                     \
1603       "movq %2, %%rbp\n\t"                                        \
1604       ".cfi_remember_state\n\t"                                   \
1605       ".cfi_def_cfa rbp, 0\n\t"
1606 #  define VALGRIND_CFI_EPILOGUE                                   \
1607       "movq %%r15, %%rbp\n\t"                                     \
1608       ".cfi_restore_state\n\t"
1609 #else
1610 #  define __FRAME_POINTER
1611 #  define VALGRIND_CFI_PROLOGUE
1612 #  define VALGRIND_CFI_EPILOGUE
1613 #endif
1614 
1615 /* Macros to save and align the stack before making a function
1616    call and restore it afterwards as gcc may not keep the stack
1617    pointer aligned if it doesn't realise calls are being made
1618    to other functions. */
1619 
1620 #define VALGRIND_ALIGN_STACK               \
1621       "movq %%rsp,%%r14\n\t"               \
1622       "andq $0xfffffffffffffff0,%%rsp\n\t"
1623 #define VALGRIND_RESTORE_STACK             \
1624       "movq %%r14,%%rsp\n\t"
1625 
1626 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1627    long) == 8. */
1628 
1629 /* NB 9 Sept 07.  There is a nasty kludge here in all these CALL_FN_
1630    macros.  In order not to trash the stack redzone, we need to drop
1631    %rsp by 128 before the hidden call, and restore afterwards.  The
1632    nastiness is that it is only by luck that the stack still appears
1633    to be unwindable during the hidden call - since then the behaviour
1634    of any routine using this macro does not match what the CFI data
1635    says.  Sigh.
1636 
1637    Why is this important?  Imagine that a wrapper has a stack
1638    allocated local, and passes to the hidden call, a pointer to it.
1639    Because gcc does not know about the hidden call, it may allocate
1640    that local in the redzone.  Unfortunately the hidden call may then
1641    trash it before it comes to use it.  So we must step clear of the
1642    redzone, for the duration of the hidden call, to make it safe.
1643 
1644    Probably the same problem afflicts the other redzone-style ABIs too
1645    (ppc64-linux); but for those, the stack is
1646    self describing (none of this CFI nonsense) so at least messing
1647    with the stack pointer doesn't give a danger of non-unwindable
1648    stack. */
1649 
1650 #define CALL_FN_W_v(lval, orig)                                        \
1651    do {                                                                \
1652       volatile OrigFn        _orig = (orig);                           \
1653       volatile unsigned long _argvec[1];                               \
1654       volatile unsigned long _res;                                     \
1655       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1656       __asm__ volatile(                                                \
1657          VALGRIND_CFI_PROLOGUE                                         \
1658          VALGRIND_ALIGN_STACK                                          \
1659          "subq $128,%%rsp\n\t"                                         \
1660          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1661          VALGRIND_CALL_NOREDIR_RAX                                     \
1662          VALGRIND_RESTORE_STACK                                        \
1663          VALGRIND_CFI_EPILOGUE                                         \
1664          : /*out*/   "=a" (_res)                                       \
1665          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1666          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1667       );                                                               \
1668       lval = (__typeof__(lval)) _res;                                  \
1669    } while (0)
1670 
1671 #define CALL_FN_W_W(lval, orig, arg1)                                  \
1672    do {                                                                \
1673       volatile OrigFn        _orig = (orig);                           \
1674       volatile unsigned long _argvec[2];                               \
1675       volatile unsigned long _res;                                     \
1676       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1677       _argvec[1] = (unsigned long)(arg1);                              \
1678       __asm__ volatile(                                                \
1679          VALGRIND_CFI_PROLOGUE                                         \
1680          VALGRIND_ALIGN_STACK                                          \
1681          "subq $128,%%rsp\n\t"                                         \
1682          "movq 8(%%rax), %%rdi\n\t"                                    \
1683          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1684          VALGRIND_CALL_NOREDIR_RAX                                     \
1685          VALGRIND_RESTORE_STACK                                        \
1686          VALGRIND_CFI_EPILOGUE                                         \
1687          : /*out*/   "=a" (_res)                                       \
1688          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1689          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1690       );                                                               \
1691       lval = (__typeof__(lval)) _res;                                  \
1692    } while (0)
1693 
1694 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                            \
1695    do {                                                                \
1696       volatile OrigFn        _orig = (orig);                           \
1697       volatile unsigned long _argvec[3];                               \
1698       volatile unsigned long _res;                                     \
1699       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1700       _argvec[1] = (unsigned long)(arg1);                              \
1701       _argvec[2] = (unsigned long)(arg2);                              \
1702       __asm__ volatile(                                                \
1703          VALGRIND_CFI_PROLOGUE                                         \
1704          VALGRIND_ALIGN_STACK                                          \
1705          "subq $128,%%rsp\n\t"                                         \
1706          "movq 16(%%rax), %%rsi\n\t"                                   \
1707          "movq 8(%%rax), %%rdi\n\t"                                    \
1708          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1709          VALGRIND_CALL_NOREDIR_RAX                                     \
1710          VALGRIND_RESTORE_STACK                                        \
1711          VALGRIND_CFI_EPILOGUE                                         \
1712          : /*out*/   "=a" (_res)                                       \
1713          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1714          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1715       );                                                               \
1716       lval = (__typeof__(lval)) _res;                                  \
1717    } while (0)
1718 
1719 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                      \
1720    do {                                                                \
1721       volatile OrigFn        _orig = (orig);                           \
1722       volatile unsigned long _argvec[4];                               \
1723       volatile unsigned long _res;                                     \
1724       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1725       _argvec[1] = (unsigned long)(arg1);                              \
1726       _argvec[2] = (unsigned long)(arg2);                              \
1727       _argvec[3] = (unsigned long)(arg3);                              \
1728       __asm__ volatile(                                                \
1729          VALGRIND_CFI_PROLOGUE                                         \
1730          VALGRIND_ALIGN_STACK                                          \
1731          "subq $128,%%rsp\n\t"                                         \
1732          "movq 24(%%rax), %%rdx\n\t"                                   \
1733          "movq 16(%%rax), %%rsi\n\t"                                   \
1734          "movq 8(%%rax), %%rdi\n\t"                                    \
1735          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1736          VALGRIND_CALL_NOREDIR_RAX                                     \
1737          VALGRIND_RESTORE_STACK                                        \
1738          VALGRIND_CFI_EPILOGUE                                         \
1739          : /*out*/   "=a" (_res)                                       \
1740          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1741          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1742       );                                                               \
1743       lval = (__typeof__(lval)) _res;                                  \
1744    } while (0)
1745 
1746 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)                \
1747    do {                                                                \
1748       volatile OrigFn        _orig = (orig);                           \
1749       volatile unsigned long _argvec[5];                               \
1750       volatile unsigned long _res;                                     \
1751       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1752       _argvec[1] = (unsigned long)(arg1);                              \
1753       _argvec[2] = (unsigned long)(arg2);                              \
1754       _argvec[3] = (unsigned long)(arg3);                              \
1755       _argvec[4] = (unsigned long)(arg4);                              \
1756       __asm__ volatile(                                                \
1757          VALGRIND_CFI_PROLOGUE                                         \
1758          VALGRIND_ALIGN_STACK                                          \
1759          "subq $128,%%rsp\n\t"                                         \
1760          "movq 32(%%rax), %%rcx\n\t"                                   \
1761          "movq 24(%%rax), %%rdx\n\t"                                   \
1762          "movq 16(%%rax), %%rsi\n\t"                                   \
1763          "movq 8(%%rax), %%rdi\n\t"                                    \
1764          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1765          VALGRIND_CALL_NOREDIR_RAX                                     \
1766          VALGRIND_RESTORE_STACK                                        \
1767          VALGRIND_CFI_EPILOGUE                                         \
1768          : /*out*/   "=a" (_res)                                       \
1769          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1770          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1771       );                                                               \
1772       lval = (__typeof__(lval)) _res;                                  \
1773    } while (0)
1774 
1775 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)             \
1776    do {                                                                \
1777       volatile OrigFn        _orig = (orig);                           \
1778       volatile unsigned long _argvec[6];                               \
1779       volatile unsigned long _res;                                     \
1780       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1781       _argvec[1] = (unsigned long)(arg1);                              \
1782       _argvec[2] = (unsigned long)(arg2);                              \
1783       _argvec[3] = (unsigned long)(arg3);                              \
1784       _argvec[4] = (unsigned long)(arg4);                              \
1785       _argvec[5] = (unsigned long)(arg5);                              \
1786       __asm__ volatile(                                                \
1787          VALGRIND_CFI_PROLOGUE                                         \
1788          VALGRIND_ALIGN_STACK                                          \
1789          "subq $128,%%rsp\n\t"                                         \
1790          "movq 40(%%rax), %%r8\n\t"                                    \
1791          "movq 32(%%rax), %%rcx\n\t"                                   \
1792          "movq 24(%%rax), %%rdx\n\t"                                   \
1793          "movq 16(%%rax), %%rsi\n\t"                                   \
1794          "movq 8(%%rax), %%rdi\n\t"                                    \
1795          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1796          VALGRIND_CALL_NOREDIR_RAX                                     \
1797          VALGRIND_RESTORE_STACK                                        \
1798          VALGRIND_CFI_EPILOGUE                                         \
1799          : /*out*/   "=a" (_res)                                       \
1800          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1801          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1802       );                                                               \
1803       lval = (__typeof__(lval)) _res;                                  \
1804    } while (0)
1805 
1806 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)        \
1807    do {                                                                \
1808       volatile OrigFn        _orig = (orig);                           \
1809       volatile unsigned long _argvec[7];                               \
1810       volatile unsigned long _res;                                     \
1811       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1812       _argvec[1] = (unsigned long)(arg1);                              \
1813       _argvec[2] = (unsigned long)(arg2);                              \
1814       _argvec[3] = (unsigned long)(arg3);                              \
1815       _argvec[4] = (unsigned long)(arg4);                              \
1816       _argvec[5] = (unsigned long)(arg5);                              \
1817       _argvec[6] = (unsigned long)(arg6);                              \
1818       __asm__ volatile(                                                \
1819          VALGRIND_CFI_PROLOGUE                                         \
1820          VALGRIND_ALIGN_STACK                                          \
1821          "subq $128,%%rsp\n\t"                                         \
1822          "movq 48(%%rax), %%r9\n\t"                                    \
1823          "movq 40(%%rax), %%r8\n\t"                                    \
1824          "movq 32(%%rax), %%rcx\n\t"                                   \
1825          "movq 24(%%rax), %%rdx\n\t"                                   \
1826          "movq 16(%%rax), %%rsi\n\t"                                   \
1827          "movq 8(%%rax), %%rdi\n\t"                                    \
1828          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1829          VALGRIND_CALL_NOREDIR_RAX                                     \
1830          VALGRIND_RESTORE_STACK                                        \
1831          VALGRIND_CFI_EPILOGUE                                         \
1832          : /*out*/   "=a" (_res)                                       \
1833          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1834          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1835       );                                                               \
1836       lval = (__typeof__(lval)) _res;                                  \
1837    } while (0)
1838 
1839 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
1840                                  arg7)                                 \
1841    do {                                                                \
1842       volatile OrigFn        _orig = (orig);                           \
1843       volatile unsigned long _argvec[8];                               \
1844       volatile unsigned long _res;                                     \
1845       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1846       _argvec[1] = (unsigned long)(arg1);                              \
1847       _argvec[2] = (unsigned long)(arg2);                              \
1848       _argvec[3] = (unsigned long)(arg3);                              \
1849       _argvec[4] = (unsigned long)(arg4);                              \
1850       _argvec[5] = (unsigned long)(arg5);                              \
1851       _argvec[6] = (unsigned long)(arg6);                              \
1852       _argvec[7] = (unsigned long)(arg7);                              \
1853       __asm__ volatile(                                                \
1854          VALGRIND_CFI_PROLOGUE                                         \
1855          VALGRIND_ALIGN_STACK                                          \
1856          "subq $136,%%rsp\n\t"                                         \
1857          "pushq 56(%%rax)\n\t"                                         \
1858          "movq 48(%%rax), %%r9\n\t"                                    \
1859          "movq 40(%%rax), %%r8\n\t"                                    \
1860          "movq 32(%%rax), %%rcx\n\t"                                   \
1861          "movq 24(%%rax), %%rdx\n\t"                                   \
1862          "movq 16(%%rax), %%rsi\n\t"                                   \
1863          "movq 8(%%rax), %%rdi\n\t"                                    \
1864          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1865          VALGRIND_CALL_NOREDIR_RAX                                     \
1866          VALGRIND_RESTORE_STACK                                        \
1867          VALGRIND_CFI_EPILOGUE                                         \
1868          : /*out*/   "=a" (_res)                                       \
1869          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1870          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1871       );                                                               \
1872       lval = (__typeof__(lval)) _res;                                  \
1873    } while (0)
1874 
1875 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
1876                                  arg7,arg8)                            \
1877    do {                                                                \
1878       volatile OrigFn        _orig = (orig);                           \
1879       volatile unsigned long _argvec[9];                               \
1880       volatile unsigned long _res;                                     \
1881       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1882       _argvec[1] = (unsigned long)(arg1);                              \
1883       _argvec[2] = (unsigned long)(arg2);                              \
1884       _argvec[3] = (unsigned long)(arg3);                              \
1885       _argvec[4] = (unsigned long)(arg4);                              \
1886       _argvec[5] = (unsigned long)(arg5);                              \
1887       _argvec[6] = (unsigned long)(arg6);                              \
1888       _argvec[7] = (unsigned long)(arg7);                              \
1889       _argvec[8] = (unsigned long)(arg8);                              \
1890       __asm__ volatile(                                                \
1891          VALGRIND_CFI_PROLOGUE                                         \
1892          VALGRIND_ALIGN_STACK                                          \
1893          "subq $128,%%rsp\n\t"                                         \
1894          "pushq 64(%%rax)\n\t"                                         \
1895          "pushq 56(%%rax)\n\t"                                         \
1896          "movq 48(%%rax), %%r9\n\t"                                    \
1897          "movq 40(%%rax), %%r8\n\t"                                    \
1898          "movq 32(%%rax), %%rcx\n\t"                                   \
1899          "movq 24(%%rax), %%rdx\n\t"                                   \
1900          "movq 16(%%rax), %%rsi\n\t"                                   \
1901          "movq 8(%%rax), %%rdi\n\t"                                    \
1902          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1903          VALGRIND_CALL_NOREDIR_RAX                                     \
1904          VALGRIND_RESTORE_STACK                                        \
1905          VALGRIND_CFI_EPILOGUE                                         \
1906          : /*out*/   "=a" (_res)                                       \
1907          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1908          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1909       );                                                               \
1910       lval = (__typeof__(lval)) _res;                                  \
1911    } while (0)
1912 
1913 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
1914                                  arg7,arg8,arg9)                       \
1915    do {                                                                \
1916       volatile OrigFn        _orig = (orig);                           \
1917       volatile unsigned long _argvec[10];                              \
1918       volatile unsigned long _res;                                     \
1919       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1920       _argvec[1] = (unsigned long)(arg1);                              \
1921       _argvec[2] = (unsigned long)(arg2);                              \
1922       _argvec[3] = (unsigned long)(arg3);                              \
1923       _argvec[4] = (unsigned long)(arg4);                              \
1924       _argvec[5] = (unsigned long)(arg5);                              \
1925       _argvec[6] = (unsigned long)(arg6);                              \
1926       _argvec[7] = (unsigned long)(arg7);                              \
1927       _argvec[8] = (unsigned long)(arg8);                              \
1928       _argvec[9] = (unsigned long)(arg9);                              \
1929       __asm__ volatile(                                                \
1930          VALGRIND_CFI_PROLOGUE                                         \
1931          VALGRIND_ALIGN_STACK                                          \
1932          "subq $136,%%rsp\n\t"                                         \
1933          "pushq 72(%%rax)\n\t"                                         \
1934          "pushq 64(%%rax)\n\t"                                         \
1935          "pushq 56(%%rax)\n\t"                                         \
1936          "movq 48(%%rax), %%r9\n\t"                                    \
1937          "movq 40(%%rax), %%r8\n\t"                                    \
1938          "movq 32(%%rax), %%rcx\n\t"                                   \
1939          "movq 24(%%rax), %%rdx\n\t"                                   \
1940          "movq 16(%%rax), %%rsi\n\t"                                   \
1941          "movq 8(%%rax), %%rdi\n\t"                                    \
1942          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1943          VALGRIND_CALL_NOREDIR_RAX                                     \
1944          VALGRIND_RESTORE_STACK                                        \
1945          VALGRIND_CFI_EPILOGUE                                         \
1946          : /*out*/   "=a" (_res)                                       \
1947          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1948          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1949       );                                                               \
1950       lval = (__typeof__(lval)) _res;                                  \
1951    } while (0)
1952 
1953 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
1954                                   arg7,arg8,arg9,arg10)                \
1955    do {                                                                \
1956       volatile OrigFn        _orig = (orig);                           \
1957       volatile unsigned long _argvec[11];                              \
1958       volatile unsigned long _res;                                     \
1959       _argvec[0] = (unsigned long)_orig.nraddr;                        \
1960       _argvec[1] = (unsigned long)(arg1);                              \
1961       _argvec[2] = (unsigned long)(arg2);                              \
1962       _argvec[3] = (unsigned long)(arg3);                              \
1963       _argvec[4] = (unsigned long)(arg4);                              \
1964       _argvec[5] = (unsigned long)(arg5);                              \
1965       _argvec[6] = (unsigned long)(arg6);                              \
1966       _argvec[7] = (unsigned long)(arg7);                              \
1967       _argvec[8] = (unsigned long)(arg8);                              \
1968       _argvec[9] = (unsigned long)(arg9);                              \
1969       _argvec[10] = (unsigned long)(arg10);                            \
1970       __asm__ volatile(                                                \
1971          VALGRIND_CFI_PROLOGUE                                         \
1972          VALGRIND_ALIGN_STACK                                          \
1973          "subq $128,%%rsp\n\t"                                         \
1974          "pushq 80(%%rax)\n\t"                                         \
1975          "pushq 72(%%rax)\n\t"                                         \
1976          "pushq 64(%%rax)\n\t"                                         \
1977          "pushq 56(%%rax)\n\t"                                         \
1978          "movq 48(%%rax), %%r9\n\t"                                    \
1979          "movq 40(%%rax), %%r8\n\t"                                    \
1980          "movq 32(%%rax), %%rcx\n\t"                                   \
1981          "movq 24(%%rax), %%rdx\n\t"                                   \
1982          "movq 16(%%rax), %%rsi\n\t"                                   \
1983          "movq 8(%%rax), %%rdi\n\t"                                    \
1984          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1985          VALGRIND_CALL_NOREDIR_RAX                                     \
1986          VALGRIND_RESTORE_STACK                                        \
1987          VALGRIND_CFI_EPILOGUE                                         \
1988          : /*out*/   "=a" (_res)                                       \
1989          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1990          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1991       );                                                               \
1992       lval = (__typeof__(lval)) _res;                                  \
1993    } while (0)
1994 
1995 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
1996                                   arg7,arg8,arg9,arg10,arg11)          \
1997    do {                                                                \
1998       volatile OrigFn        _orig = (orig);                           \
1999       volatile unsigned long _argvec[12];                              \
2000       volatile unsigned long _res;                                     \
2001       _argvec[0] = (unsigned long)_orig.nraddr;                        \
2002       _argvec[1] = (unsigned long)(arg1);                              \
2003       _argvec[2] = (unsigned long)(arg2);                              \
2004       _argvec[3] = (unsigned long)(arg3);                              \
2005       _argvec[4] = (unsigned long)(arg4);                              \
2006       _argvec[5] = (unsigned long)(arg5);                              \
2007       _argvec[6] = (unsigned long)(arg6);                              \
2008       _argvec[7] = (unsigned long)(arg7);                              \
2009       _argvec[8] = (unsigned long)(arg8);                              \
2010       _argvec[9] = (unsigned long)(arg9);                              \
2011       _argvec[10] = (unsigned long)(arg10);                            \
2012       _argvec[11] = (unsigned long)(arg11);                            \
2013       __asm__ volatile(                                                \
2014          VALGRIND_CFI_PROLOGUE                                         \
2015          VALGRIND_ALIGN_STACK                                          \
2016          "subq $136,%%rsp\n\t"                                         \
2017          "pushq 88(%%rax)\n\t"                                         \
2018          "pushq 80(%%rax)\n\t"                                         \
2019          "pushq 72(%%rax)\n\t"                                         \
2020          "pushq 64(%%rax)\n\t"                                         \
2021          "pushq 56(%%rax)\n\t"                                         \
2022          "movq 48(%%rax), %%r9\n\t"                                    \
2023          "movq 40(%%rax), %%r8\n\t"                                    \
2024          "movq 32(%%rax), %%rcx\n\t"                                   \
2025          "movq 24(%%rax), %%rdx\n\t"                                   \
2026          "movq 16(%%rax), %%rsi\n\t"                                   \
2027          "movq 8(%%rax), %%rdi\n\t"                                    \
2028          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2029          VALGRIND_CALL_NOREDIR_RAX                                     \
2030          VALGRIND_RESTORE_STACK                                        \
2031          VALGRIND_CFI_EPILOGUE                                         \
2032          : /*out*/   "=a" (_res)                                       \
2033          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2034          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2035       );                                                               \
2036       lval = (__typeof__(lval)) _res;                                  \
2037    } while (0)
2038 
2039 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
2040                                 arg7,arg8,arg9,arg10,arg11,arg12)      \
2041    do {                                                                \
2042       volatile OrigFn        _orig = (orig);                           \
2043       volatile unsigned long _argvec[13];                              \
2044       volatile unsigned long _res;                                     \
2045       _argvec[0] = (unsigned long)_orig.nraddr;                        \
2046       _argvec[1] = (unsigned long)(arg1);                              \
2047       _argvec[2] = (unsigned long)(arg2);                              \
2048       _argvec[3] = (unsigned long)(arg3);                              \
2049       _argvec[4] = (unsigned long)(arg4);                              \
2050       _argvec[5] = (unsigned long)(arg5);                              \
2051       _argvec[6] = (unsigned long)(arg6);                              \
2052       _argvec[7] = (unsigned long)(arg7);                              \
2053       _argvec[8] = (unsigned long)(arg8);                              \
2054       _argvec[9] = (unsigned long)(arg9);                              \
2055       _argvec[10] = (unsigned long)(arg10);                            \
2056       _argvec[11] = (unsigned long)(arg11);                            \
2057       _argvec[12] = (unsigned long)(arg12);                            \
2058       __asm__ volatile(                                                \
2059          VALGRIND_CFI_PROLOGUE                                         \
2060          VALGRIND_ALIGN_STACK                                          \
2061          "subq $128,%%rsp\n\t"                                         \
2062          "pushq 96(%%rax)\n\t"                                         \
2063          "pushq 88(%%rax)\n\t"                                         \
2064          "pushq 80(%%rax)\n\t"                                         \
2065          "pushq 72(%%rax)\n\t"                                         \
2066          "pushq 64(%%rax)\n\t"                                         \
2067          "pushq 56(%%rax)\n\t"                                         \
2068          "movq 48(%%rax), %%r9\n\t"                                    \
2069          "movq 40(%%rax), %%r8\n\t"                                    \
2070          "movq 32(%%rax), %%rcx\n\t"                                   \
2071          "movq 24(%%rax), %%rdx\n\t"                                   \
2072          "movq 16(%%rax), %%rsi\n\t"                                   \
2073          "movq 8(%%rax), %%rdi\n\t"                                    \
2074          "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2075          VALGRIND_CALL_NOREDIR_RAX                                     \
2076          VALGRIND_RESTORE_STACK                                        \
2077          VALGRIND_CFI_EPILOGUE                                         \
2078          : /*out*/   "=a" (_res)                                       \
2079          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2080          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2081       );                                                               \
2082       lval = (__typeof__(lval)) _res;                                  \
2083    } while (0)
2084 
2085 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
2086 
2087 /* ------------------------ ppc32-linux ------------------------ */
2088 
2089 #if defined(PLAT_ppc32_linux)
2090 
2091 /* This is useful for finding out about the on-stack stuff:
2092 
2093    extern int f9  ( int,int,int,int,int,int,int,int,int );
2094    extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2095    extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2096    extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2097 
2098    int g9 ( void ) {
2099       return f9(11,22,33,44,55,66,77,88,99);
2100    }
2101    int g10 ( void ) {
2102       return f10(11,22,33,44,55,66,77,88,99,110);
2103    }
2104    int g11 ( void ) {
2105       return f11(11,22,33,44,55,66,77,88,99,110,121);
2106    }
2107    int g12 ( void ) {
2108       return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2109    }
2110 */
2111 
2112 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2113 
2114 /* These regs are trashed by the hidden call. */
2115 #define __CALLER_SAVED_REGS                                       \
2116    "lr", "ctr", "xer",                                            \
2117    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
2118    "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
2119    "r11", "r12", "r13"
2120 
2121 /* Macros to save and align the stack before making a function
2122    call and restore it afterwards as gcc may not keep the stack
2123    pointer aligned if it doesn't realise calls are being made
2124    to other functions. */
2125 
2126 #define VALGRIND_ALIGN_STACK               \
2127       "mr 28,1\n\t"                        \
2128       "rlwinm 1,1,0,0,27\n\t"
2129 #define VALGRIND_RESTORE_STACK             \
2130       "mr 1,28\n\t"
2131 
2132 /* These CALL_FN_ macros assume that on ppc32-linux, 
2133    sizeof(unsigned long) == 4. */
2134 
2135 #define CALL_FN_W_v(lval, orig)                                   \
2136    do {                                                           \
2137       volatile OrigFn        _orig = (orig);                      \
2138       volatile unsigned long _argvec[1];                          \
2139       volatile unsigned long _res;                                \
2140       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2141       __asm__ volatile(                                           \
2142          VALGRIND_ALIGN_STACK                                     \
2143          "mr 11,%1\n\t"                                           \
2144          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2145          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2146          VALGRIND_RESTORE_STACK                                   \
2147          "mr %0,3"                                                \
2148          : /*out*/   "=r" (_res)                                  \
2149          : /*in*/    "r" (&_argvec[0])                            \
2150          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2151       );                                                          \
2152       lval = (__typeof__(lval)) _res;                             \
2153    } while (0)
2154 
2155 #define CALL_FN_W_W(lval, orig, arg1)                             \
2156    do {                                                           \
2157       volatile OrigFn        _orig = (orig);                      \
2158       volatile unsigned long _argvec[2];                          \
2159       volatile unsigned long _res;                                \
2160       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2161       _argvec[1] = (unsigned long)arg1;                           \
2162       __asm__ volatile(                                           \
2163          VALGRIND_ALIGN_STACK                                     \
2164          "mr 11,%1\n\t"                                           \
2165          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2166          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2167          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2168          VALGRIND_RESTORE_STACK                                   \
2169          "mr %0,3"                                                \
2170          : /*out*/   "=r" (_res)                                  \
2171          : /*in*/    "r" (&_argvec[0])                            \
2172          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2173       );                                                          \
2174       lval = (__typeof__(lval)) _res;                             \
2175    } while (0)
2176 
2177 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
2178    do {                                                           \
2179       volatile OrigFn        _orig = (orig);                      \
2180       volatile unsigned long _argvec[3];                          \
2181       volatile unsigned long _res;                                \
2182       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2183       _argvec[1] = (unsigned long)arg1;                           \
2184       _argvec[2] = (unsigned long)arg2;                           \
2185       __asm__ volatile(                                           \
2186          VALGRIND_ALIGN_STACK                                     \
2187          "mr 11,%1\n\t"                                           \
2188          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2189          "lwz 4,8(11)\n\t"                                        \
2190          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2191          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2192          VALGRIND_RESTORE_STACK                                   \
2193          "mr %0,3"                                                \
2194          : /*out*/   "=r" (_res)                                  \
2195          : /*in*/    "r" (&_argvec[0])                            \
2196          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2197       );                                                          \
2198       lval = (__typeof__(lval)) _res;                             \
2199    } while (0)
2200 
2201 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2202    do {                                                           \
2203       volatile OrigFn        _orig = (orig);                      \
2204       volatile unsigned long _argvec[4];                          \
2205       volatile unsigned long _res;                                \
2206       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2207       _argvec[1] = (unsigned long)arg1;                           \
2208       _argvec[2] = (unsigned long)arg2;                           \
2209       _argvec[3] = (unsigned long)arg3;                           \
2210       __asm__ volatile(                                           \
2211          VALGRIND_ALIGN_STACK                                     \
2212          "mr 11,%1\n\t"                                           \
2213          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2214          "lwz 4,8(11)\n\t"                                        \
2215          "lwz 5,12(11)\n\t"                                       \
2216          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2217          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2218          VALGRIND_RESTORE_STACK                                   \
2219          "mr %0,3"                                                \
2220          : /*out*/   "=r" (_res)                                  \
2221          : /*in*/    "r" (&_argvec[0])                            \
2222          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2223       );                                                          \
2224       lval = (__typeof__(lval)) _res;                             \
2225    } while (0)
2226 
2227 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2228    do {                                                           \
2229       volatile OrigFn        _orig = (orig);                      \
2230       volatile unsigned long _argvec[5];                          \
2231       volatile unsigned long _res;                                \
2232       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2233       _argvec[1] = (unsigned long)arg1;                           \
2234       _argvec[2] = (unsigned long)arg2;                           \
2235       _argvec[3] = (unsigned long)arg3;                           \
2236       _argvec[4] = (unsigned long)arg4;                           \
2237       __asm__ volatile(                                           \
2238          VALGRIND_ALIGN_STACK                                     \
2239          "mr 11,%1\n\t"                                           \
2240          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2241          "lwz 4,8(11)\n\t"                                        \
2242          "lwz 5,12(11)\n\t"                                       \
2243          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2244          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2245          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2246          VALGRIND_RESTORE_STACK                                   \
2247          "mr %0,3"                                                \
2248          : /*out*/   "=r" (_res)                                  \
2249          : /*in*/    "r" (&_argvec[0])                            \
2250          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2251       );                                                          \
2252       lval = (__typeof__(lval)) _res;                             \
2253    } while (0)
2254 
2255 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2256    do {                                                           \
2257       volatile OrigFn        _orig = (orig);                      \
2258       volatile unsigned long _argvec[6];                          \
2259       volatile unsigned long _res;                                \
2260       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2261       _argvec[1] = (unsigned long)arg1;                           \
2262       _argvec[2] = (unsigned long)arg2;                           \
2263       _argvec[3] = (unsigned long)arg3;                           \
2264       _argvec[4] = (unsigned long)arg4;                           \
2265       _argvec[5] = (unsigned long)arg5;                           \
2266       __asm__ volatile(                                           \
2267          VALGRIND_ALIGN_STACK                                     \
2268          "mr 11,%1\n\t"                                           \
2269          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2270          "lwz 4,8(11)\n\t"                                        \
2271          "lwz 5,12(11)\n\t"                                       \
2272          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2273          "lwz 7,20(11)\n\t"                                       \
2274          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2275          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2276          VALGRIND_RESTORE_STACK                                   \
2277          "mr %0,3"                                                \
2278          : /*out*/   "=r" (_res)                                  \
2279          : /*in*/    "r" (&_argvec[0])                            \
2280          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2281       );                                                          \
2282       lval = (__typeof__(lval)) _res;                             \
2283    } while (0)
2284 
2285 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2286    do {                                                           \
2287       volatile OrigFn        _orig = (orig);                      \
2288       volatile unsigned long _argvec[7];                          \
2289       volatile unsigned long _res;                                \
2290       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2291       _argvec[1] = (unsigned long)arg1;                           \
2292       _argvec[2] = (unsigned long)arg2;                           \
2293       _argvec[3] = (unsigned long)arg3;                           \
2294       _argvec[4] = (unsigned long)arg4;                           \
2295       _argvec[5] = (unsigned long)arg5;                           \
2296       _argvec[6] = (unsigned long)arg6;                           \
2297       __asm__ volatile(                                           \
2298          VALGRIND_ALIGN_STACK                                     \
2299          "mr 11,%1\n\t"                                           \
2300          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2301          "lwz 4,8(11)\n\t"                                        \
2302          "lwz 5,12(11)\n\t"                                       \
2303          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2304          "lwz 7,20(11)\n\t"                                       \
2305          "lwz 8,24(11)\n\t"                                       \
2306          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2307          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2308          VALGRIND_RESTORE_STACK                                   \
2309          "mr %0,3"                                                \
2310          : /*out*/   "=r" (_res)                                  \
2311          : /*in*/    "r" (&_argvec[0])                            \
2312          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2313       );                                                          \
2314       lval = (__typeof__(lval)) _res;                             \
2315    } while (0)
2316 
2317 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2318                                  arg7)                            \
2319    do {                                                           \
2320       volatile OrigFn        _orig = (orig);                      \
2321       volatile unsigned long _argvec[8];                          \
2322       volatile unsigned long _res;                                \
2323       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2324       _argvec[1] = (unsigned long)arg1;                           \
2325       _argvec[2] = (unsigned long)arg2;                           \
2326       _argvec[3] = (unsigned long)arg3;                           \
2327       _argvec[4] = (unsigned long)arg4;                           \
2328       _argvec[5] = (unsigned long)arg5;                           \
2329       _argvec[6] = (unsigned long)arg6;                           \
2330       _argvec[7] = (unsigned long)arg7;                           \
2331       __asm__ volatile(                                           \
2332          VALGRIND_ALIGN_STACK                                     \
2333          "mr 11,%1\n\t"                                           \
2334          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2335          "lwz 4,8(11)\n\t"                                        \
2336          "lwz 5,12(11)\n\t"                                       \
2337          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2338          "lwz 7,20(11)\n\t"                                       \
2339          "lwz 8,24(11)\n\t"                                       \
2340          "lwz 9,28(11)\n\t"                                       \
2341          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2342          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2343          VALGRIND_RESTORE_STACK                                   \
2344          "mr %0,3"                                                \
2345          : /*out*/   "=r" (_res)                                  \
2346          : /*in*/    "r" (&_argvec[0])                            \
2347          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2348       );                                                          \
2349       lval = (__typeof__(lval)) _res;                             \
2350    } while (0)
2351 
2352 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2353                                  arg7,arg8)                       \
2354    do {                                                           \
2355       volatile OrigFn        _orig = (orig);                      \
2356       volatile unsigned long _argvec[9];                          \
2357       volatile unsigned long _res;                                \
2358       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2359       _argvec[1] = (unsigned long)arg1;                           \
2360       _argvec[2] = (unsigned long)arg2;                           \
2361       _argvec[3] = (unsigned long)arg3;                           \
2362       _argvec[4] = (unsigned long)arg4;                           \
2363       _argvec[5] = (unsigned long)arg5;                           \
2364       _argvec[6] = (unsigned long)arg6;                           \
2365       _argvec[7] = (unsigned long)arg7;                           \
2366       _argvec[8] = (unsigned long)arg8;                           \
2367       __asm__ volatile(                                           \
2368          VALGRIND_ALIGN_STACK                                     \
2369          "mr 11,%1\n\t"                                           \
2370          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2371          "lwz 4,8(11)\n\t"                                        \
2372          "lwz 5,12(11)\n\t"                                       \
2373          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2374          "lwz 7,20(11)\n\t"                                       \
2375          "lwz 8,24(11)\n\t"                                       \
2376          "lwz 9,28(11)\n\t"                                       \
2377          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2378          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2379          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2380          VALGRIND_RESTORE_STACK                                   \
2381          "mr %0,3"                                                \
2382          : /*out*/   "=r" (_res)                                  \
2383          : /*in*/    "r" (&_argvec[0])                            \
2384          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2385       );                                                          \
2386       lval = (__typeof__(lval)) _res;                             \
2387    } while (0)
2388 
2389 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2390                                  arg7,arg8,arg9)                  \
2391    do {                                                           \
2392       volatile OrigFn        _orig = (orig);                      \
2393       volatile unsigned long _argvec[10];                         \
2394       volatile unsigned long _res;                                \
2395       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2396       _argvec[1] = (unsigned long)arg1;                           \
2397       _argvec[2] = (unsigned long)arg2;                           \
2398       _argvec[3] = (unsigned long)arg3;                           \
2399       _argvec[4] = (unsigned long)arg4;                           \
2400       _argvec[5] = (unsigned long)arg5;                           \
2401       _argvec[6] = (unsigned long)arg6;                           \
2402       _argvec[7] = (unsigned long)arg7;                           \
2403       _argvec[8] = (unsigned long)arg8;                           \
2404       _argvec[9] = (unsigned long)arg9;                           \
2405       __asm__ volatile(                                           \
2406          VALGRIND_ALIGN_STACK                                     \
2407          "mr 11,%1\n\t"                                           \
2408          "addi 1,1,-16\n\t"                                       \
2409          /* arg9 */                                               \
2410          "lwz 3,36(11)\n\t"                                       \
2411          "stw 3,8(1)\n\t"                                         \
2412          /* args1-8 */                                            \
2413          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2414          "lwz 4,8(11)\n\t"                                        \
2415          "lwz 5,12(11)\n\t"                                       \
2416          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2417          "lwz 7,20(11)\n\t"                                       \
2418          "lwz 8,24(11)\n\t"                                       \
2419          "lwz 9,28(11)\n\t"                                       \
2420          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2421          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2422          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2423          VALGRIND_RESTORE_STACK                                   \
2424          "mr %0,3"                                                \
2425          : /*out*/   "=r" (_res)                                  \
2426          : /*in*/    "r" (&_argvec[0])                            \
2427          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2428       );                                                          \
2429       lval = (__typeof__(lval)) _res;                             \
2430    } while (0)
2431 
2432 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2433                                   arg7,arg8,arg9,arg10)           \
2434    do {                                                           \
2435       volatile OrigFn        _orig = (orig);                      \
2436       volatile unsigned long _argvec[11];                         \
2437       volatile unsigned long _res;                                \
2438       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2439       _argvec[1] = (unsigned long)arg1;                           \
2440       _argvec[2] = (unsigned long)arg2;                           \
2441       _argvec[3] = (unsigned long)arg3;                           \
2442       _argvec[4] = (unsigned long)arg4;                           \
2443       _argvec[5] = (unsigned long)arg5;                           \
2444       _argvec[6] = (unsigned long)arg6;                           \
2445       _argvec[7] = (unsigned long)arg7;                           \
2446       _argvec[8] = (unsigned long)arg8;                           \
2447       _argvec[9] = (unsigned long)arg9;                           \
2448       _argvec[10] = (unsigned long)arg10;                         \
2449       __asm__ volatile(                                           \
2450          VALGRIND_ALIGN_STACK                                     \
2451          "mr 11,%1\n\t"                                           \
2452          "addi 1,1,-16\n\t"                                       \
2453          /* arg10 */                                              \
2454          "lwz 3,40(11)\n\t"                                       \
2455          "stw 3,12(1)\n\t"                                        \
2456          /* arg9 */                                               \
2457          "lwz 3,36(11)\n\t"                                       \
2458          "stw 3,8(1)\n\t"                                         \
2459          /* args1-8 */                                            \
2460          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2461          "lwz 4,8(11)\n\t"                                        \
2462          "lwz 5,12(11)\n\t"                                       \
2463          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2464          "lwz 7,20(11)\n\t"                                       \
2465          "lwz 8,24(11)\n\t"                                       \
2466          "lwz 9,28(11)\n\t"                                       \
2467          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2468          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2469          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2470          VALGRIND_RESTORE_STACK                                   \
2471          "mr %0,3"                                                \
2472          : /*out*/   "=r" (_res)                                  \
2473          : /*in*/    "r" (&_argvec[0])                            \
2474          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2475       );                                                          \
2476       lval = (__typeof__(lval)) _res;                             \
2477    } while (0)
2478 
2479 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2480                                   arg7,arg8,arg9,arg10,arg11)     \
2481    do {                                                           \
2482       volatile OrigFn        _orig = (orig);                      \
2483       volatile unsigned long _argvec[12];                         \
2484       volatile unsigned long _res;                                \
2485       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2486       _argvec[1] = (unsigned long)arg1;                           \
2487       _argvec[2] = (unsigned long)arg2;                           \
2488       _argvec[3] = (unsigned long)arg3;                           \
2489       _argvec[4] = (unsigned long)arg4;                           \
2490       _argvec[5] = (unsigned long)arg5;                           \
2491       _argvec[6] = (unsigned long)arg6;                           \
2492       _argvec[7] = (unsigned long)arg7;                           \
2493       _argvec[8] = (unsigned long)arg8;                           \
2494       _argvec[9] = (unsigned long)arg9;                           \
2495       _argvec[10] = (unsigned long)arg10;                         \
2496       _argvec[11] = (unsigned long)arg11;                         \
2497       __asm__ volatile(                                           \
2498          VALGRIND_ALIGN_STACK                                     \
2499          "mr 11,%1\n\t"                                           \
2500          "addi 1,1,-32\n\t"                                       \
2501          /* arg11 */                                              \
2502          "lwz 3,44(11)\n\t"                                       \
2503          "stw 3,16(1)\n\t"                                        \
2504          /* arg10 */                                              \
2505          "lwz 3,40(11)\n\t"                                       \
2506          "stw 3,12(1)\n\t"                                        \
2507          /* arg9 */                                               \
2508          "lwz 3,36(11)\n\t"                                       \
2509          "stw 3,8(1)\n\t"                                         \
2510          /* args1-8 */                                            \
2511          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2512          "lwz 4,8(11)\n\t"                                        \
2513          "lwz 5,12(11)\n\t"                                       \
2514          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2515          "lwz 7,20(11)\n\t"                                       \
2516          "lwz 8,24(11)\n\t"                                       \
2517          "lwz 9,28(11)\n\t"                                       \
2518          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2519          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2520          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2521          VALGRIND_RESTORE_STACK                                   \
2522          "mr %0,3"                                                \
2523          : /*out*/   "=r" (_res)                                  \
2524          : /*in*/    "r" (&_argvec[0])                            \
2525          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2526       );                                                          \
2527       lval = (__typeof__(lval)) _res;                             \
2528    } while (0)
2529 
2530 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2531                                 arg7,arg8,arg9,arg10,arg11,arg12) \
2532    do {                                                           \
2533       volatile OrigFn        _orig = (orig);                      \
2534       volatile unsigned long _argvec[13];                         \
2535       volatile unsigned long _res;                                \
2536       _argvec[0] = (unsigned long)_orig.nraddr;                   \
2537       _argvec[1] = (unsigned long)arg1;                           \
2538       _argvec[2] = (unsigned long)arg2;                           \
2539       _argvec[3] = (unsigned long)arg3;                           \
2540       _argvec[4] = (unsigned long)arg4;                           \
2541       _argvec[5] = (unsigned long)arg5;                           \
2542       _argvec[6] = (unsigned long)arg6;                           \
2543       _argvec[7] = (unsigned long)arg7;                           \
2544       _argvec[8] = (unsigned long)arg8;                           \
2545       _argvec[9] = (unsigned long)arg9;                           \
2546       _argvec[10] = (unsigned long)arg10;                         \
2547       _argvec[11] = (unsigned long)arg11;                         \
2548       _argvec[12] = (unsigned long)arg12;                         \
2549       __asm__ volatile(                                           \
2550          VALGRIND_ALIGN_STACK                                     \
2551          "mr 11,%1\n\t"                                           \
2552          "addi 1,1,-32\n\t"                                       \
2553          /* arg12 */                                              \
2554          "lwz 3,48(11)\n\t"                                       \
2555          "stw 3,20(1)\n\t"                                        \
2556          /* arg11 */                                              \
2557          "lwz 3,44(11)\n\t"                                       \
2558          "stw 3,16(1)\n\t"                                        \
2559          /* arg10 */                                              \
2560          "lwz 3,40(11)\n\t"                                       \
2561          "stw 3,12(1)\n\t"                                        \
2562          /* arg9 */                                               \
2563          "lwz 3,36(11)\n\t"                                       \
2564          "stw 3,8(1)\n\t"                                         \
2565          /* args1-8 */                                            \
2566          "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2567          "lwz 4,8(11)\n\t"                                        \
2568          "lwz 5,12(11)\n\t"                                       \
2569          "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2570          "lwz 7,20(11)\n\t"                                       \
2571          "lwz 8,24(11)\n\t"                                       \
2572          "lwz 9,28(11)\n\t"                                       \
2573          "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2574          "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2575          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2576          VALGRIND_RESTORE_STACK                                   \
2577          "mr %0,3"                                                \
2578          : /*out*/   "=r" (_res)                                  \
2579          : /*in*/    "r" (&_argvec[0])                            \
2580          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2581       );                                                          \
2582       lval = (__typeof__(lval)) _res;                             \
2583    } while (0)
2584 
2585 #endif /* PLAT_ppc32_linux */
2586 
2587 /* ------------------------ ppc64-linux ------------------------ */
2588 
2589 #if defined(PLAT_ppc64be_linux)
2590 
2591 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2592 
2593 /* These regs are trashed by the hidden call. */
2594 #define __CALLER_SAVED_REGS                                       \
2595    "lr", "ctr", "xer",                                            \
2596    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
2597    "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",         \
2598    "r11", "r12", "r13"
2599 
2600 /* Macros to save and align the stack before making a function
2601    call and restore it afterwards as gcc may not keep the stack
2602    pointer aligned if it doesn't realise calls are being made
2603    to other functions. */
2604 
2605 #define VALGRIND_ALIGN_STACK               \
2606       "mr 28,1\n\t"                        \
2607       "rldicr 1,1,0,59\n\t"
2608 #define VALGRIND_RESTORE_STACK             \
2609       "mr 1,28\n\t"
2610 
2611 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2612    long) == 8. */
2613 
2614 #define CALL_FN_W_v(lval, orig)                                   \
2615    do {                                                           \
2616       volatile OrigFn        _orig = (orig);                      \
2617       volatile unsigned long _argvec[3+0];                        \
2618       volatile unsigned long _res;                                \
2619       /* _argvec[0] holds current r2 across the call */           \
2620       _argvec[1] = (unsigned long)_orig.r2;                       \
2621       _argvec[2] = (unsigned long)_orig.nraddr;                   \
2622       __asm__ volatile(                                           \
2623          VALGRIND_ALIGN_STACK                                     \
2624          "mr 11,%1\n\t"                                           \
2625          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2626          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2627          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2628          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2629          "mr 11,%1\n\t"                                           \
2630          "mr %0,3\n\t"                                            \
2631          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2632          VALGRIND_RESTORE_STACK                                   \
2633          : /*out*/   "=r" (_res)                                  \
2634          : /*in*/    "r" (&_argvec[2])                            \
2635          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2636       );                                                          \
2637       lval = (__typeof__(lval)) _res;                             \
2638    } while (0)
2639 
2640 #define CALL_FN_W_W(lval, orig, arg1)                             \
2641    do {                                                           \
2642       volatile OrigFn        _orig = (orig);                      \
2643       volatile unsigned long _argvec[3+1];                        \
2644       volatile unsigned long _res;                                \
2645       /* _argvec[0] holds current r2 across the call */           \
2646       _argvec[1]   = (unsigned long)_orig.r2;                     \
2647       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2648       _argvec[2+1] = (unsigned long)arg1;                         \
2649       __asm__ volatile(                                           \
2650          VALGRIND_ALIGN_STACK                                     \
2651          "mr 11,%1\n\t"                                           \
2652          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2653          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2654          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2655          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2656          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2657          "mr 11,%1\n\t"                                           \
2658          "mr %0,3\n\t"                                            \
2659          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2660          VALGRIND_RESTORE_STACK                                   \
2661          : /*out*/   "=r" (_res)                                  \
2662          : /*in*/    "r" (&_argvec[2])                            \
2663          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2664       );                                                          \
2665       lval = (__typeof__(lval)) _res;                             \
2666    } while (0)
2667 
2668 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
2669    do {                                                           \
2670       volatile OrigFn        _orig = (orig);                      \
2671       volatile unsigned long _argvec[3+2];                        \
2672       volatile unsigned long _res;                                \
2673       /* _argvec[0] holds current r2 across the call */           \
2674       _argvec[1]   = (unsigned long)_orig.r2;                     \
2675       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2676       _argvec[2+1] = (unsigned long)arg1;                         \
2677       _argvec[2+2] = (unsigned long)arg2;                         \
2678       __asm__ volatile(                                           \
2679          VALGRIND_ALIGN_STACK                                     \
2680          "mr 11,%1\n\t"                                           \
2681          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2682          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2683          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2684          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2685          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2686          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2687          "mr 11,%1\n\t"                                           \
2688          "mr %0,3\n\t"                                            \
2689          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2690          VALGRIND_RESTORE_STACK                                   \
2691          : /*out*/   "=r" (_res)                                  \
2692          : /*in*/    "r" (&_argvec[2])                            \
2693          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2694       );                                                          \
2695       lval = (__typeof__(lval)) _res;                             \
2696    } while (0)
2697 
2698 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2699    do {                                                           \
2700       volatile OrigFn        _orig = (orig);                      \
2701       volatile unsigned long _argvec[3+3];                        \
2702       volatile unsigned long _res;                                \
2703       /* _argvec[0] holds current r2 across the call */           \
2704       _argvec[1]   = (unsigned long)_orig.r2;                     \
2705       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2706       _argvec[2+1] = (unsigned long)arg1;                         \
2707       _argvec[2+2] = (unsigned long)arg2;                         \
2708       _argvec[2+3] = (unsigned long)arg3;                         \
2709       __asm__ volatile(                                           \
2710          VALGRIND_ALIGN_STACK                                     \
2711          "mr 11,%1\n\t"                                           \
2712          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2713          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2714          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2715          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2716          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2717          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2718          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2719          "mr 11,%1\n\t"                                           \
2720          "mr %0,3\n\t"                                            \
2721          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2722          VALGRIND_RESTORE_STACK                                   \
2723          : /*out*/   "=r" (_res)                                  \
2724          : /*in*/    "r" (&_argvec[2])                            \
2725          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2726       );                                                          \
2727       lval = (__typeof__(lval)) _res;                             \
2728    } while (0)
2729 
2730 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2731    do {                                                           \
2732       volatile OrigFn        _orig = (orig);                      \
2733       volatile unsigned long _argvec[3+4];                        \
2734       volatile unsigned long _res;                                \
2735       /* _argvec[0] holds current r2 across the call */           \
2736       _argvec[1]   = (unsigned long)_orig.r2;                     \
2737       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2738       _argvec[2+1] = (unsigned long)arg1;                         \
2739       _argvec[2+2] = (unsigned long)arg2;                         \
2740       _argvec[2+3] = (unsigned long)arg3;                         \
2741       _argvec[2+4] = (unsigned long)arg4;                         \
2742       __asm__ volatile(                                           \
2743          VALGRIND_ALIGN_STACK                                     \
2744          "mr 11,%1\n\t"                                           \
2745          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2746          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2747          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2748          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2749          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2750          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2751          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2752          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2753          "mr 11,%1\n\t"                                           \
2754          "mr %0,3\n\t"                                            \
2755          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2756          VALGRIND_RESTORE_STACK                                   \
2757          : /*out*/   "=r" (_res)                                  \
2758          : /*in*/    "r" (&_argvec[2])                            \
2759          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2760       );                                                          \
2761       lval = (__typeof__(lval)) _res;                             \
2762    } while (0)
2763 
2764 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2765    do {                                                           \
2766       volatile OrigFn        _orig = (orig);                      \
2767       volatile unsigned long _argvec[3+5];                        \
2768       volatile unsigned long _res;                                \
2769       /* _argvec[0] holds current r2 across the call */           \
2770       _argvec[1]   = (unsigned long)_orig.r2;                     \
2771       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2772       _argvec[2+1] = (unsigned long)arg1;                         \
2773       _argvec[2+2] = (unsigned long)arg2;                         \
2774       _argvec[2+3] = (unsigned long)arg3;                         \
2775       _argvec[2+4] = (unsigned long)arg4;                         \
2776       _argvec[2+5] = (unsigned long)arg5;                         \
2777       __asm__ volatile(                                           \
2778          VALGRIND_ALIGN_STACK                                     \
2779          "mr 11,%1\n\t"                                           \
2780          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2781          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2782          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2783          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2784          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2785          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2786          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2787          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2788          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2789          "mr 11,%1\n\t"                                           \
2790          "mr %0,3\n\t"                                            \
2791          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2792          VALGRIND_RESTORE_STACK                                   \
2793          : /*out*/   "=r" (_res)                                  \
2794          : /*in*/    "r" (&_argvec[2])                            \
2795          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2796       );                                                          \
2797       lval = (__typeof__(lval)) _res;                             \
2798    } while (0)
2799 
2800 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2801    do {                                                           \
2802       volatile OrigFn        _orig = (orig);                      \
2803       volatile unsigned long _argvec[3+6];                        \
2804       volatile unsigned long _res;                                \
2805       /* _argvec[0] holds current r2 across the call */           \
2806       _argvec[1]   = (unsigned long)_orig.r2;                     \
2807       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2808       _argvec[2+1] = (unsigned long)arg1;                         \
2809       _argvec[2+2] = (unsigned long)arg2;                         \
2810       _argvec[2+3] = (unsigned long)arg3;                         \
2811       _argvec[2+4] = (unsigned long)arg4;                         \
2812       _argvec[2+5] = (unsigned long)arg5;                         \
2813       _argvec[2+6] = (unsigned long)arg6;                         \
2814       __asm__ volatile(                                           \
2815          VALGRIND_ALIGN_STACK                                     \
2816          "mr 11,%1\n\t"                                           \
2817          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2818          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2819          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2820          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2821          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2822          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2823          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2824          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2825          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2826          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2827          "mr 11,%1\n\t"                                           \
2828          "mr %0,3\n\t"                                            \
2829          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2830          VALGRIND_RESTORE_STACK                                   \
2831          : /*out*/   "=r" (_res)                                  \
2832          : /*in*/    "r" (&_argvec[2])                            \
2833          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2834       );                                                          \
2835       lval = (__typeof__(lval)) _res;                             \
2836    } while (0)
2837 
2838 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2839                                  arg7)                            \
2840    do {                                                           \
2841       volatile OrigFn        _orig = (orig);                      \
2842       volatile unsigned long _argvec[3+7];                        \
2843       volatile unsigned long _res;                                \
2844       /* _argvec[0] holds current r2 across the call */           \
2845       _argvec[1]   = (unsigned long)_orig.r2;                     \
2846       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2847       _argvec[2+1] = (unsigned long)arg1;                         \
2848       _argvec[2+2] = (unsigned long)arg2;                         \
2849       _argvec[2+3] = (unsigned long)arg3;                         \
2850       _argvec[2+4] = (unsigned long)arg4;                         \
2851       _argvec[2+5] = (unsigned long)arg5;                         \
2852       _argvec[2+6] = (unsigned long)arg6;                         \
2853       _argvec[2+7] = (unsigned long)arg7;                         \
2854       __asm__ volatile(                                           \
2855          VALGRIND_ALIGN_STACK                                     \
2856          "mr 11,%1\n\t"                                           \
2857          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2858          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2859          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2860          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2861          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2862          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2863          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2864          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2865          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2866          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2867          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2868          "mr 11,%1\n\t"                                           \
2869          "mr %0,3\n\t"                                            \
2870          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2871          VALGRIND_RESTORE_STACK                                   \
2872          : /*out*/   "=r" (_res)                                  \
2873          : /*in*/    "r" (&_argvec[2])                            \
2874          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2875       );                                                          \
2876       lval = (__typeof__(lval)) _res;                             \
2877    } while (0)
2878 
2879 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2880                                  arg7,arg8)                       \
2881    do {                                                           \
2882       volatile OrigFn        _orig = (orig);                      \
2883       volatile unsigned long _argvec[3+8];                        \
2884       volatile unsigned long _res;                                \
2885       /* _argvec[0] holds current r2 across the call */           \
2886       _argvec[1]   = (unsigned long)_orig.r2;                     \
2887       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2888       _argvec[2+1] = (unsigned long)arg1;                         \
2889       _argvec[2+2] = (unsigned long)arg2;                         \
2890       _argvec[2+3] = (unsigned long)arg3;                         \
2891       _argvec[2+4] = (unsigned long)arg4;                         \
2892       _argvec[2+5] = (unsigned long)arg5;                         \
2893       _argvec[2+6] = (unsigned long)arg6;                         \
2894       _argvec[2+7] = (unsigned long)arg7;                         \
2895       _argvec[2+8] = (unsigned long)arg8;                         \
2896       __asm__ volatile(                                           \
2897          VALGRIND_ALIGN_STACK                                     \
2898          "mr 11,%1\n\t"                                           \
2899          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2900          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2901          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2902          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2903          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2904          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2905          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2906          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2907          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2908          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2909          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2910          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2911          "mr 11,%1\n\t"                                           \
2912          "mr %0,3\n\t"                                            \
2913          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2914          VALGRIND_RESTORE_STACK                                   \
2915          : /*out*/   "=r" (_res)                                  \
2916          : /*in*/    "r" (&_argvec[2])                            \
2917          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2918       );                                                          \
2919       lval = (__typeof__(lval)) _res;                             \
2920    } while (0)
2921 
2922 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2923                                  arg7,arg8,arg9)                  \
2924    do {                                                           \
2925       volatile OrigFn        _orig = (orig);                      \
2926       volatile unsigned long _argvec[3+9];                        \
2927       volatile unsigned long _res;                                \
2928       /* _argvec[0] holds current r2 across the call */           \
2929       _argvec[1]   = (unsigned long)_orig.r2;                     \
2930       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2931       _argvec[2+1] = (unsigned long)arg1;                         \
2932       _argvec[2+2] = (unsigned long)arg2;                         \
2933       _argvec[2+3] = (unsigned long)arg3;                         \
2934       _argvec[2+4] = (unsigned long)arg4;                         \
2935       _argvec[2+5] = (unsigned long)arg5;                         \
2936       _argvec[2+6] = (unsigned long)arg6;                         \
2937       _argvec[2+7] = (unsigned long)arg7;                         \
2938       _argvec[2+8] = (unsigned long)arg8;                         \
2939       _argvec[2+9] = (unsigned long)arg9;                         \
2940       __asm__ volatile(                                           \
2941          VALGRIND_ALIGN_STACK                                     \
2942          "mr 11,%1\n\t"                                           \
2943          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2944          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2945          "addi 1,1,-128\n\t"  /* expand stack frame */            \
2946          /* arg9 */                                               \
2947          "ld  3,72(11)\n\t"                                       \
2948          "std 3,112(1)\n\t"                                       \
2949          /* args1-8 */                                            \
2950          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2951          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2952          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2953          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2954          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2955          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2956          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2957          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2958          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2959          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2960          "mr 11,%1\n\t"                                           \
2961          "mr %0,3\n\t"                                            \
2962          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2963          VALGRIND_RESTORE_STACK                                   \
2964          : /*out*/   "=r" (_res)                                  \
2965          : /*in*/    "r" (&_argvec[2])                            \
2966          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2967       );                                                          \
2968       lval = (__typeof__(lval)) _res;                             \
2969    } while (0)
2970 
2971 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2972                                   arg7,arg8,arg9,arg10)           \
2973    do {                                                           \
2974       volatile OrigFn        _orig = (orig);                      \
2975       volatile unsigned long _argvec[3+10];                       \
2976       volatile unsigned long _res;                                \
2977       /* _argvec[0] holds current r2 across the call */           \
2978       _argvec[1]   = (unsigned long)_orig.r2;                     \
2979       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2980       _argvec[2+1] = (unsigned long)arg1;                         \
2981       _argvec[2+2] = (unsigned long)arg2;                         \
2982       _argvec[2+3] = (unsigned long)arg3;                         \
2983       _argvec[2+4] = (unsigned long)arg4;                         \
2984       _argvec[2+5] = (unsigned long)arg5;                         \
2985       _argvec[2+6] = (unsigned long)arg6;                         \
2986       _argvec[2+7] = (unsigned long)arg7;                         \
2987       _argvec[2+8] = (unsigned long)arg8;                         \
2988       _argvec[2+9] = (unsigned long)arg9;                         \
2989       _argvec[2+10] = (unsigned long)arg10;                       \
2990       __asm__ volatile(                                           \
2991          VALGRIND_ALIGN_STACK                                     \
2992          "mr 11,%1\n\t"                                           \
2993          "std 2,-16(11)\n\t"  /* save tocptr */                   \
2994          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2995          "addi 1,1,-128\n\t"  /* expand stack frame */            \
2996          /* arg10 */                                              \
2997          "ld  3,80(11)\n\t"                                       \
2998          "std 3,120(1)\n\t"                                       \
2999          /* arg9 */                                               \
3000          "ld  3,72(11)\n\t"                                       \
3001          "std 3,112(1)\n\t"                                       \
3002          /* args1-8 */                                            \
3003          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3004          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3005          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3006          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3007          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3008          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3009          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3010          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3011          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3012          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3013          "mr 11,%1\n\t"                                           \
3014          "mr %0,3\n\t"                                            \
3015          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3016          VALGRIND_RESTORE_STACK                                   \
3017          : /*out*/   "=r" (_res)                                  \
3018          : /*in*/    "r" (&_argvec[2])                            \
3019          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3020       );                                                          \
3021       lval = (__typeof__(lval)) _res;                             \
3022    } while (0)
3023 
3024 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3025                                   arg7,arg8,arg9,arg10,arg11)     \
3026    do {                                                           \
3027       volatile OrigFn        _orig = (orig);                      \
3028       volatile unsigned long _argvec[3+11];                       \
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       _argvec[2+3] = (unsigned long)arg3;                         \
3036       _argvec[2+4] = (unsigned long)arg4;                         \
3037       _argvec[2+5] = (unsigned long)arg5;                         \
3038       _argvec[2+6] = (unsigned long)arg6;                         \
3039       _argvec[2+7] = (unsigned long)arg7;                         \
3040       _argvec[2+8] = (unsigned long)arg8;                         \
3041       _argvec[2+9] = (unsigned long)arg9;                         \
3042       _argvec[2+10] = (unsigned long)arg10;                       \
3043       _argvec[2+11] = (unsigned long)arg11;                       \
3044       __asm__ volatile(                                           \
3045          VALGRIND_ALIGN_STACK                                     \
3046          "mr 11,%1\n\t"                                           \
3047          "std 2,-16(11)\n\t"  /* save tocptr */                   \
3048          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3049          "addi 1,1,-144\n\t"  /* expand stack frame */            \
3050          /* arg11 */                                              \
3051          "ld  3,88(11)\n\t"                                       \
3052          "std 3,128(1)\n\t"                                       \
3053          /* arg10 */                                              \
3054          "ld  3,80(11)\n\t"                                       \
3055          "std 3,120(1)\n\t"                                       \
3056          /* arg9 */                                               \
3057          "ld  3,72(11)\n\t"                                       \
3058          "std 3,112(1)\n\t"                                       \
3059          /* args1-8 */                                            \
3060          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3061          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3062          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3063          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3064          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3065          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3066          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3067          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3068          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3069          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3070          "mr 11,%1\n\t"                                           \
3071          "mr %0,3\n\t"                                            \
3072          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3073          VALGRIND_RESTORE_STACK                                   \
3074          : /*out*/   "=r" (_res)                                  \
3075          : /*in*/    "r" (&_argvec[2])                            \
3076          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3077       );                                                          \
3078       lval = (__typeof__(lval)) _res;                             \
3079    } while (0)
3080 
3081 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3082                                 arg7,arg8,arg9,arg10,arg11,arg12) \
3083    do {                                                           \
3084       volatile OrigFn        _orig = (orig);                      \
3085       volatile unsigned long _argvec[3+12];                       \
3086       volatile unsigned long _res;                                \
3087       /* _argvec[0] holds current r2 across the call */           \
3088       _argvec[1]   = (unsigned long)_orig.r2;                     \
3089       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3090       _argvec[2+1] = (unsigned long)arg1;                         \
3091       _argvec[2+2] = (unsigned long)arg2;                         \
3092       _argvec[2+3] = (unsigned long)arg3;                         \
3093       _argvec[2+4] = (unsigned long)arg4;                         \
3094       _argvec[2+5] = (unsigned long)arg5;                         \
3095       _argvec[2+6] = (unsigned long)arg6;                         \
3096       _argvec[2+7] = (unsigned long)arg7;                         \
3097       _argvec[2+8] = (unsigned long)arg8;                         \
3098       _argvec[2+9] = (unsigned long)arg9;                         \
3099       _argvec[2+10] = (unsigned long)arg10;                       \
3100       _argvec[2+11] = (unsigned long)arg11;                       \
3101       _argvec[2+12] = (unsigned long)arg12;                       \
3102       __asm__ volatile(                                           \
3103          VALGRIND_ALIGN_STACK                                     \
3104          "mr 11,%1\n\t"                                           \
3105          "std 2,-16(11)\n\t"  /* save tocptr */                   \
3106          "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3107          "addi 1,1,-144\n\t"  /* expand stack frame */            \
3108          /* arg12 */                                              \
3109          "ld  3,96(11)\n\t"                                       \
3110          "std 3,136(1)\n\t"                                       \
3111          /* arg11 */                                              \
3112          "ld  3,88(11)\n\t"                                       \
3113          "std 3,128(1)\n\t"                                       \
3114          /* arg10 */                                              \
3115          "ld  3,80(11)\n\t"                                       \
3116          "std 3,120(1)\n\t"                                       \
3117          /* arg9 */                                               \
3118          "ld  3,72(11)\n\t"                                       \
3119          "std 3,112(1)\n\t"                                       \
3120          /* args1-8 */                                            \
3121          "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3122          "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3123          "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3124          "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3125          "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3126          "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3127          "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3128          "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3129          "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3130          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3131          "mr 11,%1\n\t"                                           \
3132          "mr %0,3\n\t"                                            \
3133          "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3134          VALGRIND_RESTORE_STACK                                   \
3135          : /*out*/   "=r" (_res)                                  \
3136          : /*in*/    "r" (&_argvec[2])                            \
3137          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3138       );                                                          \
3139       lval = (__typeof__(lval)) _res;                             \
3140    } while (0)
3141 
3142 #endif /* PLAT_ppc64be_linux */
3143 
3144 /* ------------------------- ppc64le-linux ----------------------- */
3145 #if defined(PLAT_ppc64le_linux)
3146 
3147 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3148 
3149 /* These regs are trashed by the hidden call. */
3150 #define __CALLER_SAVED_REGS                                       \
3151    "lr", "ctr", "xer",                                            \
3152    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
3153    "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",         \
3154    "r11", "r12", "r13"
3155 
3156 /* Macros to save and align the stack before making a function
3157    call and restore it afterwards as gcc may not keep the stack
3158    pointer aligned if it doesn't realise calls are being made
3159    to other functions. */
3160 
3161 #define VALGRIND_ALIGN_STACK               \
3162       "mr 28,1\n\t"                        \
3163       "rldicr 1,1,0,59\n\t"
3164 #define VALGRIND_RESTORE_STACK             \
3165       "mr 1,28\n\t"
3166 
3167 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
3168    long) == 8. */
3169 
3170 #define CALL_FN_W_v(lval, orig)                                   \
3171    do {                                                           \
3172       volatile OrigFn        _orig = (orig);                      \
3173       volatile unsigned long _argvec[3+0];                        \
3174       volatile unsigned long _res;                                \
3175       /* _argvec[0] holds current r2 across the call */           \
3176       _argvec[1] = (unsigned long)_orig.r2;                       \
3177       _argvec[2] = (unsigned long)_orig.nraddr;                   \
3178       __asm__ volatile(                                           \
3179          VALGRIND_ALIGN_STACK                                     \
3180          "mr 12,%1\n\t"                                           \
3181          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3182          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3183          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3184          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3185          "mr 12,%1\n\t"                                           \
3186          "mr %0,3\n\t"                                            \
3187          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3188          VALGRIND_RESTORE_STACK                                   \
3189          : /*out*/   "=r" (_res)                                  \
3190          : /*in*/    "r" (&_argvec[2])                            \
3191          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3192       );                                                          \
3193       lval = (__typeof__(lval)) _res;                             \
3194    } while (0)
3195 
3196 #define CALL_FN_W_W(lval, orig, arg1)                             \
3197    do {                                                           \
3198       volatile OrigFn        _orig = (orig);                      \
3199       volatile unsigned long _argvec[3+1];                        \
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       __asm__ volatile(                                           \
3206          VALGRIND_ALIGN_STACK                                     \
3207          "mr 12,%1\n\t"                                           \
3208          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3209          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3210          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3211          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3212          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3213          "mr 12,%1\n\t"                                           \
3214          "mr %0,3\n\t"                                            \
3215          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3216          VALGRIND_RESTORE_STACK                                   \
3217          : /*out*/   "=r" (_res)                                  \
3218          : /*in*/    "r" (&_argvec[2])                            \
3219          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3220       );                                                          \
3221       lval = (__typeof__(lval)) _res;                             \
3222    } while (0)
3223 
3224 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
3225    do {                                                           \
3226       volatile OrigFn        _orig = (orig);                      \
3227       volatile unsigned long _argvec[3+2];                        \
3228       volatile unsigned long _res;                                \
3229       /* _argvec[0] holds current r2 across the call */           \
3230       _argvec[1]   = (unsigned long)_orig.r2;                     \
3231       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3232       _argvec[2+1] = (unsigned long)arg1;                         \
3233       _argvec[2+2] = (unsigned long)arg2;                         \
3234       __asm__ volatile(                                           \
3235          VALGRIND_ALIGN_STACK                                     \
3236          "mr 12,%1\n\t"                                           \
3237          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3238          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3239          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3240          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3241          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3242          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3243          "mr 12,%1\n\t"                                           \
3244          "mr %0,3\n\t"                                            \
3245          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3246          VALGRIND_RESTORE_STACK                                   \
3247          : /*out*/   "=r" (_res)                                  \
3248          : /*in*/    "r" (&_argvec[2])                            \
3249          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3250       );                                                          \
3251       lval = (__typeof__(lval)) _res;                             \
3252    } while (0)
3253 
3254 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
3255    do {                                                           \
3256       volatile OrigFn        _orig = (orig);                      \
3257       volatile unsigned long _argvec[3+3];                        \
3258       volatile unsigned long _res;                                \
3259       /* _argvec[0] holds current r2 across the call */           \
3260       _argvec[1]   = (unsigned long)_orig.r2;                     \
3261       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3262       _argvec[2+1] = (unsigned long)arg1;                         \
3263       _argvec[2+2] = (unsigned long)arg2;                         \
3264       _argvec[2+3] = (unsigned long)arg3;                         \
3265       __asm__ volatile(                                           \
3266          VALGRIND_ALIGN_STACK                                     \
3267          "mr 12,%1\n\t"                                           \
3268          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3269          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3270          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3271          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3272          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3273          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3274          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3275          "mr 12,%1\n\t"                                           \
3276          "mr %0,3\n\t"                                            \
3277          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3278          VALGRIND_RESTORE_STACK                                   \
3279          : /*out*/   "=r" (_res)                                  \
3280          : /*in*/    "r" (&_argvec[2])                            \
3281          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3282       );                                                          \
3283       lval = (__typeof__(lval)) _res;                             \
3284    } while (0)
3285 
3286 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
3287    do {                                                           \
3288       volatile OrigFn        _orig = (orig);                      \
3289       volatile unsigned long _argvec[3+4];                        \
3290       volatile unsigned long _res;                                \
3291       /* _argvec[0] holds current r2 across the call */           \
3292       _argvec[1]   = (unsigned long)_orig.r2;                     \
3293       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3294       _argvec[2+1] = (unsigned long)arg1;                         \
3295       _argvec[2+2] = (unsigned long)arg2;                         \
3296       _argvec[2+3] = (unsigned long)arg3;                         \
3297       _argvec[2+4] = (unsigned long)arg4;                         \
3298       __asm__ volatile(                                           \
3299          VALGRIND_ALIGN_STACK                                     \
3300          "mr 12,%1\n\t"                                           \
3301          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3302          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3303          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3304          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3305          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3306          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3307          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3308          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3309          "mr 12,%1\n\t"                                           \
3310          "mr %0,3\n\t"                                            \
3311          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3312          VALGRIND_RESTORE_STACK                                   \
3313          : /*out*/   "=r" (_res)                                  \
3314          : /*in*/    "r" (&_argvec[2])                            \
3315          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3316       );                                                          \
3317       lval = (__typeof__(lval)) _res;                             \
3318    } while (0)
3319 
3320 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
3321    do {                                                           \
3322       volatile OrigFn        _orig = (orig);                      \
3323       volatile unsigned long _argvec[3+5];                        \
3324       volatile unsigned long _res;                                \
3325       /* _argvec[0] holds current r2 across the call */           \
3326       _argvec[1]   = (unsigned long)_orig.r2;                     \
3327       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3328       _argvec[2+1] = (unsigned long)arg1;                         \
3329       _argvec[2+2] = (unsigned long)arg2;                         \
3330       _argvec[2+3] = (unsigned long)arg3;                         \
3331       _argvec[2+4] = (unsigned long)arg4;                         \
3332       _argvec[2+5] = (unsigned long)arg5;                         \
3333       __asm__ volatile(                                           \
3334          VALGRIND_ALIGN_STACK                                     \
3335          "mr 12,%1\n\t"                                           \
3336          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3337          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3338          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3339          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3340          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3341          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3342          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3343          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3344          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3345          "mr 12,%1\n\t"                                           \
3346          "mr %0,3\n\t"                                            \
3347          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3348          VALGRIND_RESTORE_STACK                                   \
3349          : /*out*/   "=r" (_res)                                  \
3350          : /*in*/    "r" (&_argvec[2])                            \
3351          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3352       );                                                          \
3353       lval = (__typeof__(lval)) _res;                             \
3354    } while (0)
3355 
3356 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
3357    do {                                                           \
3358       volatile OrigFn        _orig = (orig);                      \
3359       volatile unsigned long _argvec[3+6];                        \
3360       volatile unsigned long _res;                                \
3361       /* _argvec[0] holds current r2 across the call */           \
3362       _argvec[1]   = (unsigned long)_orig.r2;                     \
3363       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3364       _argvec[2+1] = (unsigned long)arg1;                         \
3365       _argvec[2+2] = (unsigned long)arg2;                         \
3366       _argvec[2+3] = (unsigned long)arg3;                         \
3367       _argvec[2+4] = (unsigned long)arg4;                         \
3368       _argvec[2+5] = (unsigned long)arg5;                         \
3369       _argvec[2+6] = (unsigned long)arg6;                         \
3370       __asm__ volatile(                                           \
3371          VALGRIND_ALIGN_STACK                                     \
3372          "mr 12,%1\n\t"                                           \
3373          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3374          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3375          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3376          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3377          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3378          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3379          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3380          "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3381          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3382          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3383          "mr 12,%1\n\t"                                           \
3384          "mr %0,3\n\t"                                            \
3385          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3386          VALGRIND_RESTORE_STACK                                   \
3387          : /*out*/   "=r" (_res)                                  \
3388          : /*in*/    "r" (&_argvec[2])                            \
3389          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3390       );                                                          \
3391       lval = (__typeof__(lval)) _res;                             \
3392    } while (0)
3393 
3394 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3395                                  arg7)                            \
3396    do {                                                           \
3397       volatile OrigFn        _orig = (orig);                      \
3398       volatile unsigned long _argvec[3+7];                        \
3399       volatile unsigned long _res;                                \
3400       /* _argvec[0] holds current r2 across the call */           \
3401       _argvec[1]   = (unsigned long)_orig.r2;                     \
3402       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3403       _argvec[2+1] = (unsigned long)arg1;                         \
3404       _argvec[2+2] = (unsigned long)arg2;                         \
3405       _argvec[2+3] = (unsigned long)arg3;                         \
3406       _argvec[2+4] = (unsigned long)arg4;                         \
3407       _argvec[2+5] = (unsigned long)arg5;                         \
3408       _argvec[2+6] = (unsigned long)arg6;                         \
3409       _argvec[2+7] = (unsigned long)arg7;                         \
3410       __asm__ volatile(                                           \
3411          VALGRIND_ALIGN_STACK                                     \
3412          "mr 12,%1\n\t"                                           \
3413          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3414          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3415          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3416          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3417          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3418          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3419          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3420          "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3421          "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3422          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3423          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3424          "mr 12,%1\n\t"                                           \
3425          "mr %0,3\n\t"                                            \
3426          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3427          VALGRIND_RESTORE_STACK                                   \
3428          : /*out*/   "=r" (_res)                                  \
3429          : /*in*/    "r" (&_argvec[2])                            \
3430          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3431       );                                                          \
3432       lval = (__typeof__(lval)) _res;                             \
3433    } while (0)
3434 
3435 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3436                                  arg7,arg8)                       \
3437    do {                                                           \
3438       volatile OrigFn        _orig = (orig);                      \
3439       volatile unsigned long _argvec[3+8];                        \
3440       volatile unsigned long _res;                                \
3441       /* _argvec[0] holds current r2 across the call */           \
3442       _argvec[1]   = (unsigned long)_orig.r2;                     \
3443       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3444       _argvec[2+1] = (unsigned long)arg1;                         \
3445       _argvec[2+2] = (unsigned long)arg2;                         \
3446       _argvec[2+3] = (unsigned long)arg3;                         \
3447       _argvec[2+4] = (unsigned long)arg4;                         \
3448       _argvec[2+5] = (unsigned long)arg5;                         \
3449       _argvec[2+6] = (unsigned long)arg6;                         \
3450       _argvec[2+7] = (unsigned long)arg7;                         \
3451       _argvec[2+8] = (unsigned long)arg8;                         \
3452       __asm__ volatile(                                           \
3453          VALGRIND_ALIGN_STACK                                     \
3454          "mr 12,%1\n\t"                                           \
3455          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3456          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3457          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3458          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3459          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3460          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3461          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3462          "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3463          "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3464          "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3465          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3466          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3467          "mr 12,%1\n\t"                                           \
3468          "mr %0,3\n\t"                                            \
3469          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3470          VALGRIND_RESTORE_STACK                                   \
3471          : /*out*/   "=r" (_res)                                  \
3472          : /*in*/    "r" (&_argvec[2])                            \
3473          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3474       );                                                          \
3475       lval = (__typeof__(lval)) _res;                             \
3476    } while (0)
3477 
3478 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3479                                  arg7,arg8,arg9)                  \
3480    do {                                                           \
3481       volatile OrigFn        _orig = (orig);                      \
3482       volatile unsigned long _argvec[3+9];                        \
3483       volatile unsigned long _res;                                \
3484       /* _argvec[0] holds current r2 across the call */           \
3485       _argvec[1]   = (unsigned long)_orig.r2;                     \
3486       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3487       _argvec[2+1] = (unsigned long)arg1;                         \
3488       _argvec[2+2] = (unsigned long)arg2;                         \
3489       _argvec[2+3] = (unsigned long)arg3;                         \
3490       _argvec[2+4] = (unsigned long)arg4;                         \
3491       _argvec[2+5] = (unsigned long)arg5;                         \
3492       _argvec[2+6] = (unsigned long)arg6;                         \
3493       _argvec[2+7] = (unsigned long)arg7;                         \
3494       _argvec[2+8] = (unsigned long)arg8;                         \
3495       _argvec[2+9] = (unsigned long)arg9;                         \
3496       __asm__ volatile(                                           \
3497          VALGRIND_ALIGN_STACK                                     \
3498          "mr 12,%1\n\t"                                           \
3499          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3500          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3501          "addi 1,1,-128\n\t"  /* expand stack frame */            \
3502          /* arg9 */                                               \
3503          "ld  3,72(12)\n\t"                                       \
3504          "std 3,96(1)\n\t"                                        \
3505          /* args1-8 */                                            \
3506          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3507          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3508          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3509          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3510          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3511          "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3512          "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3513          "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3514          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3515          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3516          "mr 12,%1\n\t"                                           \
3517          "mr %0,3\n\t"                                            \
3518          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3519          VALGRIND_RESTORE_STACK                                   \
3520          : /*out*/   "=r" (_res)                                  \
3521          : /*in*/    "r" (&_argvec[2])                            \
3522          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3523       );                                                          \
3524       lval = (__typeof__(lval)) _res;                             \
3525    } while (0)
3526 
3527 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3528                                   arg7,arg8,arg9,arg10)           \
3529    do {                                                           \
3530       volatile OrigFn        _orig = (orig);                      \
3531       volatile unsigned long _argvec[3+10];                       \
3532       volatile unsigned long _res;                                \
3533       /* _argvec[0] holds current r2 across the call */           \
3534       _argvec[1]   = (unsigned long)_orig.r2;                     \
3535       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3536       _argvec[2+1] = (unsigned long)arg1;                         \
3537       _argvec[2+2] = (unsigned long)arg2;                         \
3538       _argvec[2+3] = (unsigned long)arg3;                         \
3539       _argvec[2+4] = (unsigned long)arg4;                         \
3540       _argvec[2+5] = (unsigned long)arg5;                         \
3541       _argvec[2+6] = (unsigned long)arg6;                         \
3542       _argvec[2+7] = (unsigned long)arg7;                         \
3543       _argvec[2+8] = (unsigned long)arg8;                         \
3544       _argvec[2+9] = (unsigned long)arg9;                         \
3545       _argvec[2+10] = (unsigned long)arg10;                       \
3546       __asm__ volatile(                                           \
3547          VALGRIND_ALIGN_STACK                                     \
3548          "mr 12,%1\n\t"                                           \
3549          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3550          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3551          "addi 1,1,-128\n\t"  /* expand stack frame */            \
3552          /* arg10 */                                              \
3553          "ld  3,80(12)\n\t"                                       \
3554          "std 3,104(1)\n\t"                                       \
3555          /* arg9 */                                               \
3556          "ld  3,72(12)\n\t"                                       \
3557          "std 3,96(1)\n\t"                                        \
3558          /* args1-8 */                                            \
3559          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3560          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3561          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3562          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3563          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3564          "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3565          "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3566          "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3567          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3568          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3569          "mr 12,%1\n\t"                                           \
3570          "mr %0,3\n\t"                                            \
3571          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3572          VALGRIND_RESTORE_STACK                                   \
3573          : /*out*/   "=r" (_res)                                  \
3574          : /*in*/    "r" (&_argvec[2])                            \
3575          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3576       );                                                          \
3577       lval = (__typeof__(lval)) _res;                             \
3578    } while (0)
3579 
3580 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3581                                   arg7,arg8,arg9,arg10,arg11)     \
3582    do {                                                           \
3583       volatile OrigFn        _orig = (orig);                      \
3584       volatile unsigned long _argvec[3+11];                       \
3585       volatile unsigned long _res;                                \
3586       /* _argvec[0] holds current r2 across the call */           \
3587       _argvec[1]   = (unsigned long)_orig.r2;                     \
3588       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3589       _argvec[2+1] = (unsigned long)arg1;                         \
3590       _argvec[2+2] = (unsigned long)arg2;                         \
3591       _argvec[2+3] = (unsigned long)arg3;                         \
3592       _argvec[2+4] = (unsigned long)arg4;                         \
3593       _argvec[2+5] = (unsigned long)arg5;                         \
3594       _argvec[2+6] = (unsigned long)arg6;                         \
3595       _argvec[2+7] = (unsigned long)arg7;                         \
3596       _argvec[2+8] = (unsigned long)arg8;                         \
3597       _argvec[2+9] = (unsigned long)arg9;                         \
3598       _argvec[2+10] = (unsigned long)arg10;                       \
3599       _argvec[2+11] = (unsigned long)arg11;                       \
3600       __asm__ volatile(                                           \
3601          VALGRIND_ALIGN_STACK                                     \
3602          "mr 12,%1\n\t"                                           \
3603          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3604          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3605          "addi 1,1,-144\n\t"  /* expand stack frame */            \
3606          /* arg11 */                                              \
3607          "ld  3,88(12)\n\t"                                       \
3608          "std 3,112(1)\n\t"                                       \
3609          /* arg10 */                                              \
3610          "ld  3,80(12)\n\t"                                       \
3611          "std 3,104(1)\n\t"                                       \
3612          /* arg9 */                                               \
3613          "ld  3,72(12)\n\t"                                       \
3614          "std 3,96(1)\n\t"                                        \
3615          /* args1-8 */                                            \
3616          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3617          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3618          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3619          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3620          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3621          "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3622          "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3623          "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3624          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3625          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3626          "mr 12,%1\n\t"                                           \
3627          "mr %0,3\n\t"                                            \
3628          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3629          VALGRIND_RESTORE_STACK                                   \
3630          : /*out*/   "=r" (_res)                                  \
3631          : /*in*/    "r" (&_argvec[2])                            \
3632          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3633       );                                                          \
3634       lval = (__typeof__(lval)) _res;                             \
3635    } while (0)
3636 
3637 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3638                                 arg7,arg8,arg9,arg10,arg11,arg12) \
3639    do {                                                           \
3640       volatile OrigFn        _orig = (orig);                      \
3641       volatile unsigned long _argvec[3+12];                       \
3642       volatile unsigned long _res;                                \
3643       /* _argvec[0] holds current r2 across the call */           \
3644       _argvec[1]   = (unsigned long)_orig.r2;                     \
3645       _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3646       _argvec[2+1] = (unsigned long)arg1;                         \
3647       _argvec[2+2] = (unsigned long)arg2;                         \
3648       _argvec[2+3] = (unsigned long)arg3;                         \
3649       _argvec[2+4] = (unsigned long)arg4;                         \
3650       _argvec[2+5] = (unsigned long)arg5;                         \
3651       _argvec[2+6] = (unsigned long)arg6;                         \
3652       _argvec[2+7] = (unsigned long)arg7;                         \
3653       _argvec[2+8] = (unsigned long)arg8;                         \
3654       _argvec[2+9] = (unsigned long)arg9;                         \
3655       _argvec[2+10] = (unsigned long)arg10;                       \
3656       _argvec[2+11] = (unsigned long)arg11;                       \
3657       _argvec[2+12] = (unsigned long)arg12;                       \
3658       __asm__ volatile(                                           \
3659          VALGRIND_ALIGN_STACK                                     \
3660          "mr 12,%1\n\t"                                           \
3661          "std 2,-16(12)\n\t"  /* save tocptr */                   \
3662          "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3663          "addi 1,1,-144\n\t"  /* expand stack frame */            \
3664          /* arg12 */                                              \
3665          "ld  3,96(12)\n\t"                                       \
3666          "std 3,120(1)\n\t"                                       \
3667          /* arg11 */                                              \
3668          "ld  3,88(12)\n\t"                                       \
3669          "std 3,112(1)\n\t"                                       \
3670          /* arg10 */                                              \
3671          "ld  3,80(12)\n\t"                                       \
3672          "std 3,104(1)\n\t"                                       \
3673          /* arg9 */                                               \
3674          "ld  3,72(12)\n\t"                                       \
3675          "std 3,96(1)\n\t"                                        \
3676          /* args1-8 */                                            \
3677          "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3678          "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3679          "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3680          "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3681          "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3682          "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3683          "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3684          "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3685          "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3686          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3687          "mr 12,%1\n\t"                                           \
3688          "mr %0,3\n\t"                                            \
3689          "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3690          VALGRIND_RESTORE_STACK                                   \
3691          : /*out*/   "=r" (_res)                                  \
3692          : /*in*/    "r" (&_argvec[2])                            \
3693          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3694       );                                                          \
3695       lval = (__typeof__(lval)) _res;                             \
3696    } while (0)
3697 
3698 #endif /* PLAT_ppc64le_linux */
3699 
3700 /* ------------------------- arm-linux ------------------------- */
3701 
3702 #if defined(PLAT_arm_linux)
3703 
3704 /* These regs are trashed by the hidden call. */
3705 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4", "r12", "r14"
3706 
3707 /* Macros to save and align the stack before making a function
3708    call and restore it afterwards as gcc may not keep the stack
3709    pointer aligned if it doesn't realise calls are being made
3710    to other functions. */
3711 
3712 /* This is a bit tricky.  We store the original stack pointer in r10
3713    as it is callee-saves.  gcc doesn't allow the use of r11 for some
3714    reason.  Also, we can't directly "bic" the stack pointer in thumb
3715    mode since r13 isn't an allowed register number in that context.
3716    So use r4 as a temporary, since that is about to get trashed
3717    anyway, just after each use of this macro.  Side effect is we need
3718    to be very careful about any future changes, since
3719    VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
3720 #define VALGRIND_ALIGN_STACK               \
3721       "mov r10, sp\n\t"                    \
3722       "mov r4,  sp\n\t"                    \
3723       "bic r4,  r4, #7\n\t"                \
3724       "mov sp,  r4\n\t"
3725 #define VALGRIND_RESTORE_STACK             \
3726       "mov sp,  r10\n\t"
3727 
3728 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3729    long) == 4. */
3730 
3731 #define CALL_FN_W_v(lval, orig)                                   \
3732    do {                                                           \
3733       volatile OrigFn        _orig = (orig);                      \
3734       volatile unsigned long _argvec[1];                          \
3735       volatile unsigned long _res;                                \
3736       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3737       __asm__ volatile(                                           \
3738          VALGRIND_ALIGN_STACK                                     \
3739          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3740          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3741          VALGRIND_RESTORE_STACK                                   \
3742          "mov %0, r0\n"                                           \
3743          : /*out*/   "=r" (_res)                                  \
3744          : /*in*/    "0" (&_argvec[0])                            \
3745          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3746       );                                                          \
3747       lval = (__typeof__(lval)) _res;                             \
3748    } while (0)
3749 
3750 #define CALL_FN_W_W(lval, orig, arg1)                             \
3751    do {                                                           \
3752       volatile OrigFn        _orig = (orig);                      \
3753       volatile unsigned long _argvec[2];                          \
3754       volatile unsigned long _res;                                \
3755       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3756       _argvec[1] = (unsigned long)(arg1);                         \
3757       __asm__ volatile(                                           \
3758          VALGRIND_ALIGN_STACK                                     \
3759          "ldr r0, [%1, #4] \n\t"                                  \
3760          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3761          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3762          VALGRIND_RESTORE_STACK                                   \
3763          "mov %0, r0\n"                                           \
3764          : /*out*/   "=r" (_res)                                  \
3765          : /*in*/    "0" (&_argvec[0])                            \
3766          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3767       );                                                          \
3768       lval = (__typeof__(lval)) _res;                             \
3769    } while (0)
3770 
3771 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
3772    do {                                                           \
3773       volatile OrigFn        _orig = (orig);                      \
3774       volatile unsigned long _argvec[3];                          \
3775       volatile unsigned long _res;                                \
3776       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3777       _argvec[1] = (unsigned long)(arg1);                         \
3778       _argvec[2] = (unsigned long)(arg2);                         \
3779       __asm__ volatile(                                           \
3780          VALGRIND_ALIGN_STACK                                     \
3781          "ldr r0, [%1, #4] \n\t"                                  \
3782          "ldr r1, [%1, #8] \n\t"                                  \
3783          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3784          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3785          VALGRIND_RESTORE_STACK                                   \
3786          "mov %0, r0\n"                                           \
3787          : /*out*/   "=r" (_res)                                  \
3788          : /*in*/    "0" (&_argvec[0])                            \
3789          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3790       );                                                          \
3791       lval = (__typeof__(lval)) _res;                             \
3792    } while (0)
3793 
3794 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
3795    do {                                                           \
3796       volatile OrigFn        _orig = (orig);                      \
3797       volatile unsigned long _argvec[4];                          \
3798       volatile unsigned long _res;                                \
3799       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3800       _argvec[1] = (unsigned long)(arg1);                         \
3801       _argvec[2] = (unsigned long)(arg2);                         \
3802       _argvec[3] = (unsigned long)(arg3);                         \
3803       __asm__ volatile(                                           \
3804          VALGRIND_ALIGN_STACK                                     \
3805          "ldr r0, [%1, #4] \n\t"                                  \
3806          "ldr r1, [%1, #8] \n\t"                                  \
3807          "ldr r2, [%1, #12] \n\t"                                 \
3808          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3809          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3810          VALGRIND_RESTORE_STACK                                   \
3811          "mov %0, r0\n"                                           \
3812          : /*out*/   "=r" (_res)                                  \
3813          : /*in*/    "0" (&_argvec[0])                            \
3814          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3815       );                                                          \
3816       lval = (__typeof__(lval)) _res;                             \
3817    } while (0)
3818 
3819 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
3820    do {                                                           \
3821       volatile OrigFn        _orig = (orig);                      \
3822       volatile unsigned long _argvec[5];                          \
3823       volatile unsigned long _res;                                \
3824       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3825       _argvec[1] = (unsigned long)(arg1);                         \
3826       _argvec[2] = (unsigned long)(arg2);                         \
3827       _argvec[3] = (unsigned long)(arg3);                         \
3828       _argvec[4] = (unsigned long)(arg4);                         \
3829       __asm__ volatile(                                           \
3830          VALGRIND_ALIGN_STACK                                     \
3831          "ldr r0, [%1, #4] \n\t"                                  \
3832          "ldr r1, [%1, #8] \n\t"                                  \
3833          "ldr r2, [%1, #12] \n\t"                                 \
3834          "ldr r3, [%1, #16] \n\t"                                 \
3835          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3836          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3837          VALGRIND_RESTORE_STACK                                   \
3838          "mov %0, r0"                                             \
3839          : /*out*/   "=r" (_res)                                  \
3840          : /*in*/    "0" (&_argvec[0])                            \
3841          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3842       );                                                          \
3843       lval = (__typeof__(lval)) _res;                             \
3844    } while (0)
3845 
3846 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
3847    do {                                                           \
3848       volatile OrigFn        _orig = (orig);                      \
3849       volatile unsigned long _argvec[6];                          \
3850       volatile unsigned long _res;                                \
3851       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3852       _argvec[1] = (unsigned long)(arg1);                         \
3853       _argvec[2] = (unsigned long)(arg2);                         \
3854       _argvec[3] = (unsigned long)(arg3);                         \
3855       _argvec[4] = (unsigned long)(arg4);                         \
3856       _argvec[5] = (unsigned long)(arg5);                         \
3857       __asm__ volatile(                                           \
3858          VALGRIND_ALIGN_STACK                                     \
3859          "sub sp, sp, #4 \n\t"                                    \
3860          "ldr r0, [%1, #20] \n\t"                                 \
3861          "push {r0} \n\t"                                         \
3862          "ldr r0, [%1, #4] \n\t"                                  \
3863          "ldr r1, [%1, #8] \n\t"                                  \
3864          "ldr r2, [%1, #12] \n\t"                                 \
3865          "ldr r3, [%1, #16] \n\t"                                 \
3866          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3867          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3868          VALGRIND_RESTORE_STACK                                   \
3869          "mov %0, r0"                                             \
3870          : /*out*/   "=r" (_res)                                  \
3871          : /*in*/    "0" (&_argvec[0])                            \
3872          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3873       );                                                          \
3874       lval = (__typeof__(lval)) _res;                             \
3875    } while (0)
3876 
3877 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
3878    do {                                                           \
3879       volatile OrigFn        _orig = (orig);                      \
3880       volatile unsigned long _argvec[7];                          \
3881       volatile unsigned long _res;                                \
3882       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3883       _argvec[1] = (unsigned long)(arg1);                         \
3884       _argvec[2] = (unsigned long)(arg2);                         \
3885       _argvec[3] = (unsigned long)(arg3);                         \
3886       _argvec[4] = (unsigned long)(arg4);                         \
3887       _argvec[5] = (unsigned long)(arg5);                         \
3888       _argvec[6] = (unsigned long)(arg6);                         \
3889       __asm__ volatile(                                           \
3890          VALGRIND_ALIGN_STACK                                     \
3891          "ldr r0, [%1, #20] \n\t"                                 \
3892          "ldr r1, [%1, #24] \n\t"                                 \
3893          "push {r0, r1} \n\t"                                     \
3894          "ldr r0, [%1, #4] \n\t"                                  \
3895          "ldr r1, [%1, #8] \n\t"                                  \
3896          "ldr r2, [%1, #12] \n\t"                                 \
3897          "ldr r3, [%1, #16] \n\t"                                 \
3898          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3899          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3900          VALGRIND_RESTORE_STACK                                   \
3901          "mov %0, r0"                                             \
3902          : /*out*/   "=r" (_res)                                  \
3903          : /*in*/    "0" (&_argvec[0])                            \
3904          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3905       );                                                          \
3906       lval = (__typeof__(lval)) _res;                             \
3907    } while (0)
3908 
3909 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3910                                  arg7)                            \
3911    do {                                                           \
3912       volatile OrigFn        _orig = (orig);                      \
3913       volatile unsigned long _argvec[8];                          \
3914       volatile unsigned long _res;                                \
3915       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3916       _argvec[1] = (unsigned long)(arg1);                         \
3917       _argvec[2] = (unsigned long)(arg2);                         \
3918       _argvec[3] = (unsigned long)(arg3);                         \
3919       _argvec[4] = (unsigned long)(arg4);                         \
3920       _argvec[5] = (unsigned long)(arg5);                         \
3921       _argvec[6] = (unsigned long)(arg6);                         \
3922       _argvec[7] = (unsigned long)(arg7);                         \
3923       __asm__ volatile(                                           \
3924          VALGRIND_ALIGN_STACK                                     \
3925          "sub sp, sp, #4 \n\t"                                    \
3926          "ldr r0, [%1, #20] \n\t"                                 \
3927          "ldr r1, [%1, #24] \n\t"                                 \
3928          "ldr r2, [%1, #28] \n\t"                                 \
3929          "push {r0, r1, r2} \n\t"                                 \
3930          "ldr r0, [%1, #4] \n\t"                                  \
3931          "ldr r1, [%1, #8] \n\t"                                  \
3932          "ldr r2, [%1, #12] \n\t"                                 \
3933          "ldr r3, [%1, #16] \n\t"                                 \
3934          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3935          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3936          VALGRIND_RESTORE_STACK                                   \
3937          "mov %0, r0"                                             \
3938          : /*out*/   "=r" (_res)                                  \
3939          : /*in*/    "0" (&_argvec[0])                            \
3940          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3941       );                                                          \
3942       lval = (__typeof__(lval)) _res;                             \
3943    } while (0)
3944 
3945 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3946                                  arg7,arg8)                       \
3947    do {                                                           \
3948       volatile OrigFn        _orig = (orig);                      \
3949       volatile unsigned long _argvec[9];                          \
3950       volatile unsigned long _res;                                \
3951       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3952       _argvec[1] = (unsigned long)(arg1);                         \
3953       _argvec[2] = (unsigned long)(arg2);                         \
3954       _argvec[3] = (unsigned long)(arg3);                         \
3955       _argvec[4] = (unsigned long)(arg4);                         \
3956       _argvec[5] = (unsigned long)(arg5);                         \
3957       _argvec[6] = (unsigned long)(arg6);                         \
3958       _argvec[7] = (unsigned long)(arg7);                         \
3959       _argvec[8] = (unsigned long)(arg8);                         \
3960       __asm__ volatile(                                           \
3961          VALGRIND_ALIGN_STACK                                     \
3962          "ldr r0, [%1, #20] \n\t"                                 \
3963          "ldr r1, [%1, #24] \n\t"                                 \
3964          "ldr r2, [%1, #28] \n\t"                                 \
3965          "ldr r3, [%1, #32] \n\t"                                 \
3966          "push {r0, r1, r2, r3} \n\t"                             \
3967          "ldr r0, [%1, #4] \n\t"                                  \
3968          "ldr r1, [%1, #8] \n\t"                                  \
3969          "ldr r2, [%1, #12] \n\t"                                 \
3970          "ldr r3, [%1, #16] \n\t"                                 \
3971          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3972          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3973          VALGRIND_RESTORE_STACK                                   \
3974          "mov %0, r0"                                             \
3975          : /*out*/   "=r" (_res)                                  \
3976          : /*in*/    "0" (&_argvec[0])                            \
3977          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3978       );                                                          \
3979       lval = (__typeof__(lval)) _res;                             \
3980    } while (0)
3981 
3982 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3983                                  arg7,arg8,arg9)                  \
3984    do {                                                           \
3985       volatile OrigFn        _orig = (orig);                      \
3986       volatile unsigned long _argvec[10];                         \
3987       volatile unsigned long _res;                                \
3988       _argvec[0] = (unsigned long)_orig.nraddr;                   \
3989       _argvec[1] = (unsigned long)(arg1);                         \
3990       _argvec[2] = (unsigned long)(arg2);                         \
3991       _argvec[3] = (unsigned long)(arg3);                         \
3992       _argvec[4] = (unsigned long)(arg4);                         \
3993       _argvec[5] = (unsigned long)(arg5);                         \
3994       _argvec[6] = (unsigned long)(arg6);                         \
3995       _argvec[7] = (unsigned long)(arg7);                         \
3996       _argvec[8] = (unsigned long)(arg8);                         \
3997       _argvec[9] = (unsigned long)(arg9);                         \
3998       __asm__ volatile(                                           \
3999          VALGRIND_ALIGN_STACK                                     \
4000          "sub sp, sp, #4 \n\t"                                    \
4001          "ldr r0, [%1, #20] \n\t"                                 \
4002          "ldr r1, [%1, #24] \n\t"                                 \
4003          "ldr r2, [%1, #28] \n\t"                                 \
4004          "ldr r3, [%1, #32] \n\t"                                 \
4005          "ldr r4, [%1, #36] \n\t"                                 \
4006          "push {r0, r1, r2, r3, r4} \n\t"                         \
4007          "ldr r0, [%1, #4] \n\t"                                  \
4008          "ldr r1, [%1, #8] \n\t"                                  \
4009          "ldr r2, [%1, #12] \n\t"                                 \
4010          "ldr r3, [%1, #16] \n\t"                                 \
4011          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4012          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4013          VALGRIND_RESTORE_STACK                                   \
4014          "mov %0, r0"                                             \
4015          : /*out*/   "=r" (_res)                                  \
4016          : /*in*/    "0" (&_argvec[0])                            \
4017          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4018       );                                                          \
4019       lval = (__typeof__(lval)) _res;                             \
4020    } while (0)
4021 
4022 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4023                                   arg7,arg8,arg9,arg10)           \
4024    do {                                                           \
4025       volatile OrigFn        _orig = (orig);                      \
4026       volatile unsigned long _argvec[11];                         \
4027       volatile unsigned long _res;                                \
4028       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4029       _argvec[1] = (unsigned long)(arg1);                         \
4030       _argvec[2] = (unsigned long)(arg2);                         \
4031       _argvec[3] = (unsigned long)(arg3);                         \
4032       _argvec[4] = (unsigned long)(arg4);                         \
4033       _argvec[5] = (unsigned long)(arg5);                         \
4034       _argvec[6] = (unsigned long)(arg6);                         \
4035       _argvec[7] = (unsigned long)(arg7);                         \
4036       _argvec[8] = (unsigned long)(arg8);                         \
4037       _argvec[9] = (unsigned long)(arg9);                         \
4038       _argvec[10] = (unsigned long)(arg10);                       \
4039       __asm__ volatile(                                           \
4040          VALGRIND_ALIGN_STACK                                     \
4041          "ldr r0, [%1, #40] \n\t"                                 \
4042          "push {r0} \n\t"                                         \
4043          "ldr r0, [%1, #20] \n\t"                                 \
4044          "ldr r1, [%1, #24] \n\t"                                 \
4045          "ldr r2, [%1, #28] \n\t"                                 \
4046          "ldr r3, [%1, #32] \n\t"                                 \
4047          "ldr r4, [%1, #36] \n\t"                                 \
4048          "push {r0, r1, r2, r3, r4} \n\t"                         \
4049          "ldr r0, [%1, #4] \n\t"                                  \
4050          "ldr r1, [%1, #8] \n\t"                                  \
4051          "ldr r2, [%1, #12] \n\t"                                 \
4052          "ldr r3, [%1, #16] \n\t"                                 \
4053          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4054          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4055          VALGRIND_RESTORE_STACK                                   \
4056          "mov %0, r0"                                             \
4057          : /*out*/   "=r" (_res)                                  \
4058          : /*in*/    "0" (&_argvec[0])                            \
4059          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4060       );                                                          \
4061       lval = (__typeof__(lval)) _res;                             \
4062    } while (0)
4063 
4064 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
4065                                   arg6,arg7,arg8,arg9,arg10,      \
4066                                   arg11)                          \
4067    do {                                                           \
4068       volatile OrigFn        _orig = (orig);                      \
4069       volatile unsigned long _argvec[12];                         \
4070       volatile unsigned long _res;                                \
4071       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4072       _argvec[1] = (unsigned long)(arg1);                         \
4073       _argvec[2] = (unsigned long)(arg2);                         \
4074       _argvec[3] = (unsigned long)(arg3);                         \
4075       _argvec[4] = (unsigned long)(arg4);                         \
4076       _argvec[5] = (unsigned long)(arg5);                         \
4077       _argvec[6] = (unsigned long)(arg6);                         \
4078       _argvec[7] = (unsigned long)(arg7);                         \
4079       _argvec[8] = (unsigned long)(arg8);                         \
4080       _argvec[9] = (unsigned long)(arg9);                         \
4081       _argvec[10] = (unsigned long)(arg10);                       \
4082       _argvec[11] = (unsigned long)(arg11);                       \
4083       __asm__ volatile(                                           \
4084          VALGRIND_ALIGN_STACK                                     \
4085          "sub sp, sp, #4 \n\t"                                    \
4086          "ldr r0, [%1, #40] \n\t"                                 \
4087          "ldr r1, [%1, #44] \n\t"                                 \
4088          "push {r0, r1} \n\t"                                     \
4089          "ldr r0, [%1, #20] \n\t"                                 \
4090          "ldr r1, [%1, #24] \n\t"                                 \
4091          "ldr r2, [%1, #28] \n\t"                                 \
4092          "ldr r3, [%1, #32] \n\t"                                 \
4093          "ldr r4, [%1, #36] \n\t"                                 \
4094          "push {r0, r1, r2, r3, r4} \n\t"                         \
4095          "ldr r0, [%1, #4] \n\t"                                  \
4096          "ldr r1, [%1, #8] \n\t"                                  \
4097          "ldr r2, [%1, #12] \n\t"                                 \
4098          "ldr r3, [%1, #16] \n\t"                                 \
4099          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4100          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4101          VALGRIND_RESTORE_STACK                                   \
4102          "mov %0, r0"                                             \
4103          : /*out*/   "=r" (_res)                                  \
4104          : /*in*/    "0" (&_argvec[0])                            \
4105          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4106       );                                                          \
4107       lval = (__typeof__(lval)) _res;                             \
4108    } while (0)
4109 
4110 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
4111                                   arg6,arg7,arg8,arg9,arg10,      \
4112                                   arg11,arg12)                    \
4113    do {                                                           \
4114       volatile OrigFn        _orig = (orig);                      \
4115       volatile unsigned long _argvec[13];                         \
4116       volatile unsigned long _res;                                \
4117       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4118       _argvec[1] = (unsigned long)(arg1);                         \
4119       _argvec[2] = (unsigned long)(arg2);                         \
4120       _argvec[3] = (unsigned long)(arg3);                         \
4121       _argvec[4] = (unsigned long)(arg4);                         \
4122       _argvec[5] = (unsigned long)(arg5);                         \
4123       _argvec[6] = (unsigned long)(arg6);                         \
4124       _argvec[7] = (unsigned long)(arg7);                         \
4125       _argvec[8] = (unsigned long)(arg8);                         \
4126       _argvec[9] = (unsigned long)(arg9);                         \
4127       _argvec[10] = (unsigned long)(arg10);                       \
4128       _argvec[11] = (unsigned long)(arg11);                       \
4129       _argvec[12] = (unsigned long)(arg12);                       \
4130       __asm__ volatile(                                           \
4131          VALGRIND_ALIGN_STACK                                     \
4132          "ldr r0, [%1, #40] \n\t"                                 \
4133          "ldr r1, [%1, #44] \n\t"                                 \
4134          "ldr r2, [%1, #48] \n\t"                                 \
4135          "push {r0, r1, r2} \n\t"                                 \
4136          "ldr r0, [%1, #20] \n\t"                                 \
4137          "ldr r1, [%1, #24] \n\t"                                 \
4138          "ldr r2, [%1, #28] \n\t"                                 \
4139          "ldr r3, [%1, #32] \n\t"                                 \
4140          "ldr r4, [%1, #36] \n\t"                                 \
4141          "push {r0, r1, r2, r3, r4} \n\t"                         \
4142          "ldr r0, [%1, #4] \n\t"                                  \
4143          "ldr r1, [%1, #8] \n\t"                                  \
4144          "ldr r2, [%1, #12] \n\t"                                 \
4145          "ldr r3, [%1, #16] \n\t"                                 \
4146          "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4147          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4148          VALGRIND_RESTORE_STACK                                   \
4149          "mov %0, r0"                                             \
4150          : /*out*/   "=r" (_res)                                  \
4151          : /*in*/    "0" (&_argvec[0])                            \
4152          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4153       );                                                          \
4154       lval = (__typeof__(lval)) _res;                             \
4155    } while (0)
4156 
4157 #endif /* PLAT_arm_linux */
4158 
4159 /* ------------------------ arm64-linux ------------------------ */
4160 
4161 #if defined(PLAT_arm64_linux)
4162 
4163 /* These regs are trashed by the hidden call. */
4164 #define __CALLER_SAVED_REGS \
4165      "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9",   \
4166      "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17",      \
4167      "x18", "x19", "x20", "x30",                                  \
4168      "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",  \
4169      "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17",      \
4170      "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25",      \
4171      "v26", "v27", "v28", "v29", "v30", "v31"
4172 
4173 /* x21 is callee-saved, so we can use it to save and restore SP around
4174    the hidden call. */
4175 #define VALGRIND_ALIGN_STACK               \
4176       "mov x21, sp\n\t"                    \
4177       "bic sp, x21, #15\n\t"
4178 #define VALGRIND_RESTORE_STACK             \
4179       "mov sp,  x21\n\t"
4180 
4181 /* These CALL_FN_ macros assume that on arm64-linux,
4182    sizeof(unsigned long) == 8. */
4183 
4184 #define CALL_FN_W_v(lval, orig)                                   \
4185    do {                                                           \
4186       volatile OrigFn        _orig = (orig);                      \
4187       volatile unsigned long _argvec[1];                          \
4188       volatile unsigned long _res;                                \
4189       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4190       __asm__ volatile(                                           \
4191          VALGRIND_ALIGN_STACK                                     \
4192          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4193          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4194          VALGRIND_RESTORE_STACK                                   \
4195          "mov %0, x0\n"                                           \
4196          : /*out*/   "=r" (_res)                                  \
4197          : /*in*/    "0" (&_argvec[0])                            \
4198          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4199       );                                                          \
4200       lval = (__typeof__(lval)) _res;                             \
4201    } while (0)
4202 
4203 #define CALL_FN_W_W(lval, orig, arg1)                             \
4204    do {                                                           \
4205       volatile OrigFn        _orig = (orig);                      \
4206       volatile unsigned long _argvec[2];                          \
4207       volatile unsigned long _res;                                \
4208       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4209       _argvec[1] = (unsigned long)(arg1);                         \
4210       __asm__ volatile(                                           \
4211          VALGRIND_ALIGN_STACK                                     \
4212          "ldr x0, [%1, #8] \n\t"                                  \
4213          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4214          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4215          VALGRIND_RESTORE_STACK                                   \
4216          "mov %0, x0\n"                                           \
4217          : /*out*/   "=r" (_res)                                  \
4218          : /*in*/    "0" (&_argvec[0])                            \
4219          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4220       );                                                          \
4221       lval = (__typeof__(lval)) _res;                             \
4222    } while (0)
4223 
4224 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
4225    do {                                                           \
4226       volatile OrigFn        _orig = (orig);                      \
4227       volatile unsigned long _argvec[3];                          \
4228       volatile unsigned long _res;                                \
4229       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4230       _argvec[1] = (unsigned long)(arg1);                         \
4231       _argvec[2] = (unsigned long)(arg2);                         \
4232       __asm__ volatile(                                           \
4233          VALGRIND_ALIGN_STACK                                     \
4234          "ldr x0, [%1, #8] \n\t"                                  \
4235          "ldr x1, [%1, #16] \n\t"                                 \
4236          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4237          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4238          VALGRIND_RESTORE_STACK                                   \
4239          "mov %0, x0\n"                                           \
4240          : /*out*/   "=r" (_res)                                  \
4241          : /*in*/    "0" (&_argvec[0])                            \
4242          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4243       );                                                          \
4244       lval = (__typeof__(lval)) _res;                             \
4245    } while (0)
4246 
4247 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
4248    do {                                                           \
4249       volatile OrigFn        _orig = (orig);                      \
4250       volatile unsigned long _argvec[4];                          \
4251       volatile unsigned long _res;                                \
4252       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4253       _argvec[1] = (unsigned long)(arg1);                         \
4254       _argvec[2] = (unsigned long)(arg2);                         \
4255       _argvec[3] = (unsigned long)(arg3);                         \
4256       __asm__ volatile(                                           \
4257          VALGRIND_ALIGN_STACK                                     \
4258          "ldr x0, [%1, #8] \n\t"                                  \
4259          "ldr x1, [%1, #16] \n\t"                                 \
4260          "ldr x2, [%1, #24] \n\t"                                 \
4261          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4262          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4263          VALGRIND_RESTORE_STACK                                   \
4264          "mov %0, x0\n"                                           \
4265          : /*out*/   "=r" (_res)                                  \
4266          : /*in*/    "0" (&_argvec[0])                            \
4267          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4268       );                                                          \
4269       lval = (__typeof__(lval)) _res;                             \
4270    } while (0)
4271 
4272 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
4273    do {                                                           \
4274       volatile OrigFn        _orig = (orig);                      \
4275       volatile unsigned long _argvec[5];                          \
4276       volatile unsigned long _res;                                \
4277       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4278       _argvec[1] = (unsigned long)(arg1);                         \
4279       _argvec[2] = (unsigned long)(arg2);                         \
4280       _argvec[3] = (unsigned long)(arg3);                         \
4281       _argvec[4] = (unsigned long)(arg4);                         \
4282       __asm__ volatile(                                           \
4283          VALGRIND_ALIGN_STACK                                     \
4284          "ldr x0, [%1, #8] \n\t"                                  \
4285          "ldr x1, [%1, #16] \n\t"                                 \
4286          "ldr x2, [%1, #24] \n\t"                                 \
4287          "ldr x3, [%1, #32] \n\t"                                 \
4288          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4289          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4290          VALGRIND_RESTORE_STACK                                   \
4291          "mov %0, x0"                                             \
4292          : /*out*/   "=r" (_res)                                  \
4293          : /*in*/    "0" (&_argvec[0])                            \
4294          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4295       );                                                          \
4296       lval = (__typeof__(lval)) _res;                             \
4297    } while (0)
4298 
4299 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
4300    do {                                                           \
4301       volatile OrigFn        _orig = (orig);                      \
4302       volatile unsigned long _argvec[6];                          \
4303       volatile unsigned long _res;                                \
4304       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4305       _argvec[1] = (unsigned long)(arg1);                         \
4306       _argvec[2] = (unsigned long)(arg2);                         \
4307       _argvec[3] = (unsigned long)(arg3);                         \
4308       _argvec[4] = (unsigned long)(arg4);                         \
4309       _argvec[5] = (unsigned long)(arg5);                         \
4310       __asm__ volatile(                                           \
4311          VALGRIND_ALIGN_STACK                                     \
4312          "ldr x0, [%1, #8] \n\t"                                  \
4313          "ldr x1, [%1, #16] \n\t"                                 \
4314          "ldr x2, [%1, #24] \n\t"                                 \
4315          "ldr x3, [%1, #32] \n\t"                                 \
4316          "ldr x4, [%1, #40] \n\t"                                 \
4317          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4318          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4319          VALGRIND_RESTORE_STACK                                   \
4320          "mov %0, x0"                                             \
4321          : /*out*/   "=r" (_res)                                  \
4322          : /*in*/    "0" (&_argvec[0])                            \
4323          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4324       );                                                          \
4325       lval = (__typeof__(lval)) _res;                             \
4326    } while (0)
4327 
4328 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
4329    do {                                                           \
4330       volatile OrigFn        _orig = (orig);                      \
4331       volatile unsigned long _argvec[7];                          \
4332       volatile unsigned long _res;                                \
4333       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4334       _argvec[1] = (unsigned long)(arg1);                         \
4335       _argvec[2] = (unsigned long)(arg2);                         \
4336       _argvec[3] = (unsigned long)(arg3);                         \
4337       _argvec[4] = (unsigned long)(arg4);                         \
4338       _argvec[5] = (unsigned long)(arg5);                         \
4339       _argvec[6] = (unsigned long)(arg6);                         \
4340       __asm__ volatile(                                           \
4341          VALGRIND_ALIGN_STACK                                     \
4342          "ldr x0, [%1, #8] \n\t"                                  \
4343          "ldr x1, [%1, #16] \n\t"                                 \
4344          "ldr x2, [%1, #24] \n\t"                                 \
4345          "ldr x3, [%1, #32] \n\t"                                 \
4346          "ldr x4, [%1, #40] \n\t"                                 \
4347          "ldr x5, [%1, #48] \n\t"                                 \
4348          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4349          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4350          VALGRIND_RESTORE_STACK                                   \
4351          "mov %0, x0"                                             \
4352          : /*out*/   "=r" (_res)                                  \
4353          : /*in*/    "0" (&_argvec[0])                            \
4354          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4355       );                                                          \
4356       lval = (__typeof__(lval)) _res;                             \
4357    } while (0)
4358 
4359 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4360                                  arg7)                            \
4361    do {                                                           \
4362       volatile OrigFn        _orig = (orig);                      \
4363       volatile unsigned long _argvec[8];                          \
4364       volatile unsigned long _res;                                \
4365       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4366       _argvec[1] = (unsigned long)(arg1);                         \
4367       _argvec[2] = (unsigned long)(arg2);                         \
4368       _argvec[3] = (unsigned long)(arg3);                         \
4369       _argvec[4] = (unsigned long)(arg4);                         \
4370       _argvec[5] = (unsigned long)(arg5);                         \
4371       _argvec[6] = (unsigned long)(arg6);                         \
4372       _argvec[7] = (unsigned long)(arg7);                         \
4373       __asm__ volatile(                                           \
4374          VALGRIND_ALIGN_STACK                                     \
4375          "ldr x0, [%1, #8] \n\t"                                  \
4376          "ldr x1, [%1, #16] \n\t"                                 \
4377          "ldr x2, [%1, #24] \n\t"                                 \
4378          "ldr x3, [%1, #32] \n\t"                                 \
4379          "ldr x4, [%1, #40] \n\t"                                 \
4380          "ldr x5, [%1, #48] \n\t"                                 \
4381          "ldr x6, [%1, #56] \n\t"                                 \
4382          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4383          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4384          VALGRIND_RESTORE_STACK                                   \
4385          "mov %0, x0"                                             \
4386          : /*out*/   "=r" (_res)                                  \
4387          : /*in*/    "0" (&_argvec[0])                            \
4388          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4389       );                                                          \
4390       lval = (__typeof__(lval)) _res;                             \
4391    } while (0)
4392 
4393 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4394                                  arg7,arg8)                       \
4395    do {                                                           \
4396       volatile OrigFn        _orig = (orig);                      \
4397       volatile unsigned long _argvec[9];                          \
4398       volatile unsigned long _res;                                \
4399       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4400       _argvec[1] = (unsigned long)(arg1);                         \
4401       _argvec[2] = (unsigned long)(arg2);                         \
4402       _argvec[3] = (unsigned long)(arg3);                         \
4403       _argvec[4] = (unsigned long)(arg4);                         \
4404       _argvec[5] = (unsigned long)(arg5);                         \
4405       _argvec[6] = (unsigned long)(arg6);                         \
4406       _argvec[7] = (unsigned long)(arg7);                         \
4407       _argvec[8] = (unsigned long)(arg8);                         \
4408       __asm__ volatile(                                           \
4409          VALGRIND_ALIGN_STACK                                     \
4410          "ldr x0, [%1, #8] \n\t"                                  \
4411          "ldr x1, [%1, #16] \n\t"                                 \
4412          "ldr x2, [%1, #24] \n\t"                                 \
4413          "ldr x3, [%1, #32] \n\t"                                 \
4414          "ldr x4, [%1, #40] \n\t"                                 \
4415          "ldr x5, [%1, #48] \n\t"                                 \
4416          "ldr x6, [%1, #56] \n\t"                                 \
4417          "ldr x7, [%1, #64] \n\t"                                 \
4418          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4419          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4420          VALGRIND_RESTORE_STACK                                   \
4421          "mov %0, x0"                                             \
4422          : /*out*/   "=r" (_res)                                  \
4423          : /*in*/    "0" (&_argvec[0])                            \
4424          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4425       );                                                          \
4426       lval = (__typeof__(lval)) _res;                             \
4427    } while (0)
4428 
4429 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4430                                  arg7,arg8,arg9)                  \
4431    do {                                                           \
4432       volatile OrigFn        _orig = (orig);                      \
4433       volatile unsigned long _argvec[10];                         \
4434       volatile unsigned long _res;                                \
4435       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4436       _argvec[1] = (unsigned long)(arg1);                         \
4437       _argvec[2] = (unsigned long)(arg2);                         \
4438       _argvec[3] = (unsigned long)(arg3);                         \
4439       _argvec[4] = (unsigned long)(arg4);                         \
4440       _argvec[5] = (unsigned long)(arg5);                         \
4441       _argvec[6] = (unsigned long)(arg6);                         \
4442       _argvec[7] = (unsigned long)(arg7);                         \
4443       _argvec[8] = (unsigned long)(arg8);                         \
4444       _argvec[9] = (unsigned long)(arg9);                         \
4445       __asm__ volatile(                                           \
4446          VALGRIND_ALIGN_STACK                                     \
4447          "sub sp, sp, #0x20 \n\t"                                 \
4448          "ldr x0, [%1, #8] \n\t"                                  \
4449          "ldr x1, [%1, #16] \n\t"                                 \
4450          "ldr x2, [%1, #24] \n\t"                                 \
4451          "ldr x3, [%1, #32] \n\t"                                 \
4452          "ldr x4, [%1, #40] \n\t"                                 \
4453          "ldr x5, [%1, #48] \n\t"                                 \
4454          "ldr x6, [%1, #56] \n\t"                                 \
4455          "ldr x7, [%1, #64] \n\t"                                 \
4456          "ldr x8, [%1, #72] \n\t"                                 \
4457          "str x8, [sp, #0]  \n\t"                                 \
4458          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4459          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4460          VALGRIND_RESTORE_STACK                                   \
4461          "mov %0, x0"                                             \
4462          : /*out*/   "=r" (_res)                                  \
4463          : /*in*/    "0" (&_argvec[0])                            \
4464          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4465       );                                                          \
4466       lval = (__typeof__(lval)) _res;                             \
4467    } while (0)
4468 
4469 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4470                                   arg7,arg8,arg9,arg10)           \
4471    do {                                                           \
4472       volatile OrigFn        _orig = (orig);                      \
4473       volatile unsigned long _argvec[11];                         \
4474       volatile unsigned long _res;                                \
4475       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4476       _argvec[1] = (unsigned long)(arg1);                         \
4477       _argvec[2] = (unsigned long)(arg2);                         \
4478       _argvec[3] = (unsigned long)(arg3);                         \
4479       _argvec[4] = (unsigned long)(arg4);                         \
4480       _argvec[5] = (unsigned long)(arg5);                         \
4481       _argvec[6] = (unsigned long)(arg6);                         \
4482       _argvec[7] = (unsigned long)(arg7);                         \
4483       _argvec[8] = (unsigned long)(arg8);                         \
4484       _argvec[9] = (unsigned long)(arg9);                         \
4485       _argvec[10] = (unsigned long)(arg10);                       \
4486       __asm__ volatile(                                           \
4487          VALGRIND_ALIGN_STACK                                     \
4488          "sub sp, sp, #0x20 \n\t"                                 \
4489          "ldr x0, [%1, #8] \n\t"                                  \
4490          "ldr x1, [%1, #16] \n\t"                                 \
4491          "ldr x2, [%1, #24] \n\t"                                 \
4492          "ldr x3, [%1, #32] \n\t"                                 \
4493          "ldr x4, [%1, #40] \n\t"                                 \
4494          "ldr x5, [%1, #48] \n\t"                                 \
4495          "ldr x6, [%1, #56] \n\t"                                 \
4496          "ldr x7, [%1, #64] \n\t"                                 \
4497          "ldr x8, [%1, #72] \n\t"                                 \
4498          "str x8, [sp, #0]  \n\t"                                 \
4499          "ldr x8, [%1, #80] \n\t"                                 \
4500          "str x8, [sp, #8]  \n\t"                                 \
4501          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4502          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4503          VALGRIND_RESTORE_STACK                                   \
4504          "mov %0, x0"                                             \
4505          : /*out*/   "=r" (_res)                                  \
4506          : /*in*/    "0" (&_argvec[0])                            \
4507          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4508       );                                                          \
4509       lval = (__typeof__(lval)) _res;                             \
4510    } while (0)
4511 
4512 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4513                                   arg7,arg8,arg9,arg10,arg11)     \
4514    do {                                                           \
4515       volatile OrigFn        _orig = (orig);                      \
4516       volatile unsigned long _argvec[12];                         \
4517       volatile unsigned long _res;                                \
4518       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4519       _argvec[1] = (unsigned long)(arg1);                         \
4520       _argvec[2] = (unsigned long)(arg2);                         \
4521       _argvec[3] = (unsigned long)(arg3);                         \
4522       _argvec[4] = (unsigned long)(arg4);                         \
4523       _argvec[5] = (unsigned long)(arg5);                         \
4524       _argvec[6] = (unsigned long)(arg6);                         \
4525       _argvec[7] = (unsigned long)(arg7);                         \
4526       _argvec[8] = (unsigned long)(arg8);                         \
4527       _argvec[9] = (unsigned long)(arg9);                         \
4528       _argvec[10] = (unsigned long)(arg10);                       \
4529       _argvec[11] = (unsigned long)(arg11);                       \
4530       __asm__ volatile(                                           \
4531          VALGRIND_ALIGN_STACK                                     \
4532          "sub sp, sp, #0x30 \n\t"                                 \
4533          "ldr x0, [%1, #8] \n\t"                                  \
4534          "ldr x1, [%1, #16] \n\t"                                 \
4535          "ldr x2, [%1, #24] \n\t"                                 \
4536          "ldr x3, [%1, #32] \n\t"                                 \
4537          "ldr x4, [%1, #40] \n\t"                                 \
4538          "ldr x5, [%1, #48] \n\t"                                 \
4539          "ldr x6, [%1, #56] \n\t"                                 \
4540          "ldr x7, [%1, #64] \n\t"                                 \
4541          "ldr x8, [%1, #72] \n\t"                                 \
4542          "str x8, [sp, #0]  \n\t"                                 \
4543          "ldr x8, [%1, #80] \n\t"                                 \
4544          "str x8, [sp, #8]  \n\t"                                 \
4545          "ldr x8, [%1, #88] \n\t"                                 \
4546          "str x8, [sp, #16] \n\t"                                 \
4547          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4548          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4549          VALGRIND_RESTORE_STACK                                   \
4550          "mov %0, x0"                                             \
4551          : /*out*/   "=r" (_res)                                  \
4552          : /*in*/    "0" (&_argvec[0])                            \
4553          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4554       );                                                          \
4555       lval = (__typeof__(lval)) _res;                             \
4556    } while (0)
4557 
4558 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4559                                   arg7,arg8,arg9,arg10,arg11,     \
4560                                   arg12)                          \
4561    do {                                                           \
4562       volatile OrigFn        _orig = (orig);                      \
4563       volatile unsigned long _argvec[13];                         \
4564       volatile unsigned long _res;                                \
4565       _argvec[0] = (unsigned long)_orig.nraddr;                   \
4566       _argvec[1] = (unsigned long)(arg1);                         \
4567       _argvec[2] = (unsigned long)(arg2);                         \
4568       _argvec[3] = (unsigned long)(arg3);                         \
4569       _argvec[4] = (unsigned long)(arg4);                         \
4570       _argvec[5] = (unsigned long)(arg5);                         \
4571       _argvec[6] = (unsigned long)(arg6);                         \
4572       _argvec[7] = (unsigned long)(arg7);                         \
4573       _argvec[8] = (unsigned long)(arg8);                         \
4574       _argvec[9] = (unsigned long)(arg9);                         \
4575       _argvec[10] = (unsigned long)(arg10);                       \
4576       _argvec[11] = (unsigned long)(arg11);                       \
4577       _argvec[12] = (unsigned long)(arg12);                       \
4578       __asm__ volatile(                                           \
4579          VALGRIND_ALIGN_STACK                                     \
4580          "sub sp, sp, #0x30 \n\t"                                 \
4581          "ldr x0, [%1, #8] \n\t"                                  \
4582          "ldr x1, [%1, #16] \n\t"                                 \
4583          "ldr x2, [%1, #24] \n\t"                                 \
4584          "ldr x3, [%1, #32] \n\t"                                 \
4585          "ldr x4, [%1, #40] \n\t"                                 \
4586          "ldr x5, [%1, #48] \n\t"                                 \
4587          "ldr x6, [%1, #56] \n\t"                                 \
4588          "ldr x7, [%1, #64] \n\t"                                 \
4589          "ldr x8, [%1, #72] \n\t"                                 \
4590          "str x8, [sp, #0]  \n\t"                                 \
4591          "ldr x8, [%1, #80] \n\t"                                 \
4592          "str x8, [sp, #8]  \n\t"                                 \
4593          "ldr x8, [%1, #88] \n\t"                                 \
4594          "str x8, [sp, #16] \n\t"                                 \
4595          "ldr x8, [%1, #96] \n\t"                                 \
4596          "str x8, [sp, #24] \n\t"                                 \
4597          "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4598          VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4599          VALGRIND_RESTORE_STACK                                   \
4600          "mov %0, x0"                                             \
4601          : /*out*/   "=r" (_res)                                  \
4602          : /*in*/    "0" (&_argvec[0])                            \
4603          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4604       );                                                          \
4605       lval = (__typeof__(lval)) _res;                             \
4606    } while (0)
4607 
4608 #endif /* PLAT_arm64_linux */
4609 
4610 /* ------------------------- s390x-linux ------------------------- */
4611 
4612 #if defined(PLAT_s390x_linux)
4613 
4614 /* Similar workaround as amd64 (see above), but we use r11 as frame
4615    pointer and save the old r11 in r7. r11 might be used for
4616    argvec, therefore we copy argvec in r1 since r1 is clobbered
4617    after the call anyway.  */
4618 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4619 #  define __FRAME_POINTER                                         \
4620       ,"d"(__builtin_dwarf_cfa())
4621 #  define VALGRIND_CFI_PROLOGUE                                   \
4622       ".cfi_remember_state\n\t"                                   \
4623       "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */          \
4624       "lgr 7,11\n\t"                                              \
4625       "lgr 11,%2\n\t"                                             \
4626       ".cfi_def_cfa r11, 0\n\t"
4627 #  define VALGRIND_CFI_EPILOGUE                                   \
4628       "lgr 11, 7\n\t"                                             \
4629       ".cfi_restore_state\n\t"
4630 #else
4631 #  define __FRAME_POINTER
4632 #  define VALGRIND_CFI_PROLOGUE                                   \
4633       "lgr 1,%1\n\t"
4634 #  define VALGRIND_CFI_EPILOGUE
4635 #endif
4636 
4637 /* Nb: On s390 the stack pointer is properly aligned *at all times*
4638    according to the s390 GCC maintainer. (The ABI specification is not
4639    precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4640    VALGRIND_RESTORE_STACK are not defined here. */
4641 
4642 /* These regs are trashed by the hidden call. Note that we overwrite
4643    r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4644    function a proper return address. All others are ABI defined call
4645    clobbers. */
4646 #define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4647                            "f0","f1","f2","f3","f4","f5","f6","f7"
4648 
4649 /* Nb: Although r11 is modified in the asm snippets below (inside 
4650    VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4651    two reasons:
4652    (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4653        modified
4654    (2) GCC will complain that r11 cannot appear inside a clobber section,
4655        when compiled with -O -fno-omit-frame-pointer
4656  */
4657 
4658 #define CALL_FN_W_v(lval, orig)                                  \
4659    do {                                                          \
4660       volatile OrigFn        _orig = (orig);                     \
4661       volatile unsigned long  _argvec[1];                        \
4662       volatile unsigned long _res;                               \
4663       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4664       __asm__ volatile(                                          \
4665          VALGRIND_CFI_PROLOGUE                                   \
4666          "aghi 15,-160\n\t"                                      \
4667          "lg 1, 0(1)\n\t"  /* target->r1 */                      \
4668          VALGRIND_CALL_NOREDIR_R1                                \
4669          "lgr %0, 2\n\t"                                         \
4670          "aghi 15,160\n\t"                                       \
4671          VALGRIND_CFI_EPILOGUE                                   \
4672          : /*out*/   "=d" (_res)                                 \
4673          : /*in*/    "d" (&_argvec[0]) __FRAME_POINTER           \
4674          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4675       );                                                         \
4676       lval = (__typeof__(lval)) _res;                            \
4677    } while (0)
4678 
4679 /* The call abi has the arguments in r2-r6 and stack */
4680 #define CALL_FN_W_W(lval, orig, arg1)                            \
4681    do {                                                          \
4682       volatile OrigFn        _orig = (orig);                     \
4683       volatile unsigned long _argvec[2];                         \
4684       volatile unsigned long _res;                               \
4685       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4686       _argvec[1] = (unsigned long)arg1;                          \
4687       __asm__ volatile(                                          \
4688          VALGRIND_CFI_PROLOGUE                                   \
4689          "aghi 15,-160\n\t"                                      \
4690          "lg 2, 8(1)\n\t"                                        \
4691          "lg 1, 0(1)\n\t"                                        \
4692          VALGRIND_CALL_NOREDIR_R1                                \
4693          "lgr %0, 2\n\t"                                         \
4694          "aghi 15,160\n\t"                                       \
4695          VALGRIND_CFI_EPILOGUE                                   \
4696          : /*out*/   "=d" (_res)                                 \
4697          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4698          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4699       );                                                         \
4700       lval = (__typeof__(lval)) _res;                            \
4701    } while (0)
4702 
4703 #define CALL_FN_W_WW(lval, orig, arg1, arg2)                     \
4704    do {                                                          \
4705       volatile OrigFn        _orig = (orig);                     \
4706       volatile unsigned long _argvec[3];                         \
4707       volatile unsigned long _res;                               \
4708       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4709       _argvec[1] = (unsigned long)arg1;                          \
4710       _argvec[2] = (unsigned long)arg2;                          \
4711       __asm__ volatile(                                          \
4712          VALGRIND_CFI_PROLOGUE                                   \
4713          "aghi 15,-160\n\t"                                      \
4714          "lg 2, 8(1)\n\t"                                        \
4715          "lg 3,16(1)\n\t"                                        \
4716          "lg 1, 0(1)\n\t"                                        \
4717          VALGRIND_CALL_NOREDIR_R1                                \
4718          "lgr %0, 2\n\t"                                         \
4719          "aghi 15,160\n\t"                                       \
4720          VALGRIND_CFI_EPILOGUE                                   \
4721          : /*out*/   "=d" (_res)                                 \
4722          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4723          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4724       );                                                         \
4725       lval = (__typeof__(lval)) _res;                            \
4726    } while (0)
4727 
4728 #define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3)              \
4729    do {                                                          \
4730       volatile OrigFn        _orig = (orig);                     \
4731       volatile unsigned long _argvec[4];                         \
4732       volatile unsigned long _res;                               \
4733       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4734       _argvec[1] = (unsigned long)arg1;                          \
4735       _argvec[2] = (unsigned long)arg2;                          \
4736       _argvec[3] = (unsigned long)arg3;                          \
4737       __asm__ volatile(                                          \
4738          VALGRIND_CFI_PROLOGUE                                   \
4739          "aghi 15,-160\n\t"                                      \
4740          "lg 2, 8(1)\n\t"                                        \
4741          "lg 3,16(1)\n\t"                                        \
4742          "lg 4,24(1)\n\t"                                        \
4743          "lg 1, 0(1)\n\t"                                        \
4744          VALGRIND_CALL_NOREDIR_R1                                \
4745          "lgr %0, 2\n\t"                                         \
4746          "aghi 15,160\n\t"                                       \
4747          VALGRIND_CFI_EPILOGUE                                   \
4748          : /*out*/   "=d" (_res)                                 \
4749          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4750          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4751       );                                                         \
4752       lval = (__typeof__(lval)) _res;                            \
4753    } while (0)
4754 
4755 #define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4)       \
4756    do {                                                          \
4757       volatile OrigFn        _orig = (orig);                     \
4758       volatile unsigned long _argvec[5];                         \
4759       volatile unsigned long _res;                               \
4760       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4761       _argvec[1] = (unsigned long)arg1;                          \
4762       _argvec[2] = (unsigned long)arg2;                          \
4763       _argvec[3] = (unsigned long)arg3;                          \
4764       _argvec[4] = (unsigned long)arg4;                          \
4765       __asm__ volatile(                                          \
4766          VALGRIND_CFI_PROLOGUE                                   \
4767          "aghi 15,-160\n\t"                                      \
4768          "lg 2, 8(1)\n\t"                                        \
4769          "lg 3,16(1)\n\t"                                        \
4770          "lg 4,24(1)\n\t"                                        \
4771          "lg 5,32(1)\n\t"                                        \
4772          "lg 1, 0(1)\n\t"                                        \
4773          VALGRIND_CALL_NOREDIR_R1                                \
4774          "lgr %0, 2\n\t"                                         \
4775          "aghi 15,160\n\t"                                       \
4776          VALGRIND_CFI_EPILOGUE                                   \
4777          : /*out*/   "=d" (_res)                                 \
4778          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4779          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4780       );                                                         \
4781       lval = (__typeof__(lval)) _res;                            \
4782    } while (0)
4783 
4784 #define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5)   \
4785    do {                                                          \
4786       volatile OrigFn        _orig = (orig);                     \
4787       volatile unsigned long _argvec[6];                         \
4788       volatile unsigned long _res;                               \
4789       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4790       _argvec[1] = (unsigned long)arg1;                          \
4791       _argvec[2] = (unsigned long)arg2;                          \
4792       _argvec[3] = (unsigned long)arg3;                          \
4793       _argvec[4] = (unsigned long)arg4;                          \
4794       _argvec[5] = (unsigned long)arg5;                          \
4795       __asm__ volatile(                                          \
4796          VALGRIND_CFI_PROLOGUE                                   \
4797          "aghi 15,-160\n\t"                                      \
4798          "lg 2, 8(1)\n\t"                                        \
4799          "lg 3,16(1)\n\t"                                        \
4800          "lg 4,24(1)\n\t"                                        \
4801          "lg 5,32(1)\n\t"                                        \
4802          "lg 6,40(1)\n\t"                                        \
4803          "lg 1, 0(1)\n\t"                                        \
4804          VALGRIND_CALL_NOREDIR_R1                                \
4805          "lgr %0, 2\n\t"                                         \
4806          "aghi 15,160\n\t"                                       \
4807          VALGRIND_CFI_EPILOGUE                                   \
4808          : /*out*/   "=d" (_res)                                 \
4809          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4810          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4811       );                                                         \
4812       lval = (__typeof__(lval)) _res;                            \
4813    } while (0)
4814 
4815 #define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4816                      arg6)                                       \
4817    do {                                                          \
4818       volatile OrigFn        _orig = (orig);                     \
4819       volatile unsigned long _argvec[7];                         \
4820       volatile unsigned long _res;                               \
4821       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4822       _argvec[1] = (unsigned long)arg1;                          \
4823       _argvec[2] = (unsigned long)arg2;                          \
4824       _argvec[3] = (unsigned long)arg3;                          \
4825       _argvec[4] = (unsigned long)arg4;                          \
4826       _argvec[5] = (unsigned long)arg5;                          \
4827       _argvec[6] = (unsigned long)arg6;                          \
4828       __asm__ volatile(                                          \
4829          VALGRIND_CFI_PROLOGUE                                   \
4830          "aghi 15,-168\n\t"                                      \
4831          "lg 2, 8(1)\n\t"                                        \
4832          "lg 3,16(1)\n\t"                                        \
4833          "lg 4,24(1)\n\t"                                        \
4834          "lg 5,32(1)\n\t"                                        \
4835          "lg 6,40(1)\n\t"                                        \
4836          "mvc 160(8,15), 48(1)\n\t"                              \
4837          "lg 1, 0(1)\n\t"                                        \
4838          VALGRIND_CALL_NOREDIR_R1                                \
4839          "lgr %0, 2\n\t"                                         \
4840          "aghi 15,168\n\t"                                       \
4841          VALGRIND_CFI_EPILOGUE                                   \
4842          : /*out*/   "=d" (_res)                                 \
4843          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4844          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4845       );                                                         \
4846       lval = (__typeof__(lval)) _res;                            \
4847    } while (0)
4848 
4849 #define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4850                      arg6, arg7)                                 \
4851    do {                                                          \
4852       volatile OrigFn        _orig = (orig);                     \
4853       volatile unsigned long _argvec[8];                         \
4854       volatile unsigned long _res;                               \
4855       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4856       _argvec[1] = (unsigned long)arg1;                          \
4857       _argvec[2] = (unsigned long)arg2;                          \
4858       _argvec[3] = (unsigned long)arg3;                          \
4859       _argvec[4] = (unsigned long)arg4;                          \
4860       _argvec[5] = (unsigned long)arg5;                          \
4861       _argvec[6] = (unsigned long)arg6;                          \
4862       _argvec[7] = (unsigned long)arg7;                          \
4863       __asm__ volatile(                                          \
4864          VALGRIND_CFI_PROLOGUE                                   \
4865          "aghi 15,-176\n\t"                                      \
4866          "lg 2, 8(1)\n\t"                                        \
4867          "lg 3,16(1)\n\t"                                        \
4868          "lg 4,24(1)\n\t"                                        \
4869          "lg 5,32(1)\n\t"                                        \
4870          "lg 6,40(1)\n\t"                                        \
4871          "mvc 160(8,15), 48(1)\n\t"                              \
4872          "mvc 168(8,15), 56(1)\n\t"                              \
4873          "lg 1, 0(1)\n\t"                                        \
4874          VALGRIND_CALL_NOREDIR_R1                                \
4875          "lgr %0, 2\n\t"                                         \
4876          "aghi 15,176\n\t"                                       \
4877          VALGRIND_CFI_EPILOGUE                                   \
4878          : /*out*/   "=d" (_res)                                 \
4879          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4880          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4881       );                                                         \
4882       lval = (__typeof__(lval)) _res;                            \
4883    } while (0)
4884 
4885 #define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4886                      arg6, arg7 ,arg8)                           \
4887    do {                                                          \
4888       volatile OrigFn        _orig = (orig);                     \
4889       volatile unsigned long _argvec[9];                         \
4890       volatile unsigned long _res;                               \
4891       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4892       _argvec[1] = (unsigned long)arg1;                          \
4893       _argvec[2] = (unsigned long)arg2;                          \
4894       _argvec[3] = (unsigned long)arg3;                          \
4895       _argvec[4] = (unsigned long)arg4;                          \
4896       _argvec[5] = (unsigned long)arg5;                          \
4897       _argvec[6] = (unsigned long)arg6;                          \
4898       _argvec[7] = (unsigned long)arg7;                          \
4899       _argvec[8] = (unsigned long)arg8;                          \
4900       __asm__ volatile(                                          \
4901          VALGRIND_CFI_PROLOGUE                                   \
4902          "aghi 15,-184\n\t"                                      \
4903          "lg 2, 8(1)\n\t"                                        \
4904          "lg 3,16(1)\n\t"                                        \
4905          "lg 4,24(1)\n\t"                                        \
4906          "lg 5,32(1)\n\t"                                        \
4907          "lg 6,40(1)\n\t"                                        \
4908          "mvc 160(8,15), 48(1)\n\t"                              \
4909          "mvc 168(8,15), 56(1)\n\t"                              \
4910          "mvc 176(8,15), 64(1)\n\t"                              \
4911          "lg 1, 0(1)\n\t"                                        \
4912          VALGRIND_CALL_NOREDIR_R1                                \
4913          "lgr %0, 2\n\t"                                         \
4914          "aghi 15,184\n\t"                                       \
4915          VALGRIND_CFI_EPILOGUE                                   \
4916          : /*out*/   "=d" (_res)                                 \
4917          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4918          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4919       );                                                         \
4920       lval = (__typeof__(lval)) _res;                            \
4921    } while (0)
4922 
4923 #define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4924                      arg6, arg7 ,arg8, arg9)                     \
4925    do {                                                          \
4926       volatile OrigFn        _orig = (orig);                     \
4927       volatile unsigned long _argvec[10];                        \
4928       volatile unsigned long _res;                               \
4929       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4930       _argvec[1] = (unsigned long)arg1;                          \
4931       _argvec[2] = (unsigned long)arg2;                          \
4932       _argvec[3] = (unsigned long)arg3;                          \
4933       _argvec[4] = (unsigned long)arg4;                          \
4934       _argvec[5] = (unsigned long)arg5;                          \
4935       _argvec[6] = (unsigned long)arg6;                          \
4936       _argvec[7] = (unsigned long)arg7;                          \
4937       _argvec[8] = (unsigned long)arg8;                          \
4938       _argvec[9] = (unsigned long)arg9;                          \
4939       __asm__ volatile(                                          \
4940          VALGRIND_CFI_PROLOGUE                                   \
4941          "aghi 15,-192\n\t"                                      \
4942          "lg 2, 8(1)\n\t"                                        \
4943          "lg 3,16(1)\n\t"                                        \
4944          "lg 4,24(1)\n\t"                                        \
4945          "lg 5,32(1)\n\t"                                        \
4946          "lg 6,40(1)\n\t"                                        \
4947          "mvc 160(8,15), 48(1)\n\t"                              \
4948          "mvc 168(8,15), 56(1)\n\t"                              \
4949          "mvc 176(8,15), 64(1)\n\t"                              \
4950          "mvc 184(8,15), 72(1)\n\t"                              \
4951          "lg 1, 0(1)\n\t"                                        \
4952          VALGRIND_CALL_NOREDIR_R1                                \
4953          "lgr %0, 2\n\t"                                         \
4954          "aghi 15,192\n\t"                                       \
4955          VALGRIND_CFI_EPILOGUE                                   \
4956          : /*out*/   "=d" (_res)                                 \
4957          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4958          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4959       );                                                         \
4960       lval = (__typeof__(lval)) _res;                            \
4961    } while (0)
4962 
4963 #define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
4964                      arg6, arg7 ,arg8, arg9, arg10)              \
4965    do {                                                          \
4966       volatile OrigFn        _orig = (orig);                     \
4967       volatile unsigned long _argvec[11];                        \
4968       volatile unsigned long _res;                               \
4969       _argvec[0] = (unsigned long)_orig.nraddr;                  \
4970       _argvec[1] = (unsigned long)arg1;                          \
4971       _argvec[2] = (unsigned long)arg2;                          \
4972       _argvec[3] = (unsigned long)arg3;                          \
4973       _argvec[4] = (unsigned long)arg4;                          \
4974       _argvec[5] = (unsigned long)arg5;                          \
4975       _argvec[6] = (unsigned long)arg6;                          \
4976       _argvec[7] = (unsigned long)arg7;                          \
4977       _argvec[8] = (unsigned long)arg8;                          \
4978       _argvec[9] = (unsigned long)arg9;                          \
4979       _argvec[10] = (unsigned long)arg10;                        \
4980       __asm__ volatile(                                          \
4981          VALGRIND_CFI_PROLOGUE                                   \
4982          "aghi 15,-200\n\t"                                      \
4983          "lg 2, 8(1)\n\t"                                        \
4984          "lg 3,16(1)\n\t"                                        \
4985          "lg 4,24(1)\n\t"                                        \
4986          "lg 5,32(1)\n\t"                                        \
4987          "lg 6,40(1)\n\t"                                        \
4988          "mvc 160(8,15), 48(1)\n\t"                              \
4989          "mvc 168(8,15), 56(1)\n\t"                              \
4990          "mvc 176(8,15), 64(1)\n\t"                              \
4991          "mvc 184(8,15), 72(1)\n\t"                              \
4992          "mvc 192(8,15), 80(1)\n\t"                              \
4993          "lg 1, 0(1)\n\t"                                        \
4994          VALGRIND_CALL_NOREDIR_R1                                \
4995          "lgr %0, 2\n\t"                                         \
4996          "aghi 15,200\n\t"                                       \
4997          VALGRIND_CFI_EPILOGUE                                   \
4998          : /*out*/   "=d" (_res)                                 \
4999          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5000          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5001       );                                                         \
5002       lval = (__typeof__(lval)) _res;                            \
5003    } while (0)
5004 
5005 #define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5006                      arg6, arg7 ,arg8, arg9, arg10, arg11)       \
5007    do {                                                          \
5008       volatile OrigFn        _orig = (orig);                     \
5009       volatile unsigned long _argvec[12];                        \
5010       volatile unsigned long _res;                               \
5011       _argvec[0] = (unsigned long)_orig.nraddr;                  \
5012       _argvec[1] = (unsigned long)arg1;                          \
5013       _argvec[2] = (unsigned long)arg2;                          \
5014       _argvec[3] = (unsigned long)arg3;                          \
5015       _argvec[4] = (unsigned long)arg4;                          \
5016       _argvec[5] = (unsigned long)arg5;                          \
5017       _argvec[6] = (unsigned long)arg6;                          \
5018       _argvec[7] = (unsigned long)arg7;                          \
5019       _argvec[8] = (unsigned long)arg8;                          \
5020       _argvec[9] = (unsigned long)arg9;                          \
5021       _argvec[10] = (unsigned long)arg10;                        \
5022       _argvec[11] = (unsigned long)arg11;                        \
5023       __asm__ volatile(                                          \
5024          VALGRIND_CFI_PROLOGUE                                   \
5025          "aghi 15,-208\n\t"                                      \
5026          "lg 2, 8(1)\n\t"                                        \
5027          "lg 3,16(1)\n\t"                                        \
5028          "lg 4,24(1)\n\t"                                        \
5029          "lg 5,32(1)\n\t"                                        \
5030          "lg 6,40(1)\n\t"                                        \
5031          "mvc 160(8,15), 48(1)\n\t"                              \
5032          "mvc 168(8,15), 56(1)\n\t"                              \
5033          "mvc 176(8,15), 64(1)\n\t"                              \
5034          "mvc 184(8,15), 72(1)\n\t"                              \
5035          "mvc 192(8,15), 80(1)\n\t"                              \
5036          "mvc 200(8,15), 88(1)\n\t"                              \
5037          "lg 1, 0(1)\n\t"                                        \
5038          VALGRIND_CALL_NOREDIR_R1                                \
5039          "lgr %0, 2\n\t"                                         \
5040          "aghi 15,208\n\t"                                       \
5041          VALGRIND_CFI_EPILOGUE                                   \
5042          : /*out*/   "=d" (_res)                                 \
5043          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5044          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5045       );                                                         \
5046       lval = (__typeof__(lval)) _res;                            \
5047    } while (0)
5048 
5049 #define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5050                      arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
5051    do {                                                          \
5052       volatile OrigFn        _orig = (orig);                     \
5053       volatile unsigned long _argvec[13];                        \
5054       volatile unsigned long _res;                               \
5055       _argvec[0] = (unsigned long)_orig.nraddr;                  \
5056       _argvec[1] = (unsigned long)arg1;                          \
5057       _argvec[2] = (unsigned long)arg2;                          \
5058       _argvec[3] = (unsigned long)arg3;                          \
5059       _argvec[4] = (unsigned long)arg4;                          \
5060       _argvec[5] = (unsigned long)arg5;                          \
5061       _argvec[6] = (unsigned long)arg6;                          \
5062       _argvec[7] = (unsigned long)arg7;                          \
5063       _argvec[8] = (unsigned long)arg8;                          \
5064       _argvec[9] = (unsigned long)arg9;                          \
5065       _argvec[10] = (unsigned long)arg10;                        \
5066       _argvec[11] = (unsigned long)arg11;                        \
5067       _argvec[12] = (unsigned long)arg12;                        \
5068       __asm__ volatile(                                          \
5069          VALGRIND_CFI_PROLOGUE                                   \
5070          "aghi 15,-216\n\t"                                      \
5071          "lg 2, 8(1)\n\t"                                        \
5072          "lg 3,16(1)\n\t"                                        \
5073          "lg 4,24(1)\n\t"                                        \
5074          "lg 5,32(1)\n\t"                                        \
5075          "lg 6,40(1)\n\t"                                        \
5076          "mvc 160(8,15), 48(1)\n\t"                              \
5077          "mvc 168(8,15), 56(1)\n\t"                              \
5078          "mvc 176(8,15), 64(1)\n\t"                              \
5079          "mvc 184(8,15), 72(1)\n\t"                              \
5080          "mvc 192(8,15), 80(1)\n\t"                              \
5081          "mvc 200(8,15), 88(1)\n\t"                              \
5082          "mvc 208(8,15), 96(1)\n\t"                              \
5083          "lg 1, 0(1)\n\t"                                        \
5084          VALGRIND_CALL_NOREDIR_R1                                \
5085          "lgr %0, 2\n\t"                                         \
5086          "aghi 15,216\n\t"                                       \
5087          VALGRIND_CFI_EPILOGUE                                   \
5088          : /*out*/   "=d" (_res)                                 \
5089          : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5090          : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5091       );                                                         \
5092       lval = (__typeof__(lval)) _res;                            \
5093    } while (0)
5094 
5095 
5096 #endif /* PLAT_s390x_linux */
5097 
5098 /* ------------------------- mips32-linux ----------------------- */
5099  
5100 #if defined(PLAT_mips32_linux)
5101 
5102 /* These regs are trashed by the hidden call. */
5103 #define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6",       \
5104 "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5105 "$25", "$31"
5106 
5107 /* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5108    long) == 4. */
5109 
5110 #define CALL_FN_W_v(lval, orig)                                   \
5111    do {                                                           \
5112       volatile OrigFn        _orig = (orig);                      \
5113       volatile unsigned long _argvec[1];                          \
5114       volatile unsigned long _res;                                \
5115       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5116       __asm__ volatile(                                           \
5117          "subu $29, $29, 8 \n\t"                                  \
5118          "sw $28, 0($29) \n\t"                                    \
5119          "sw $31, 4($29) \n\t"                                    \
5120          "subu $29, $29, 16 \n\t"                                 \
5121          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5122          VALGRIND_CALL_NOREDIR_T9                                 \
5123          "addu $29, $29, 16\n\t"                                  \
5124          "lw $28, 0($29) \n\t"                                    \
5125          "lw $31, 4($29) \n\t"                                    \
5126          "addu $29, $29, 8 \n\t"                                  \
5127          "move %0, $2\n"                                          \
5128          : /*out*/   "=r" (_res)                                  \
5129          : /*in*/    "0" (&_argvec[0])                            \
5130          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5131       );                                                          \
5132       lval = (__typeof__(lval)) _res;                             \
5133    } while (0)
5134 
5135 #define CALL_FN_W_W(lval, orig, arg1)                             \
5136    do {                                                           \
5137       volatile OrigFn        _orig = (orig);                      \
5138      volatile unsigned long _argvec[2];                           \
5139       volatile unsigned long _res;                                \
5140       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5141       _argvec[1] = (unsigned long)(arg1);                         \
5142       __asm__ volatile(                                           \
5143          "subu $29, $29, 8 \n\t"                                  \
5144          "sw $28, 0($29) \n\t"                                    \
5145          "sw $31, 4($29) \n\t"                                    \
5146          "subu $29, $29, 16 \n\t"                                 \
5147          "lw $4, 4(%1) \n\t"   /* arg1*/                          \
5148          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5149          VALGRIND_CALL_NOREDIR_T9                                 \
5150          "addu $29, $29, 16 \n\t"                                 \
5151          "lw $28, 0($29) \n\t"                                    \
5152          "lw $31, 4($29) \n\t"                                    \
5153          "addu $29, $29, 8 \n\t"                                  \
5154          "move %0, $2\n"                                          \
5155          : /*out*/   "=r" (_res)                                  \
5156          : /*in*/    "0" (&_argvec[0])                            \
5157          : /*trash*/ "memory",  __CALLER_SAVED_REGS               \
5158       );                                                          \
5159       lval = (__typeof__(lval)) _res;                             \
5160    } while (0)
5161 
5162 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
5163    do {                                                           \
5164       volatile OrigFn        _orig = (orig);                      \
5165       volatile unsigned long _argvec[3];                          \
5166       volatile unsigned long _res;                                \
5167       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5168       _argvec[1] = (unsigned long)(arg1);                         \
5169       _argvec[2] = (unsigned long)(arg2);                         \
5170       __asm__ volatile(                                           \
5171          "subu $29, $29, 8 \n\t"                                  \
5172          "sw $28, 0($29) \n\t"                                    \
5173          "sw $31, 4($29) \n\t"                                    \
5174          "subu $29, $29, 16 \n\t"                                 \
5175          "lw $4, 4(%1) \n\t"                                      \
5176          "lw $5, 8(%1) \n\t"                                      \
5177          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5178          VALGRIND_CALL_NOREDIR_T9                                 \
5179          "addu $29, $29, 16 \n\t"                                 \
5180          "lw $28, 0($29) \n\t"                                    \
5181          "lw $31, 4($29) \n\t"                                    \
5182          "addu $29, $29, 8 \n\t"                                  \
5183          "move %0, $2\n"                                          \
5184          : /*out*/   "=r" (_res)                                  \
5185          : /*in*/    "0" (&_argvec[0])                            \
5186          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5187       );                                                          \
5188       lval = (__typeof__(lval)) _res;                             \
5189    } while (0)
5190 
5191 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
5192    do {                                                           \
5193       volatile OrigFn        _orig = (orig);                      \
5194       volatile unsigned long _argvec[4];                          \
5195       volatile unsigned long _res;                                \
5196       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5197       _argvec[1] = (unsigned long)(arg1);                         \
5198       _argvec[2] = (unsigned long)(arg2);                         \
5199       _argvec[3] = (unsigned long)(arg3);                         \
5200       __asm__ volatile(                                           \
5201          "subu $29, $29, 8 \n\t"                                  \
5202          "sw $28, 0($29) \n\t"                                    \
5203          "sw $31, 4($29) \n\t"                                    \
5204          "subu $29, $29, 16 \n\t"                                 \
5205          "lw $4, 4(%1) \n\t"                                      \
5206          "lw $5, 8(%1) \n\t"                                      \
5207          "lw $6, 12(%1) \n\t"                                     \
5208          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5209          VALGRIND_CALL_NOREDIR_T9                                 \
5210          "addu $29, $29, 16 \n\t"                                 \
5211          "lw $28, 0($29) \n\t"                                    \
5212          "lw $31, 4($29) \n\t"                                    \
5213          "addu $29, $29, 8 \n\t"                                  \
5214          "move %0, $2\n"                                          \
5215          : /*out*/   "=r" (_res)                                  \
5216          : /*in*/    "0" (&_argvec[0])                            \
5217          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5218       );                                                          \
5219       lval = (__typeof__(lval)) _res;                             \
5220    } while (0)
5221 
5222 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
5223    do {                                                           \
5224       volatile OrigFn        _orig = (orig);                      \
5225       volatile unsigned long _argvec[5];                          \
5226       volatile unsigned long _res;                                \
5227       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5228       _argvec[1] = (unsigned long)(arg1);                         \
5229       _argvec[2] = (unsigned long)(arg2);                         \
5230       _argvec[3] = (unsigned long)(arg3);                         \
5231       _argvec[4] = (unsigned long)(arg4);                         \
5232       __asm__ volatile(                                           \
5233          "subu $29, $29, 8 \n\t"                                  \
5234          "sw $28, 0($29) \n\t"                                    \
5235          "sw $31, 4($29) \n\t"                                    \
5236          "subu $29, $29, 16 \n\t"                                 \
5237          "lw $4, 4(%1) \n\t"                                      \
5238          "lw $5, 8(%1) \n\t"                                      \
5239          "lw $6, 12(%1) \n\t"                                     \
5240          "lw $7, 16(%1) \n\t"                                     \
5241          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5242          VALGRIND_CALL_NOREDIR_T9                                 \
5243          "addu $29, $29, 16 \n\t"                                 \
5244          "lw $28, 0($29) \n\t"                                    \
5245          "lw $31, 4($29) \n\t"                                    \
5246          "addu $29, $29, 8 \n\t"                                  \
5247          "move %0, $2\n"                                          \
5248          : /*out*/   "=r" (_res)                                  \
5249          : /*in*/    "0" (&_argvec[0])                            \
5250          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5251       );                                                          \
5252       lval = (__typeof__(lval)) _res;                             \
5253    } while (0)
5254 
5255 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
5256    do {                                                           \
5257       volatile OrigFn        _orig = (orig);                      \
5258       volatile unsigned long _argvec[6];                          \
5259       volatile unsigned long _res;                                \
5260       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5261       _argvec[1] = (unsigned long)(arg1);                         \
5262       _argvec[2] = (unsigned long)(arg2);                         \
5263       _argvec[3] = (unsigned long)(arg3);                         \
5264       _argvec[4] = (unsigned long)(arg4);                         \
5265       _argvec[5] = (unsigned long)(arg5);                         \
5266       __asm__ volatile(                                           \
5267          "subu $29, $29, 8 \n\t"                                  \
5268          "sw $28, 0($29) \n\t"                                    \
5269          "sw $31, 4($29) \n\t"                                    \
5270          "lw $4, 20(%1) \n\t"                                     \
5271          "subu $29, $29, 24\n\t"                                  \
5272          "sw $4, 16($29) \n\t"                                    \
5273          "lw $4, 4(%1) \n\t"                                      \
5274          "lw $5, 8(%1) \n\t"                                      \
5275          "lw $6, 12(%1) \n\t"                                     \
5276          "lw $7, 16(%1) \n\t"                                     \
5277          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5278          VALGRIND_CALL_NOREDIR_T9                                 \
5279          "addu $29, $29, 24 \n\t"                                 \
5280          "lw $28, 0($29) \n\t"                                    \
5281          "lw $31, 4($29) \n\t"                                    \
5282          "addu $29, $29, 8 \n\t"                                  \
5283          "move %0, $2\n"                                          \
5284          : /*out*/   "=r" (_res)                                  \
5285          : /*in*/    "0" (&_argvec[0])                            \
5286          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5287       );                                                          \
5288       lval = (__typeof__(lval)) _res;                             \
5289    } while (0)
5290 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
5291    do {                                                           \
5292       volatile OrigFn        _orig = (orig);                      \
5293       volatile unsigned long _argvec[7];                          \
5294       volatile unsigned long _res;                                \
5295       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5296       _argvec[1] = (unsigned long)(arg1);                         \
5297       _argvec[2] = (unsigned long)(arg2);                         \
5298       _argvec[3] = (unsigned long)(arg3);                         \
5299       _argvec[4] = (unsigned long)(arg4);                         \
5300       _argvec[5] = (unsigned long)(arg5);                         \
5301       _argvec[6] = (unsigned long)(arg6);                         \
5302       __asm__ volatile(                                           \
5303          "subu $29, $29, 8 \n\t"                                  \
5304          "sw $28, 0($29) \n\t"                                    \
5305          "sw $31, 4($29) \n\t"                                    \
5306          "lw $4, 20(%1) \n\t"                                     \
5307          "subu $29, $29, 32\n\t"                                  \
5308          "sw $4, 16($29) \n\t"                                    \
5309          "lw $4, 24(%1) \n\t"                                     \
5310          "nop\n\t"                                                \
5311          "sw $4, 20($29) \n\t"                                    \
5312          "lw $4, 4(%1) \n\t"                                      \
5313          "lw $5, 8(%1) \n\t"                                      \
5314          "lw $6, 12(%1) \n\t"                                     \
5315          "lw $7, 16(%1) \n\t"                                     \
5316          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5317          VALGRIND_CALL_NOREDIR_T9                                 \
5318          "addu $29, $29, 32 \n\t"                                 \
5319          "lw $28, 0($29) \n\t"                                    \
5320          "lw $31, 4($29) \n\t"                                    \
5321          "addu $29, $29, 8 \n\t"                                  \
5322          "move %0, $2\n"                                          \
5323          : /*out*/   "=r" (_res)                                  \
5324          : /*in*/    "0" (&_argvec[0])                            \
5325          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5326       );                                                          \
5327       lval = (__typeof__(lval)) _res;                             \
5328    } while (0)
5329 
5330 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5331                                  arg7)                            \
5332    do {                                                           \
5333       volatile OrigFn        _orig = (orig);                      \
5334       volatile unsigned long _argvec[8];                          \
5335       volatile unsigned long _res;                                \
5336       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5337       _argvec[1] = (unsigned long)(arg1);                         \
5338       _argvec[2] = (unsigned long)(arg2);                         \
5339       _argvec[3] = (unsigned long)(arg3);                         \
5340       _argvec[4] = (unsigned long)(arg4);                         \
5341       _argvec[5] = (unsigned long)(arg5);                         \
5342       _argvec[6] = (unsigned long)(arg6);                         \
5343       _argvec[7] = (unsigned long)(arg7);                         \
5344       __asm__ volatile(                                           \
5345          "subu $29, $29, 8 \n\t"                                  \
5346          "sw $28, 0($29) \n\t"                                    \
5347          "sw $31, 4($29) \n\t"                                    \
5348          "lw $4, 20(%1) \n\t"                                     \
5349          "subu $29, $29, 32\n\t"                                  \
5350          "sw $4, 16($29) \n\t"                                    \
5351          "lw $4, 24(%1) \n\t"                                     \
5352          "sw $4, 20($29) \n\t"                                    \
5353          "lw $4, 28(%1) \n\t"                                     \
5354          "sw $4, 24($29) \n\t"                                    \
5355          "lw $4, 4(%1) \n\t"                                      \
5356          "lw $5, 8(%1) \n\t"                                      \
5357          "lw $6, 12(%1) \n\t"                                     \
5358          "lw $7, 16(%1) \n\t"                                     \
5359          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5360          VALGRIND_CALL_NOREDIR_T9                                 \
5361          "addu $29, $29, 32 \n\t"                                 \
5362          "lw $28, 0($29) \n\t"                                    \
5363          "lw $31, 4($29) \n\t"                                    \
5364          "addu $29, $29, 8 \n\t"                                  \
5365          "move %0, $2\n"                                          \
5366          : /*out*/   "=r" (_res)                                  \
5367          : /*in*/    "0" (&_argvec[0])                            \
5368          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5369       );                                                          \
5370       lval = (__typeof__(lval)) _res;                             \
5371    } while (0)
5372 
5373 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5374                                  arg7,arg8)                       \
5375    do {                                                           \
5376       volatile OrigFn        _orig = (orig);                      \
5377       volatile unsigned long _argvec[9];                          \
5378       volatile unsigned long _res;                                \
5379       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5380       _argvec[1] = (unsigned long)(arg1);                         \
5381       _argvec[2] = (unsigned long)(arg2);                         \
5382       _argvec[3] = (unsigned long)(arg3);                         \
5383       _argvec[4] = (unsigned long)(arg4);                         \
5384       _argvec[5] = (unsigned long)(arg5);                         \
5385       _argvec[6] = (unsigned long)(arg6);                         \
5386       _argvec[7] = (unsigned long)(arg7);                         \
5387       _argvec[8] = (unsigned long)(arg8);                         \
5388       __asm__ volatile(                                           \
5389          "subu $29, $29, 8 \n\t"                                  \
5390          "sw $28, 0($29) \n\t"                                    \
5391          "sw $31, 4($29) \n\t"                                    \
5392          "lw $4, 20(%1) \n\t"                                     \
5393          "subu $29, $29, 40\n\t"                                  \
5394          "sw $4, 16($29) \n\t"                                    \
5395          "lw $4, 24(%1) \n\t"                                     \
5396          "sw $4, 20($29) \n\t"                                    \
5397          "lw $4, 28(%1) \n\t"                                     \
5398          "sw $4, 24($29) \n\t"                                    \
5399          "lw $4, 32(%1) \n\t"                                     \
5400          "sw $4, 28($29) \n\t"                                    \
5401          "lw $4, 4(%1) \n\t"                                      \
5402          "lw $5, 8(%1) \n\t"                                      \
5403          "lw $6, 12(%1) \n\t"                                     \
5404          "lw $7, 16(%1) \n\t"                                     \
5405          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5406          VALGRIND_CALL_NOREDIR_T9                                 \
5407          "addu $29, $29, 40 \n\t"                                 \
5408          "lw $28, 0($29) \n\t"                                    \
5409          "lw $31, 4($29) \n\t"                                    \
5410          "addu $29, $29, 8 \n\t"                                  \
5411          "move %0, $2\n"                                          \
5412          : /*out*/   "=r" (_res)                                  \
5413          : /*in*/    "0" (&_argvec[0])                            \
5414          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5415       );                                                          \
5416       lval = (__typeof__(lval)) _res;                             \
5417    } while (0)
5418 
5419 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5420                                  arg7,arg8,arg9)                  \
5421    do {                                                           \
5422       volatile OrigFn        _orig = (orig);                      \
5423       volatile unsigned long _argvec[10];                         \
5424       volatile unsigned long _res;                                \
5425       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5426       _argvec[1] = (unsigned long)(arg1);                         \
5427       _argvec[2] = (unsigned long)(arg2);                         \
5428       _argvec[3] = (unsigned long)(arg3);                         \
5429       _argvec[4] = (unsigned long)(arg4);                         \
5430       _argvec[5] = (unsigned long)(arg5);                         \
5431       _argvec[6] = (unsigned long)(arg6);                         \
5432       _argvec[7] = (unsigned long)(arg7);                         \
5433       _argvec[8] = (unsigned long)(arg8);                         \
5434       _argvec[9] = (unsigned long)(arg9);                         \
5435       __asm__ volatile(                                           \
5436          "subu $29, $29, 8 \n\t"                                  \
5437          "sw $28, 0($29) \n\t"                                    \
5438          "sw $31, 4($29) \n\t"                                    \
5439          "lw $4, 20(%1) \n\t"                                     \
5440          "subu $29, $29, 40\n\t"                                  \
5441          "sw $4, 16($29) \n\t"                                    \
5442          "lw $4, 24(%1) \n\t"                                     \
5443          "sw $4, 20($29) \n\t"                                    \
5444          "lw $4, 28(%1) \n\t"                                     \
5445          "sw $4, 24($29) \n\t"                                    \
5446          "lw $4, 32(%1) \n\t"                                     \
5447          "sw $4, 28($29) \n\t"                                    \
5448          "lw $4, 36(%1) \n\t"                                     \
5449          "sw $4, 32($29) \n\t"                                    \
5450          "lw $4, 4(%1) \n\t"                                      \
5451          "lw $5, 8(%1) \n\t"                                      \
5452          "lw $6, 12(%1) \n\t"                                     \
5453          "lw $7, 16(%1) \n\t"                                     \
5454          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5455          VALGRIND_CALL_NOREDIR_T9                                 \
5456          "addu $29, $29, 40 \n\t"                                 \
5457          "lw $28, 0($29) \n\t"                                    \
5458          "lw $31, 4($29) \n\t"                                    \
5459          "addu $29, $29, 8 \n\t"                                  \
5460          "move %0, $2\n"                                          \
5461          : /*out*/   "=r" (_res)                                  \
5462          : /*in*/    "0" (&_argvec[0])                            \
5463          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5464       );                                                          \
5465       lval = (__typeof__(lval)) _res;                             \
5466    } while (0)
5467 
5468 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
5469                                   arg7,arg8,arg9,arg10)           \
5470    do {                                                           \
5471       volatile OrigFn        _orig = (orig);                      \
5472       volatile unsigned long _argvec[11];                         \
5473       volatile unsigned long _res;                                \
5474       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5475       _argvec[1] = (unsigned long)(arg1);                         \
5476       _argvec[2] = (unsigned long)(arg2);                         \
5477       _argvec[3] = (unsigned long)(arg3);                         \
5478       _argvec[4] = (unsigned long)(arg4);                         \
5479       _argvec[5] = (unsigned long)(arg5);                         \
5480       _argvec[6] = (unsigned long)(arg6);                         \
5481       _argvec[7] = (unsigned long)(arg7);                         \
5482       _argvec[8] = (unsigned long)(arg8);                         \
5483       _argvec[9] = (unsigned long)(arg9);                         \
5484       _argvec[10] = (unsigned long)(arg10);                       \
5485       __asm__ volatile(                                           \
5486          "subu $29, $29, 8 \n\t"                                  \
5487          "sw $28, 0($29) \n\t"                                    \
5488          "sw $31, 4($29) \n\t"                                    \
5489          "lw $4, 20(%1) \n\t"                                     \
5490          "subu $29, $29, 48\n\t"                                  \
5491          "sw $4, 16($29) \n\t"                                    \
5492          "lw $4, 24(%1) \n\t"                                     \
5493          "sw $4, 20($29) \n\t"                                    \
5494          "lw $4, 28(%1) \n\t"                                     \
5495          "sw $4, 24($29) \n\t"                                    \
5496          "lw $4, 32(%1) \n\t"                                     \
5497          "sw $4, 28($29) \n\t"                                    \
5498          "lw $4, 36(%1) \n\t"                                     \
5499          "sw $4, 32($29) \n\t"                                    \
5500          "lw $4, 40(%1) \n\t"                                     \
5501          "sw $4, 36($29) \n\t"                                    \
5502          "lw $4, 4(%1) \n\t"                                      \
5503          "lw $5, 8(%1) \n\t"                                      \
5504          "lw $6, 12(%1) \n\t"                                     \
5505          "lw $7, 16(%1) \n\t"                                     \
5506          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5507          VALGRIND_CALL_NOREDIR_T9                                 \
5508          "addu $29, $29, 48 \n\t"                                 \
5509          "lw $28, 0($29) \n\t"                                    \
5510          "lw $31, 4($29) \n\t"                                    \
5511          "addu $29, $29, 8 \n\t"                                  \
5512          "move %0, $2\n"                                          \
5513          : /*out*/   "=r" (_res)                                  \
5514          : /*in*/    "0" (&_argvec[0])                            \
5515          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5516       );                                                          \
5517       lval = (__typeof__(lval)) _res;                             \
5518    } while (0)
5519 
5520 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
5521                                   arg6,arg7,arg8,arg9,arg10,      \
5522                                   arg11)                          \
5523    do {                                                           \
5524       volatile OrigFn        _orig = (orig);                      \
5525       volatile unsigned long _argvec[12];                         \
5526       volatile unsigned long _res;                                \
5527       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5528       _argvec[1] = (unsigned long)(arg1);                         \
5529       _argvec[2] = (unsigned long)(arg2);                         \
5530       _argvec[3] = (unsigned long)(arg3);                         \
5531       _argvec[4] = (unsigned long)(arg4);                         \
5532       _argvec[5] = (unsigned long)(arg5);                         \
5533       _argvec[6] = (unsigned long)(arg6);                         \
5534       _argvec[7] = (unsigned long)(arg7);                         \
5535       _argvec[8] = (unsigned long)(arg8);                         \
5536       _argvec[9] = (unsigned long)(arg9);                         \
5537       _argvec[10] = (unsigned long)(arg10);                       \
5538       _argvec[11] = (unsigned long)(arg11);                       \
5539       __asm__ volatile(                                           \
5540          "subu $29, $29, 8 \n\t"                                  \
5541          "sw $28, 0($29) \n\t"                                    \
5542          "sw $31, 4($29) \n\t"                                    \
5543          "lw $4, 20(%1) \n\t"                                     \
5544          "subu $29, $29, 48\n\t"                                  \
5545          "sw $4, 16($29) \n\t"                                    \
5546          "lw $4, 24(%1) \n\t"                                     \
5547          "sw $4, 20($29) \n\t"                                    \
5548          "lw $4, 28(%1) \n\t"                                     \
5549          "sw $4, 24($29) \n\t"                                    \
5550          "lw $4, 32(%1) \n\t"                                     \
5551          "sw $4, 28($29) \n\t"                                    \
5552          "lw $4, 36(%1) \n\t"                                     \
5553          "sw $4, 32($29) \n\t"                                    \
5554          "lw $4, 40(%1) \n\t"                                     \
5555          "sw $4, 36($29) \n\t"                                    \
5556          "lw $4, 44(%1) \n\t"                                     \
5557          "sw $4, 40($29) \n\t"                                    \
5558          "lw $4, 4(%1) \n\t"                                      \
5559          "lw $5, 8(%1) \n\t"                                      \
5560          "lw $6, 12(%1) \n\t"                                     \
5561          "lw $7, 16(%1) \n\t"                                     \
5562          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5563          VALGRIND_CALL_NOREDIR_T9                                 \
5564          "addu $29, $29, 48 \n\t"                                 \
5565          "lw $28, 0($29) \n\t"                                    \
5566          "lw $31, 4($29) \n\t"                                    \
5567          "addu $29, $29, 8 \n\t"                                  \
5568          "move %0, $2\n"                                          \
5569          : /*out*/   "=r" (_res)                                  \
5570          : /*in*/    "0" (&_argvec[0])                            \
5571          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5572       );                                                          \
5573       lval = (__typeof__(lval)) _res;                             \
5574    } while (0)
5575 
5576 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
5577                                   arg6,arg7,arg8,arg9,arg10,      \
5578                                   arg11,arg12)                    \
5579    do {                                                           \
5580       volatile OrigFn        _orig = (orig);                      \
5581       volatile unsigned long _argvec[13];                         \
5582       volatile unsigned long _res;                                \
5583       _argvec[0] = (unsigned long)_orig.nraddr;                   \
5584       _argvec[1] = (unsigned long)(arg1);                         \
5585       _argvec[2] = (unsigned long)(arg2);                         \
5586       _argvec[3] = (unsigned long)(arg3);                         \
5587       _argvec[4] = (unsigned long)(arg4);                         \
5588       _argvec[5] = (unsigned long)(arg5);                         \
5589       _argvec[6] = (unsigned long)(arg6);                         \
5590       _argvec[7] = (unsigned long)(arg7);                         \
5591       _argvec[8] = (unsigned long)(arg8);                         \
5592       _argvec[9] = (unsigned long)(arg9);                         \
5593       _argvec[10] = (unsigned long)(arg10);                       \
5594       _argvec[11] = (unsigned long)(arg11);                       \
5595       _argvec[12] = (unsigned long)(arg12);                       \
5596       __asm__ volatile(                                           \
5597          "subu $29, $29, 8 \n\t"                                  \
5598          "sw $28, 0($29) \n\t"                                    \
5599          "sw $31, 4($29) \n\t"                                    \
5600          "lw $4, 20(%1) \n\t"                                     \
5601          "subu $29, $29, 56\n\t"                                  \
5602          "sw $4, 16($29) \n\t"                                    \
5603          "lw $4, 24(%1) \n\t"                                     \
5604          "sw $4, 20($29) \n\t"                                    \
5605          "lw $4, 28(%1) \n\t"                                     \
5606          "sw $4, 24($29) \n\t"                                    \
5607          "lw $4, 32(%1) \n\t"                                     \
5608          "sw $4, 28($29) \n\t"                                    \
5609          "lw $4, 36(%1) \n\t"                                     \
5610          "sw $4, 32($29) \n\t"                                    \
5611          "lw $4, 40(%1) \n\t"                                     \
5612          "sw $4, 36($29) \n\t"                                    \
5613          "lw $4, 44(%1) \n\t"                                     \
5614          "sw $4, 40($29) \n\t"                                    \
5615          "lw $4, 48(%1) \n\t"                                     \
5616          "sw $4, 44($29) \n\t"                                    \
5617          "lw $4, 4(%1) \n\t"                                      \
5618          "lw $5, 8(%1) \n\t"                                      \
5619          "lw $6, 12(%1) \n\t"                                     \
5620          "lw $7, 16(%1) \n\t"                                     \
5621          "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5622          VALGRIND_CALL_NOREDIR_T9                                 \
5623          "addu $29, $29, 56 \n\t"                                 \
5624          "lw $28, 0($29) \n\t"                                    \
5625          "lw $31, 4($29) \n\t"                                    \
5626          "addu $29, $29, 8 \n\t"                                  \
5627          "move %0, $2\n"                                          \
5628          : /*out*/   "=r" (_res)                                  \
5629          : /*in*/    "r" (&_argvec[0])                            \
5630          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5631       );                                                          \
5632       lval = (__typeof__(lval)) _res;                             \
5633    } while (0)
5634 
5635 #endif /* PLAT_mips32_linux */
5636 
5637 /* ------------------------- mips64-linux ------------------------- */
5638 
5639 #if defined(PLAT_mips64_linux)
5640 
5641 /* These regs are trashed by the hidden call. */
5642 #define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6",       \
5643 "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5644 "$25", "$31"
5645 
5646 /* These CALL_FN_ macros assume that on mips64-linux,
5647    sizeof(long long) == 8. */
5648 
5649 #define MIPS64_LONG2REG_CAST(x) ((long long)(long)x)
5650 
5651 #define CALL_FN_W_v(lval, orig)                                   \
5652    do {                                                           \
5653       volatile OrigFn        _orig = (orig);                      \
5654       volatile unsigned long long _argvec[1];                     \
5655       volatile unsigned long long _res;                           \
5656       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5657       __asm__ volatile(                                           \
5658          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5659          VALGRIND_CALL_NOREDIR_T9                                 \
5660          "move %0, $2\n"                                          \
5661          : /*out*/   "=r" (_res)                                  \
5662          : /*in*/    "0" (&_argvec[0])                            \
5663          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5664       );                                                          \
5665       lval = (__typeof__(lval)) (long)_res;                       \
5666    } while (0)
5667 
5668 #define CALL_FN_W_W(lval, orig, arg1)                             \
5669    do {                                                           \
5670       volatile OrigFn        _orig = (orig);                      \
5671       volatile unsigned long long _argvec[2];                     \
5672       volatile unsigned long long  _res;                          \
5673       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5674       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5675       __asm__ volatile(                                           \
5676          "ld $4, 8(%1)\n\t"   /* arg1*/                           \
5677          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5678          VALGRIND_CALL_NOREDIR_T9                                 \
5679          "move %0, $2\n"                                          \
5680          : /*out*/   "=r" (_res)                                  \
5681          : /*in*/    "r" (&_argvec[0])                            \
5682          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5683       );                                                          \
5684       lval = (__typeof__(lval)) (long)_res;                       \
5685    } while (0)
5686 
5687 #define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
5688    do {                                                           \
5689       volatile OrigFn        _orig = (orig);                      \
5690       volatile unsigned long long _argvec[3];                     \
5691       volatile unsigned long long _res;                           \
5692       _argvec[0] = _orig.nraddr;                                  \
5693       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5694       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5695       __asm__ volatile(                                           \
5696          "ld $4, 8(%1)\n\t"                                       \
5697          "ld $5, 16(%1)\n\t"                                      \
5698          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5699          VALGRIND_CALL_NOREDIR_T9                                 \
5700          "move %0, $2\n"                                          \
5701          : /*out*/   "=r" (_res)                                  \
5702          : /*in*/    "r" (&_argvec[0])                            \
5703          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5704       );                                                          \
5705       lval = (__typeof__(lval)) (long)_res;                       \
5706    } while (0)
5707 
5708 
5709 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
5710    do {                                                           \
5711       volatile OrigFn        _orig = (orig);                      \
5712       volatile unsigned long long _argvec[4];                     \
5713       volatile unsigned long long _res;                           \
5714       _argvec[0] = _orig.nraddr;                                  \
5715       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5716       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5717       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5718       __asm__ volatile(                                           \
5719          "ld $4, 8(%1)\n\t"                                       \
5720          "ld $5, 16(%1)\n\t"                                      \
5721          "ld $6, 24(%1)\n\t"                                      \
5722          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5723          VALGRIND_CALL_NOREDIR_T9                                 \
5724          "move %0, $2\n"                                          \
5725          : /*out*/   "=r" (_res)                                  \
5726          : /*in*/    "r" (&_argvec[0])                            \
5727          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5728       );                                                          \
5729       lval = (__typeof__(lval)) (long)_res;                       \
5730    } while (0)
5731 
5732 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
5733    do {                                                           \
5734       volatile OrigFn        _orig = (orig);                      \
5735       volatile unsigned long long _argvec[5];                     \
5736       volatile unsigned long long _res;                           \
5737       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5738       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5739       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5740       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5741       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5742       __asm__ volatile(                                           \
5743          "ld $4, 8(%1)\n\t"                                       \
5744          "ld $5, 16(%1)\n\t"                                      \
5745          "ld $6, 24(%1)\n\t"                                      \
5746          "ld $7, 32(%1)\n\t"                                      \
5747          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5748          VALGRIND_CALL_NOREDIR_T9                                 \
5749          "move %0, $2\n"                                          \
5750          : /*out*/   "=r" (_res)                                  \
5751          : /*in*/    "r" (&_argvec[0])                            \
5752          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5753       );                                                          \
5754       lval = (__typeof__(lval)) (long)_res;                       \
5755    } while (0)
5756 
5757 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
5758    do {                                                           \
5759       volatile OrigFn        _orig = (orig);                      \
5760       volatile unsigned long long _argvec[6];                     \
5761       volatile unsigned long long _res;                           \
5762       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5763       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5764       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5765       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5766       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5767       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5768       __asm__ volatile(                                           \
5769          "ld $4, 8(%1)\n\t"                                       \
5770          "ld $5, 16(%1)\n\t"                                      \
5771          "ld $6, 24(%1)\n\t"                                      \
5772          "ld $7, 32(%1)\n\t"                                      \
5773          "ld $8, 40(%1)\n\t"                                      \
5774          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5775          VALGRIND_CALL_NOREDIR_T9                                 \
5776          "move %0, $2\n"                                          \
5777          : /*out*/   "=r" (_res)                                  \
5778          : /*in*/    "r" (&_argvec[0])                            \
5779          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5780       );                                                          \
5781       lval = (__typeof__(lval)) (long)_res;                       \
5782    } while (0)
5783 
5784 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
5785    do {                                                           \
5786       volatile OrigFn        _orig = (orig);                      \
5787       volatile unsigned long long _argvec[7];                     \
5788       volatile unsigned long long _res;                           \
5789       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5790       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5791       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5792       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5793       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5794       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5795       _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5796       __asm__ volatile(                                           \
5797          "ld $4, 8(%1)\n\t"                                       \
5798          "ld $5, 16(%1)\n\t"                                      \
5799          "ld $6, 24(%1)\n\t"                                      \
5800          "ld $7, 32(%1)\n\t"                                      \
5801          "ld $8, 40(%1)\n\t"                                      \
5802          "ld $9, 48(%1)\n\t"                                      \
5803          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5804          VALGRIND_CALL_NOREDIR_T9                                 \
5805          "move %0, $2\n"                                          \
5806          : /*out*/   "=r" (_res)                                  \
5807          : /*in*/    "r" (&_argvec[0])                            \
5808          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5809       );                                                          \
5810       lval = (__typeof__(lval)) (long)_res;                       \
5811    } while (0)
5812 
5813 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5814                                  arg7)                            \
5815    do {                                                           \
5816       volatile OrigFn        _orig = (orig);                      \
5817       volatile unsigned long long _argvec[8];                     \
5818       volatile unsigned long long _res;                           \
5819       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5820       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5821       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5822       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5823       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5824       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5825       _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5826       _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5827       __asm__ volatile(                                           \
5828          "ld $4, 8(%1)\n\t"                                       \
5829          "ld $5, 16(%1)\n\t"                                      \
5830          "ld $6, 24(%1)\n\t"                                      \
5831          "ld $7, 32(%1)\n\t"                                      \
5832          "ld $8, 40(%1)\n\t"                                      \
5833          "ld $9, 48(%1)\n\t"                                      \
5834          "ld $10, 56(%1)\n\t"                                     \
5835          "ld $25, 0(%1) \n\t"  /* target->t9 */                   \
5836          VALGRIND_CALL_NOREDIR_T9                                 \
5837          "move %0, $2\n"                                          \
5838          : /*out*/   "=r" (_res)                                  \
5839          : /*in*/    "r" (&_argvec[0])                            \
5840          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5841       );                                                          \
5842       lval = (__typeof__(lval)) (long)_res;                       \
5843    } while (0)
5844 
5845 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5846                                  arg7,arg8)                       \
5847    do {                                                           \
5848       volatile OrigFn        _orig = (orig);                      \
5849       volatile unsigned long long _argvec[9];                     \
5850       volatile unsigned long long _res;                           \
5851       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5852       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5853       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5854       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5855       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5856       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5857       _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5858       _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5859       _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
5860       __asm__ volatile(                                           \
5861          "ld $4, 8(%1)\n\t"                                       \
5862          "ld $5, 16(%1)\n\t"                                      \
5863          "ld $6, 24(%1)\n\t"                                      \
5864          "ld $7, 32(%1)\n\t"                                      \
5865          "ld $8, 40(%1)\n\t"                                      \
5866          "ld $9, 48(%1)\n\t"                                      \
5867          "ld $10, 56(%1)\n\t"                                     \
5868          "ld $11, 64(%1)\n\t"                                     \
5869          "ld $25, 0(%1) \n\t"  /* target->t9 */                   \
5870          VALGRIND_CALL_NOREDIR_T9                                 \
5871          "move %0, $2\n"                                          \
5872          : /*out*/   "=r" (_res)                                  \
5873          : /*in*/    "r" (&_argvec[0])                            \
5874          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5875       );                                                          \
5876       lval = (__typeof__(lval)) (long)_res;                       \
5877    } while (0)
5878 
5879 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5880                                  arg7,arg8,arg9)                  \
5881    do {                                                           \
5882       volatile OrigFn        _orig = (orig);                      \
5883       volatile unsigned long long _argvec[10];                    \
5884       volatile unsigned long long _res;                           \
5885       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5886       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5887       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5888       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5889       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5890       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5891       _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5892       _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5893       _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
5894       _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
5895       __asm__ volatile(                                           \
5896          "dsubu $29, $29, 8\n\t"                                  \
5897          "ld $4, 72(%1)\n\t"                                      \
5898          "sd $4, 0($29)\n\t"                                      \
5899          "ld $4, 8(%1)\n\t"                                       \
5900          "ld $5, 16(%1)\n\t"                                      \
5901          "ld $6, 24(%1)\n\t"                                      \
5902          "ld $7, 32(%1)\n\t"                                      \
5903          "ld $8, 40(%1)\n\t"                                      \
5904          "ld $9, 48(%1)\n\t"                                      \
5905          "ld $10, 56(%1)\n\t"                                     \
5906          "ld $11, 64(%1)\n\t"                                     \
5907          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5908          VALGRIND_CALL_NOREDIR_T9                                 \
5909          "daddu $29, $29, 8\n\t"                                  \
5910          "move %0, $2\n"                                          \
5911          : /*out*/   "=r" (_res)                                  \
5912          : /*in*/    "r" (&_argvec[0])                            \
5913          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5914       );                                                          \
5915       lval = (__typeof__(lval)) (long)_res;                       \
5916    } while (0)
5917 
5918 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
5919                                   arg7,arg8,arg9,arg10)           \
5920    do {                                                           \
5921       volatile OrigFn        _orig = (orig);                      \
5922       volatile unsigned long long _argvec[11];                    \
5923       volatile unsigned long long _res;                           \
5924       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5925       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5926       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5927       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5928       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5929       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5930       _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5931       _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5932       _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
5933       _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
5934       _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
5935       __asm__ volatile(                                           \
5936          "dsubu $29, $29, 16\n\t"                                 \
5937          "ld $4, 72(%1)\n\t"                                      \
5938          "sd $4, 0($29)\n\t"                                      \
5939          "ld $4, 80(%1)\n\t"                                      \
5940          "sd $4, 8($29)\n\t"                                      \
5941          "ld $4, 8(%1)\n\t"                                       \
5942          "ld $5, 16(%1)\n\t"                                      \
5943          "ld $6, 24(%1)\n\t"                                      \
5944          "ld $7, 32(%1)\n\t"                                      \
5945          "ld $8, 40(%1)\n\t"                                      \
5946          "ld $9, 48(%1)\n\t"                                      \
5947          "ld $10, 56(%1)\n\t"                                     \
5948          "ld $11, 64(%1)\n\t"                                     \
5949          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5950          VALGRIND_CALL_NOREDIR_T9                                 \
5951          "daddu $29, $29, 16\n\t"                                 \
5952          "move %0, $2\n"                                          \
5953          : /*out*/   "=r" (_res)                                  \
5954          : /*in*/    "r" (&_argvec[0])                            \
5955          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5956       );                                                          \
5957       lval = (__typeof__(lval)) (long)_res;                       \
5958    } while (0)
5959 
5960 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
5961                                   arg6,arg7,arg8,arg9,arg10,      \
5962                                   arg11)                          \
5963    do {                                                           \
5964       volatile OrigFn        _orig = (orig);                      \
5965       volatile unsigned long long _argvec[12];                    \
5966       volatile unsigned long long _res;                           \
5967       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5968       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5969       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5970       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5971       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5972       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5973       _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5974       _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5975       _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
5976       _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
5977       _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
5978       _argvec[11] = MIPS64_LONG2REG_CAST(arg11);                  \
5979       __asm__ volatile(                                           \
5980          "dsubu $29, $29, 24\n\t"                                 \
5981          "ld $4, 72(%1)\n\t"                                      \
5982          "sd $4, 0($29)\n\t"                                      \
5983          "ld $4, 80(%1)\n\t"                                      \
5984          "sd $4, 8($29)\n\t"                                      \
5985          "ld $4, 88(%1)\n\t"                                      \
5986          "sd $4, 16($29)\n\t"                                     \
5987          "ld $4, 8(%1)\n\t"                                       \
5988          "ld $5, 16(%1)\n\t"                                      \
5989          "ld $6, 24(%1)\n\t"                                      \
5990          "ld $7, 32(%1)\n\t"                                      \
5991          "ld $8, 40(%1)\n\t"                                      \
5992          "ld $9, 48(%1)\n\t"                                      \
5993          "ld $10, 56(%1)\n\t"                                     \
5994          "ld $11, 64(%1)\n\t"                                     \
5995          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5996          VALGRIND_CALL_NOREDIR_T9                                 \
5997          "daddu $29, $29, 24\n\t"                                 \
5998          "move %0, $2\n"                                          \
5999          : /*out*/   "=r" (_res)                                  \
6000          : /*in*/    "r" (&_argvec[0])                            \
6001          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6002       );                                                          \
6003       lval = (__typeof__(lval)) (long)_res;                       \
6004    } while (0)
6005 
6006 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
6007                                   arg6,arg7,arg8,arg9,arg10,      \
6008                                   arg11,arg12)                    \
6009    do {                                                           \
6010       volatile OrigFn        _orig = (orig);                      \
6011       volatile unsigned long long _argvec[13];                    \
6012       volatile unsigned long long _res;                           \
6013       _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6014       _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6015       _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6016       _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6017       _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6018       _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6019       _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6020       _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6021       _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6022       _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
6023       _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
6024       _argvec[11] = MIPS64_LONG2REG_CAST(arg11);                  \
6025       _argvec[12] = MIPS64_LONG2REG_CAST(arg12);                  \
6026       __asm__ volatile(                                           \
6027          "dsubu $29, $29, 32\n\t"                                 \
6028          "ld $4, 72(%1)\n\t"                                      \
6029          "sd $4, 0($29)\n\t"                                      \
6030          "ld $4, 80(%1)\n\t"                                      \
6031          "sd $4, 8($29)\n\t"                                      \
6032          "ld $4, 88(%1)\n\t"                                      \
6033          "sd $4, 16($29)\n\t"                                     \
6034          "ld $4, 96(%1)\n\t"                                      \
6035          "sd $4, 24($29)\n\t"                                     \
6036          "ld $4, 8(%1)\n\t"                                       \
6037          "ld $5, 16(%1)\n\t"                                      \
6038          "ld $6, 24(%1)\n\t"                                      \
6039          "ld $7, 32(%1)\n\t"                                      \
6040          "ld $8, 40(%1)\n\t"                                      \
6041          "ld $9, 48(%1)\n\t"                                      \
6042          "ld $10, 56(%1)\n\t"                                     \
6043          "ld $11, 64(%1)\n\t"                                     \
6044          "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6045          VALGRIND_CALL_NOREDIR_T9                                 \
6046          "daddu $29, $29, 32\n\t"                                 \
6047          "move %0, $2\n"                                          \
6048          : /*out*/   "=r" (_res)                                  \
6049          : /*in*/    "r" (&_argvec[0])                            \
6050          : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6051       );                                                          \
6052       lval = (__typeof__(lval)) (long)_res;                       \
6053    } while (0)
6054 
6055 #endif /* PLAT_mips64_linux */
6056 
6057 /* ------------------------------------------------------------------ */
6058 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
6059 /*                                                                    */
6060 /* ------------------------------------------------------------------ */
6061 
6062 /* Some request codes.  There are many more of these, but most are not
6063    exposed to end-user view.  These are the public ones, all of the
6064    form 0x1000 + small_number.
6065 
6066    Core ones are in the range 0x00000000--0x0000ffff.  The non-public
6067    ones start at 0x2000.
6068 */
6069 
6070 /* These macros are used by tools -- they must be public, but don't
6071    embed them into other programs. */
6072 #define VG_USERREQ_TOOL_BASE(a,b) \
6073    ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
6074 #define VG_IS_TOOL_USERREQ(a, b, v) \
6075    (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
6076 
6077 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 
6078    This enum comprises an ABI exported by Valgrind to programs
6079    which use client requests.  DO NOT CHANGE THE NUMERIC VALUES OF THESE
6080    ENTRIES, NOR DELETE ANY -- add new ones at the end of the most
6081    relevant group. */
6082 typedef
6083    enum { VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
6084           VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
6085 
6086           /* These allow any function to be called from the simulated
6087              CPU but run on the real CPU.  Nb: the first arg passed to
6088              the function is always the ThreadId of the running
6089              thread!  So CLIENT_CALL0 actually requires a 1 arg
6090              function, etc. */
6091           VG_USERREQ__CLIENT_CALL0 = 0x1101,
6092           VG_USERREQ__CLIENT_CALL1 = 0x1102,
6093           VG_USERREQ__CLIENT_CALL2 = 0x1103,
6094           VG_USERREQ__CLIENT_CALL3 = 0x1104,
6095 
6096           /* Can be useful in regression testing suites -- eg. can
6097              send Valgrind's output to /dev/null and still count
6098              errors. */
6099           VG_USERREQ__COUNT_ERRORS = 0x1201,
6100 
6101           /* Allows the client program and/or gdbserver to execute a monitor
6102              command. */
6103           VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
6104 
6105           /* These are useful and can be interpreted by any tool that
6106              tracks malloc() et al, by using vg_replace_malloc.c. */
6107           VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
6108           VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
6109           VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
6110           /* Memory pool support. */
6111           VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
6112           VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
6113           VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
6114           VG_USERREQ__MEMPOOL_FREE     = 0x1306,
6115           VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
6116           VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
6117           VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
6118           VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
6119 
6120           /* Allow printfs to valgrind log. */
6121           /* The first two pass the va_list argument by value, which
6122              assumes it is the same size as or smaller than a UWord,
6123              which generally isn't the case.  Hence are deprecated.
6124              The second two pass the vargs by reference and so are
6125              immune to this problem. */
6126           /* both :: char* fmt, va_list vargs (DEPRECATED) */
6127           VG_USERREQ__PRINTF           = 0x1401,
6128           VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
6129           /* both :: char* fmt, va_list* vargs */
6130           VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
6131           VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
6132 
6133           /* Stack support. */
6134           VG_USERREQ__STACK_REGISTER   = 0x1501,
6135           VG_USERREQ__STACK_DEREGISTER = 0x1502,
6136           VG_USERREQ__STACK_CHANGE     = 0x1503,
6137 
6138           /* Wine support */
6139           VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
6140 
6141           /* Querying of debug info. */
6142           VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
6143 
6144           /* Disable/enable error reporting level.  Takes a single
6145              Word arg which is the delta to this thread's error
6146              disablement indicator.  Hence 1 disables or further
6147              disables errors, and -1 moves back towards enablement.
6148              Other values are not allowed. */
6149           VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
6150 
6151           /* Some requests used for Valgrind internal, such as
6152              self-test or self-hosting. */
6153           /* Initialise IR injection */
6154           VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901,
6155           /* Used by Inner Valgrind to inform Outer Valgrind where to
6156              find the list of inner guest threads */
6157           VG_USERREQ__INNER_THREADS    = 0x1902,
6158    } Vg_ClientRequest;
6159 
6160 #if !defined(__GNUC__)
6161 #  define __extension__ /* */
6162 #endif
6163 
6164 
6165 /* Returns the number of Valgrinds this code is running under.  That
6166    is, 0 if running natively, 1 if running under Valgrind, 2 if
6167    running under Valgrind which is running under another Valgrind,
6168    etc. */
6169 #define RUNNING_ON_VALGRIND                                           \
6170     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */,         \
6171                                     VG_USERREQ__RUNNING_ON_VALGRIND,  \
6172                                     0, 0, 0, 0, 0)                    \
6173 
6174 
6175 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
6176    _qzz_len - 1].  Useful if you are debugging a JITter or some such,
6177    since it provides a way to make sure valgrind will retranslate the
6178    invalidated area.  Returns no value. */
6179 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len)              \
6180     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS,  \
6181                                     _qzz_addr, _qzz_len, 0, 0, 0)
6182 
6183 #define VALGRIND_INNER_THREADS(_qzz_addr)                               \
6184    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__INNER_THREADS,           \
6185                                    _qzz_addr, 0, 0, 0, 0)
6186 
6187 
6188 /* These requests are for getting Valgrind itself to print something.
6189    Possibly with a backtrace.  This is a really ugly hack.  The return value
6190    is the number of characters printed, excluding the "**<pid>** " part at the
6191    start and the backtrace (if present). */
6192 
6193 #if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6194 /* Modern GCC will optimize the static routine out if unused,
6195    and unused attribute will shut down warnings about it.  */
6196 static int VALGRIND_PRINTF(const char *format, ...)
6197    __attribute__((format(__printf__, 1, 2), __unused__));
6198 #endif
6199 static int
6200 #if defined(_MSC_VER)
6201 __inline
6202 #endif
6203 VALGRIND_PRINTF(const char *format, ...)
6204 {
6205 #if defined(NVALGRIND)
6206    (void)format;
6207    return 0;
6208 #else /* NVALGRIND */
6209 #if defined(_MSC_VER) || defined(__MINGW64__)
6210    uintptr_t _qzz_res;
6211 #else
6212    unsigned long _qzz_res;
6213 #endif
6214    va_list vargs;
6215    va_start(vargs, format);
6216 #if defined(_MSC_VER) || defined(__MINGW64__)
6217    _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6218                               VG_USERREQ__PRINTF_VALIST_BY_REF,
6219                               (uintptr_t)format,
6220                               (uintptr_t)&vargs,
6221                               0, 0, 0);
6222 #else
6223    _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6224                               VG_USERREQ__PRINTF_VALIST_BY_REF,
6225                               (unsigned long)format,
6226                               (unsigned long)&vargs, 
6227                               0, 0, 0);
6228 #endif
6229    va_end(vargs);
6230    return (int)_qzz_res;
6231 #endif /* NVALGRIND */
6232 }
6233 
6234 #if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6235 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6236    __attribute__((format(__printf__, 1, 2), __unused__));
6237 #endif
6238 static int
6239 #if defined(_MSC_VER)
6240 __inline
6241 #endif
6242 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6243 {
6244 #if defined(NVALGRIND)
6245    (void)format;
6246    return 0;
6247 #else /* NVALGRIND */
6248 #if defined(_MSC_VER) || defined(__MINGW64__)
6249    uintptr_t _qzz_res;
6250 #else
6251    unsigned long _qzz_res;
6252 #endif
6253    va_list vargs;
6254    va_start(vargs, format);
6255 #if defined(_MSC_VER) || defined(__MINGW64__)
6256    _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6257                               VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6258                               (uintptr_t)format,
6259                               (uintptr_t)&vargs,
6260                               0, 0, 0);
6261 #else
6262    _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6263                               VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6264                               (unsigned long)format,
6265                               (unsigned long)&vargs, 
6266                               0, 0, 0);
6267 #endif
6268    va_end(vargs);
6269    return (int)_qzz_res;
6270 #endif /* NVALGRIND */
6271 }
6272 
6273 
6274 /* These requests allow control to move from the simulated CPU to the
6275    real CPU, calling an arbitrary function.
6276    
6277    Note that the current ThreadId is inserted as the first argument.
6278    So this call:
6279 
6280      VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
6281 
6282    requires f to have this signature:
6283 
6284      Word f(Word tid, Word arg1, Word arg2)
6285 
6286    where "Word" is a word-sized type.
6287 
6288    Note that these client requests are not entirely reliable.  For example,
6289    if you call a function with them that subsequently calls printf(),
6290    there's a high chance Valgrind will crash.  Generally, your prospects of
6291    these working are made higher if the called function does not refer to
6292    any global variables, and does not refer to any libc or other functions
6293    (printf et al).  Any kind of entanglement with libc or dynamic linking is
6294    likely to have a bad outcome, for tricky reasons which we've grappled
6295    with a lot in the past.
6296 */
6297 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn)                          \
6298     VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,       \
6299                                     VG_USERREQ__CLIENT_CALL0,     \
6300                                     _qyy_fn,                      \
6301                                     0, 0, 0, 0)
6302 
6303 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1)                    \
6304     VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,            \
6305                                     VG_USERREQ__CLIENT_CALL1,          \
6306                                     _qyy_fn,                           \
6307                                     _qyy_arg1, 0, 0, 0)
6308 
6309 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2)         \
6310     VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,            \
6311                                     VG_USERREQ__CLIENT_CALL2,          \
6312                                     _qyy_fn,                           \
6313                                     _qyy_arg1, _qyy_arg2, 0, 0)
6314 
6315 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
6316     VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,             \
6317                                     VG_USERREQ__CLIENT_CALL3,           \
6318                                     _qyy_fn,                            \
6319                                     _qyy_arg1, _qyy_arg2,               \
6320                                     _qyy_arg3, 0)
6321 
6322 
6323 /* Counts the number of errors that have been recorded by a tool.  Nb:
6324    the tool must record the errors with VG_(maybe_record_error)() or
6325    VG_(unique_error)() for them to be counted. */
6326 #define VALGRIND_COUNT_ERRORS                                     \
6327     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(                    \
6328                                0 /* default return */,            \
6329                                VG_USERREQ__COUNT_ERRORS,          \
6330                                0, 0, 0, 0, 0)
6331 
6332 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
6333    when heap blocks are allocated in order to give accurate results.  This
6334    happens automatically for the standard allocator functions such as
6335    malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
6336    delete[], etc.
6337 
6338    But if your program uses a custom allocator, this doesn't automatically
6339    happen, and Valgrind will not do as well.  For example, if you allocate
6340    superblocks with mmap() and then allocates chunks of the superblocks, all
6341    Valgrind's observations will be at the mmap() level and it won't know that
6342    the chunks should be considered separate entities.  In Memcheck's case,
6343    that means you probably won't get heap block overrun detection (because
6344    there won't be redzones marked as unaddressable) and you definitely won't
6345    get any leak detection.
6346 
6347    The following client requests allow a custom allocator to be annotated so
6348    that it can be handled accurately by Valgrind.
6349 
6350    VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
6351    by a malloc()-like function.  For Memcheck (an illustrative case), this
6352    does two things:
6353 
6354    - It records that the block has been allocated.  This means any addresses
6355      within the block mentioned in error messages will be
6356      identified as belonging to the block.  It also means that if the block
6357      isn't freed it will be detected by the leak checker.
6358 
6359    - It marks the block as being addressable and undefined (if 'is_zeroed' is
6360      not set), or addressable and defined (if 'is_zeroed' is set).  This
6361      controls how accesses to the block by the program are handled.
6362    
6363    'addr' is the start of the usable block (ie. after any
6364    redzone), 'sizeB' is its size.  'rzB' is the redzone size if the allocator
6365    can apply redzones -- these are blocks of padding at the start and end of
6366    each block.  Adding redzones is recommended as it makes it much more likely
6367    Valgrind will spot block overruns.  `is_zeroed' indicates if the memory is
6368    zeroed (or filled with another predictable value), as is the case for
6369    calloc().
6370    
6371    VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
6372    heap block -- that will be used by the client program -- is allocated.
6373    It's best to put it at the outermost level of the allocator if possible;
6374    for example, if you have a function my_alloc() which calls
6375    internal_alloc(), and the client request is put inside internal_alloc(),
6376    stack traces relating to the heap block will contain entries for both
6377    my_alloc() and internal_alloc(), which is probably not what you want.
6378 
6379    For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
6380    custom blocks from within a heap block, B, that has been allocated with
6381    malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
6382    -- the custom blocks will take precedence.
6383 
6384    VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK.  For
6385    Memcheck, it does two things:
6386 
6387    - It records that the block has been deallocated.  This assumes that the
6388      block was annotated as having been allocated via
6389      VALGRIND_MALLOCLIKE_BLOCK.  Otherwise, an error will be issued.
6390 
6391    - It marks the block as being unaddressable.
6392 
6393    VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
6394    heap block is deallocated.
6395 
6396    VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
6397    Memcheck, it does four things:
6398 
6399    - It records that the size of a block has been changed.  This assumes that
6400      the block was annotated as having been allocated via
6401      VALGRIND_MALLOCLIKE_BLOCK.  Otherwise, an error will be issued.
6402 
6403    - If the block shrunk, it marks the freed memory as being unaddressable.
6404 
6405    - If the block grew, it marks the new area as undefined and defines a red
6406      zone past the end of the new block.
6407 
6408    - The V-bits of the overlap between the old and the new block are preserved.
6409 
6410    VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
6411    and before deallocation of the old block.
6412 
6413    In many cases, these three client requests will not be enough to get your
6414    allocator working well with Memcheck.  More specifically, if your allocator
6415    writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
6416    will be necessary to mark the memory as addressable just before the zeroing
6417    occurs, otherwise you'll get a lot of invalid write errors.  For example,
6418    you'll need to do this if your allocator recycles freed blocks, but it
6419    zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
6420    Alternatively, if your allocator reuses freed blocks for allocator-internal
6421    data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
6422 
6423    Really, what's happening is a blurring of the lines between the client
6424    program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
6425    memory should be considered unaddressable to the client program, but the
6426    allocator knows more than the rest of the client program and so may be able
6427    to safely access it.  Extra client requests are necessary for Valgrind to
6428    understand the distinction between the allocator and the rest of the
6429    program.
6430 
6431    Ignored if addr == 0.
6432 */
6433 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)          \
6434     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK,       \
6435                                     addr, sizeB, rzB, is_zeroed, 0)
6436 
6437 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6438    Ignored if addr == 0.
6439 */
6440 #define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB)     \
6441     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK,    \
6442                                     addr, oldSizeB, newSizeB, rzB, 0)
6443 
6444 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6445    Ignored if addr == 0.
6446 */
6447 #define VALGRIND_FREELIKE_BLOCK(addr, rzB)                              \
6448     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK,         \
6449                                     addr, rzB, 0, 0, 0)
6450 
6451 /* Create a memory pool. */
6452 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)             \
6453     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL,   \
6454                                     pool, rzB, is_zeroed, 0, 0)
6455 
6456 /* Create a memory pool with some flags specifying extended behaviour.
6457    When flags is zero, the behaviour is identical to VALGRIND_CREATE_MEMPOOL.
6458    
6459    The flag VALGRIND_MEMPOOL_METAPOOL specifies that the pieces of memory 
6460    associated with the pool using VALGRIND_MEMPOOL_ALLOC  will be used
6461    by the application as superblocks to dole out MALLOC_LIKE blocks using
6462    VALGRIND_MALLOCLIKE_BLOCK. In other words, a meta pool is a "2 levels"
6463    pool : first level is the blocks described by VALGRIND_MEMPOOL_ALLOC.
6464    The second level blocks are described using VALGRIND_MALLOCLIKE_BLOCK.
6465    Note that the association between the pool and the second level blocks
6466    is implicit : second level blocks will be located inside first level
6467    blocks. It is necessary to use the VALGRIND_MEMPOOL_METAPOOL flag
6468    for such 2 levels pools, as otherwise valgrind will detect overlapping
6469    memory blocks, and will abort execution (e.g. during leak search).
6470 
6471    Such a meta pool can also be marked as an 'auto free' pool using the flag
6472    VALGRIND_MEMPOOL_AUTO_FREE, which must be OR-ed together with the
6473    VALGRIND_MEMPOOL_METAPOOL. For an 'auto free' pool, VALGRIND_MEMPOOL_FREE
6474    will automatically free the second level blocks that are contained
6475    inside the first level block freed with VALGRIND_MEMPOOL_FREE.
6476    In other words, calling VALGRIND_MEMPOOL_FREE will cause implicit calls
6477    to VALGRIND_FREELIKE_BLOCK for all the second level blocks included
6478    in the first level block.
6479    Note: it is an error to use the VALGRIND_MEMPOOL_AUTO_FREE flag
6480    without the VALGRIND_MEMPOOL_METAPOOL flag.
6481 */
6482 #define VALGRIND_MEMPOOL_AUTO_FREE  1
6483 #define VALGRIND_MEMPOOL_METAPOOL   2
6484 #define VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags)        \
6485    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL,          \
6486                                    pool, rzB, is_zeroed, flags, 0)
6487 
6488 /* Destroy a memory pool. */
6489 #define VALGRIND_DESTROY_MEMPOOL(pool)                            \
6490     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL,  \
6491                                     pool, 0, 0, 0, 0)
6492 
6493 /* Associate a piece of memory with a memory pool. */
6494 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)                  \
6495     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC,    \
6496                                     pool, addr, size, 0, 0)
6497 
6498 /* Disassociate a piece of memory from a memory pool. */
6499 #define VALGRIND_MEMPOOL_FREE(pool, addr)                         \
6500     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE,     \
6501                                     pool, addr, 0, 0, 0)
6502 
6503 /* Disassociate any pieces outside a particular range. */
6504 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size)                   \
6505     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM,     \
6506                                     pool, addr, size, 0, 0)
6507 
6508 /* Resize and/or move a piece associated with a memory pool. */
6509 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB)                       \
6510     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL,     \
6511                                     poolA, poolB, 0, 0, 0)
6512 
6513 /* Resize and/or move a piece associated with a memory pool. */
6514 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size)         \
6515     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE,   \
6516                                     pool, addrA, addrB, size, 0)
6517 
6518 /* Return 1 if a mempool exists, else 0. */
6519 #define VALGRIND_MEMPOOL_EXISTS(pool)                             \
6520     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
6521                                VG_USERREQ__MEMPOOL_EXISTS,        \
6522                                pool, 0, 0, 0, 0)
6523 
6524 /* Mark a piece of memory as being a stack. Returns a stack id.
6525    start is the lowest addressable stack byte, end is the highest
6526    addressable stack byte. */
6527 #define VALGRIND_STACK_REGISTER(start, end)                       \
6528     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
6529                                VG_USERREQ__STACK_REGISTER,        \
6530                                start, end, 0, 0, 0)
6531 
6532 /* Unmark the piece of memory associated with a stack id as being a
6533    stack. */
6534 #define VALGRIND_STACK_DEREGISTER(id)                             \
6535     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
6536                                     id, 0, 0, 0, 0)
6537 
6538 /* Change the start and end address of the stack id.
6539    start is the new lowest addressable stack byte, end is the new highest
6540    addressable stack byte. */
6541 #define VALGRIND_STACK_CHANGE(id, start, end)                     \
6542     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE,     \
6543                                     id, start, end, 0, 0)
6544 
6545 /* Load PDB debug info for Wine PE image_map. */
6546 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta)     \
6547     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
6548                                     fd, ptr, total_size, delta, 0)
6549 
6550 /* Map a code address to a source file name and line number.  buf64
6551    must point to a 64-byte buffer in the caller's address space.  The
6552    result will be dumped in there and is guaranteed to be zero
6553    terminated.  If no info is found, the first byte is set to zero. */
6554 #define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64)                    \
6555     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
6556                                VG_USERREQ__MAP_IP_TO_SRCLOC,      \
6557                                addr, buf64, 0, 0, 0)
6558 
6559 /* Disable error reporting for this thread.  Behaves in a stack like
6560    way, so you can safely call this multiple times provided that
6561    VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
6562    to re-enable reporting.  The first call of this macro disables
6563    reporting.  Subsequent calls have no effect except to increase the
6564    number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
6565    reporting.  Child threads do not inherit this setting from their
6566    parents -- they are always created with reporting enabled. */
6567 #define VALGRIND_DISABLE_ERROR_REPORTING                                \
6568     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6569                                     1, 0, 0, 0, 0)
6570 
6571 /* Re-enable error reporting, as per comments on
6572    VALGRIND_DISABLE_ERROR_REPORTING. */
6573 #define VALGRIND_ENABLE_ERROR_REPORTING                                 \
6574     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6575                                     -1, 0, 0, 0, 0)
6576 
6577 /* Execute a monitor command from the client program.
6578    If a connection is opened with GDB, the output will be sent
6579    according to the output mode set for vgdb.
6580    If no connection is opened, output will go to the log output.
6581    Returns 1 if command not recognised, 0 otherwise. */
6582 #define VALGRIND_MONITOR_COMMAND(command)                               \
6583    VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
6584                                    command, 0, 0, 0, 0)
6585 
6586 
6587 #undef PLAT_x86_darwin
6588 #undef PLAT_amd64_darwin
6589 #undef PLAT_x86_win32
6590 #undef PLAT_amd64_win64
6591 #undef PLAT_x86_linux
6592 #undef PLAT_amd64_linux
6593 #undef PLAT_ppc32_linux
6594 #undef PLAT_ppc64be_linux
6595 #undef PLAT_ppc64le_linux
6596 #undef PLAT_arm_linux
6597 #undef PLAT_s390x_linux
6598 #undef PLAT_mips32_linux
6599 #undef PLAT_mips64_linux
6600 #undef PLAT_x86_solaris
6601 #undef PLAT_amd64_solaris
6602 
6603 #endif   /* __VALGRIND_H */