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