1/* -*- c -*-
2   ----------------------------------------------------------------
3
4   Notice that the following BSD-style license applies to this one
5   file (valgrind.h) only.  The rest of Valgrind is licensed under the
6   terms of the GNU General Public License, version 2, unless
7   otherwise indicated.  See the COPYING file in the source
8   distribution for details.
9
10   ----------------------------------------------------------------
11
12   This file is part of Valgrind, a dynamic binary instrumentation
13   framework.
14
15   Copyright (C) 2000-2017 Julian Seward.  All rights reserved.
16
17   Redistribution and use in source and binary forms, with or without
18   modification, are permitted provided that the following conditions
19   are met:
20
21   1. Redistributions of source code must retain the above copyright
22      notice, this list of conditions and the following disclaimer.
23
24   2. The origin of this software must not be misrepresented; you must
25      not claim that you wrote the original software.  If you use this
26      software in a product, an acknowledgment in the product
27      documentation would be appreciated but is not required.
28
29   3. Altered source versions must be plainly marked as such, and must
30      not be misrepresented as being the original software.
31
32   4. The name of the author may not be used to endorse or promote
33      products derived from this software without specific prior written
34      permission.
35
36   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48   ----------------------------------------------------------------
49
50   Notice that the above BSD-style license applies to this one file
51   (valgrind.h) only.  The entire rest of Valgrind is licensed under
52   the terms of the GNU General Public License, version 2.  See the
53   COPYING file in the source distribution for details.
54
55   ----------------------------------------------------------------
56*/
57
58
59/* This file is for inclusion into client (your!) code.
60
61   You can use these macros to manipulate and query Valgrind's
62   execution inside your own programs.
63
64   The resulting executables will still run without Valgrind, just a
65   little bit more slowly than they otherwise would, but otherwise
66   unchanged.  When not running on valgrind, each client request
67   consumes very few (eg. 7) instructions, so the resulting performance
68   loss is negligible unless you plan to execute client requests
69   millions of times per second.  Nevertheless, if that is still a
70   problem, you can compile with the NVALGRIND symbol defined (gcc
71   -DNVALGRIND) so that client requests are not even compiled in.  */
72
73#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
76
77/* ------------------------------------------------------------------ */
78/* VERSION NUMBER OF VALGRIND                                         */
79/* ------------------------------------------------------------------ */
80
81/* Specify Valgrind's version number, so that user code can
82   conditionally compile based on our version number.  Note that these
83   were introduced at version 3.6 and so do not exist in version 3.5
84   or earlier.  The recommended way to use them to check for "version
85   X.Y or later" is (eg)
86
87#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__)   \
88    && (__VALGRIND_MAJOR__ > 3                                   \
89        || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
90*/
91#define __VALGRIND_MAJOR__    3
92#define __VALGRIND_MINOR__    18
93
94
95#include <stdarg.h>
96
97/* Nb: this file might be included in a file compiled with -ansi.  So
98   we can't use C++ style "//" comments nor the "asm" keyword (instead
99   use "__asm__"). */
100
101/* Derive some tags indicating what the target platform is.  Note
102   that in this file we're using the compiler's CPP symbols for
103   identifying architectures, which are different to the ones we use
104   within the rest of Valgrind.  Note, __powerpc__ is active for both
105   32 and 64-bit PPC, whereas __powerpc64__ is only active for the
106   latter (on Linux, that is).
107
108   Misc note: how to find out what's predefined in gcc by default:
109   gcc -Wp,-dM somefile.c
110*/
111#undef PLAT_x86_darwin
112#undef PLAT_amd64_darwin
113#undef PLAT_x86_freebsd
114#undef PLAT_amd64_freebsd
115#undef PLAT_x86_win32
116#undef PLAT_amd64_win64
117#undef PLAT_x86_linux
118#undef PLAT_amd64_linux
119#undef PLAT_ppc32_linux
120#undef PLAT_ppc64be_linux
121#undef PLAT_ppc64le_linux
122#undef PLAT_arm_linux
123#undef PLAT_arm64_linux
124#undef PLAT_s390x_linux
125#undef PLAT_mips32_linux
126#undef PLAT_mips64_linux
127#undef PLAT_nanomips_linux
128#undef PLAT_x86_solaris
129#undef PLAT_amd64_solaris
130
131
132#if defined(__APPLE__) && defined(__i386__)
133#  define PLAT_x86_darwin 1
134#elif defined(__APPLE__) && defined(__x86_64__)
135#  define PLAT_amd64_darwin 1
136#elif defined(__FreeBSD__) && defined(__i386__)
137#  define PLAT_x86_freebsd 1
138#elif defined(__FreeBSD__) && defined(__amd64__)
139#  define PLAT_amd64_freebsd 1
140#elif (defined(__MINGW32__) && defined(__i386__)) \
141      || defined(__CYGWIN32__) \
142      || (defined(_WIN32) && defined(_M_IX86))
143#  define PLAT_x86_win32 1
144#elif (defined(__MINGW32__) && defined(__x86_64__)) \
145      || (defined(_WIN32) && defined(_M_X64))
146/* __MINGW32__ and _WIN32 are defined in 64 bit mode as well. */
147#  define PLAT_amd64_win64 1
148#elif defined(__linux__) && defined(__i386__)
149#  define PLAT_x86_linux 1
150#elif defined(__linux__) && defined(__x86_64__) && !defined(__ILP32__)
151#  define PLAT_amd64_linux 1
152#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
153#  define PLAT_ppc32_linux 1
154#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
155/* Big Endian uses ELF version 1 */
156#  define PLAT_ppc64be_linux 1
157#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2
158/* Little Endian uses ELF version 2 */
159#  define PLAT_ppc64le_linux 1
160#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
161#  define PLAT_arm_linux 1
162#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
163#  define PLAT_arm64_linux 1
164#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
165#  define PLAT_s390x_linux 1
166#elif defined(__linux__) && defined(__mips__) && (__mips==64)
167#  define PLAT_mips64_linux 1
168#elif defined(__linux__) && defined(__mips__) && (__mips==32)
169#  define PLAT_mips32_linux 1
170#elif defined(__linux__) && defined(__nanomips__)
171#  define PLAT_nanomips_linux 1
172#elif defined(__sun) && defined(__i386__)
173#  define PLAT_x86_solaris 1
174#elif defined(__sun) && defined(__x86_64__)
175#  define PLAT_amd64_solaris 1
176#else
177/* If we're not compiling for our target platform, don't generate
178   any inline asms.  */
179#  if !defined(NVALGRIND)
180#    define NVALGRIND 1
181#  endif
182#endif
183
184
185/* ------------------------------------------------------------------ */
186/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS.  There is nothing */
187/* in here of use to end-users -- skip to the next section.           */
188/* ------------------------------------------------------------------ */
189
190/*
191 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
192 * request. Accepts both pointers and integers as arguments.
193 *
194 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
195 * client request that does not return a value.
196
197 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
198 * client request and whose value equals the client request result.  Accepts
199 * both pointers and integers as arguments.  Note that such calls are not
200 * necessarily pure functions -- they may have side effects.
201 */
202
203#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default,            \
204                                   _zzq_request, _zzq_arg1, _zzq_arg2,  \
205                                   _zzq_arg3, _zzq_arg4, _zzq_arg5)     \
206  do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default),   \
207                        (_zzq_request), (_zzq_arg1), (_zzq_arg2),       \
208                        (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
209
210#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1,        \
211                           _zzq_arg2,  _zzq_arg3, _zzq_arg4, _zzq_arg5) \
212  do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                        \
213                    (_zzq_request), (_zzq_arg1), (_zzq_arg2),           \
214                    (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
215
216#if defined(NVALGRIND)
217
218/* Define NVALGRIND to completely remove the Valgrind magic sequence
219   from the compiled code (analogous to NDEBUG's effects on
220   assert()) */
221#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
222        _zzq_default, _zzq_request,                               \
223        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
224      (_zzq_default)
225
226#else  /* ! NVALGRIND */
227
228/* The following defines the magic code sequences which the JITter
229   spots and handles magically.  Don't look too closely at them as
230   they will rot your brain.
231
232   The assembly code sequences for all architectures is in this one
233   file.  This is because this file must be stand-alone, and we don't
234   want to have multiple files.
235
236   For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
237   value gets put in the return slot, so that everything works when
238   this is executed not under Valgrind.  Args are passed in a memory
239   block, and so there's no intrinsic limit to the number that could
240   be passed, but it's currently five.
241
242   The macro args are:
243      _zzq_rlval    result lvalue
244      _zzq_default  default value (result returned when running on real CPU)
245      _zzq_request  request code
246      _zzq_arg1..5  request params
247
248   The other two macros are used to support function wrapping, and are
249   a lot simpler.  VALGRIND_GET_NR_CONTEXT returns the value of the
250   guest's NRADDR pseudo-register and whatever other information is
251   needed to safely run the call original from the wrapper: on
252   ppc64-linux, the R2 value at the divert point is also needed.  This
253   information is abstracted into a user-visible type, OrigFn.
254
255   VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
256   guest, but guarantees that the branch instruction will not be
257   redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
258   branch-and-link-to-r11.  VALGRIND_CALL_NOREDIR is just text, not a
259   complete inline asm, since it needs to be combined with more magic
260   inline asm stuff to be useful.
261*/
262
263/* ----------------- x86-{linux,darwin,solaris} ---------------- */
264
265#if defined(PLAT_x86_linux)  ||  defined(PLAT_x86_darwin)  \
266    ||  (defined(PLAT_x86_win32) && defined(__GNUC__)) \
267    ||  defined(PLAT_x86_solaris) || defined(PLAT_x86_freebsd)
268
269typedef
270   struct {
271      unsigned int nraddr; /* where's the code? */
272   }
273   OrigFn;
274
275#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
276                     "roll $3,  %%edi ; roll $13, %%edi\n\t"      \
277                     "roll $29, %%edi ; roll $19, %%edi\n\t"
278
279#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
280        _zzq_default, _zzq_request,                               \
281        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
282  __extension__                                                   \
283  ({volatile unsigned int _zzq_args[6];                           \
284    volatile unsigned int _zzq_result;                            \
285    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
286    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
287    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
288    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
289    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
290    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
291    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
292                     /* %EDX = client_request ( %EAX ) */         \
293                     "xchgl %%ebx,%%ebx"                          \
294                     : "=d" (_zzq_result)                         \
295                     : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
296                     : "cc", "memory"                             \
297                    );                                            \
298    _zzq_result;                                                  \
299  })
300
301#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
302  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
303    volatile unsigned int __addr;                                 \
304    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
305                     /* %EAX = guest_NRADDR */                    \
306                     "xchgl %%ecx,%%ecx"                          \
307                     : "=a" (__addr)                              \
308                     :                                            \
309                     : "cc", "memory"                             \
310                    );                                            \
311    _zzq_orig->nraddr = __addr;                                   \
312  }
313
314#define VALGRIND_CALL_NOREDIR_EAX                                 \
315                     __SPECIAL_INSTRUCTION_PREAMBLE               \
316                     /* call-noredir *%EAX */                     \
317                     "xchgl %%edx,%%edx\n\t"
318
319#define VALGRIND_VEX_INJECT_IR()                                 \
320 do {                                                            \
321    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
322                     "xchgl %%edi,%%edi\n\t"                     \
323                     : : : "cc", "memory"                        \
324                    );                                           \
325 } while (0)
326
327#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__)
328          || PLAT_x86_solaris */
329
330/* ------------------------- x86-Win32 ------------------------- */
331
332#if defined(PLAT_x86_win32) && !defined(__GNUC__)
333
334typedef
335   struct {
336      unsigned int nraddr; /* where's the code? */
337   }
338   OrigFn;
339
340#if defined(_MSC_VER)
341
342#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
343                     __asm rol edi, 3  __asm rol edi, 13          \
344                     __asm rol edi, 29 __asm rol edi, 19
345
346#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
347        _zzq_default, _zzq_request,                               \
348        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
349    valgrind_do_client_request_expr((uintptr_t)(_zzq_default),    \
350        (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1),        \
351        (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3),           \
352        (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
353
354static __inline uintptr_t
355valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
356                                uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
357                                uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
358                                uintptr_t _zzq_arg5)
359{
360    volatile uintptr_t _zzq_args[6];
361    volatile unsigned int _zzq_result;
362    _zzq_args[0] = (uintptr_t)(_zzq_request);
363    _zzq_args[1] = (uintptr_t)(_zzq_arg1);
364    _zzq_args[2] = (uintptr_t)(_zzq_arg2);
365    _zzq_args[3] = (uintptr_t)(_zzq_arg3);
366    _zzq_args[4] = (uintptr_t)(_zzq_arg4);
367    _zzq_args[5] = (uintptr_t)(_zzq_arg5);
368    __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
369            __SPECIAL_INSTRUCTION_PREAMBLE
370            /* %EDX = client_request ( %EAX ) */
371            __asm xchg ebx,ebx
372            __asm mov _zzq_result, edx
373    }
374    return _zzq_result;
375}
376
377#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
378  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
379    volatile unsigned int __addr;                                 \
380    __asm { __SPECIAL_INSTRUCTION_PREAMBLE                        \
381            /* %EAX = guest_NRADDR */                             \
382            __asm xchg ecx,ecx                                    \
383            __asm mov __addr, eax                                 \
384    }                                                             \
385    _zzq_orig->nraddr = __addr;                                   \
386  }
387
388#define VALGRIND_CALL_NOREDIR_EAX ERROR
389
390#define VALGRIND_VEX_INJECT_IR()                                 \
391 do {                                                            \
392    __asm { __SPECIAL_INSTRUCTION_PREAMBLE                       \
393            __asm xchg edi,edi                                   \
394    }                                                            \
395 } while (0)
396
397#else
398#error Unsupported compiler.
399#endif
400
401#endif /* PLAT_x86_win32 */
402
403/* ----------------- amd64-{linux,darwin,solaris} --------------- */
404
405#if defined(PLAT_amd64_linux)  ||  defined(PLAT_amd64_darwin) \
406    ||  defined(PLAT_amd64_solaris) \
407    ||  defined(PLAT_amd64_freebsd) \
408    ||  (defined(PLAT_amd64_win64) && defined(__GNUC__))
409
410typedef
411   struct {
412      unsigned long int nraddr; /* where's the code? */
413   }
414   OrigFn;
415
416#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
417                     "rolq $3,  %%rdi ; rolq $13, %%rdi\n\t"      \
418                     "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
419
420#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
421        _zzq_default, _zzq_request,                               \
422        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
423    __extension__                                                 \
424    ({ volatile unsigned long int _zzq_args[6];                   \
425    volatile unsigned long int _zzq_result;                       \
426    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
427    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
428    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
429    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
430    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
431    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
432    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
433                     /* %RDX = client_request ( %RAX ) */         \
434                     "xchgq %%rbx,%%rbx"                          \
435                     : "=d" (_zzq_result)                         \
436                     : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
437                     : "cc", "memory"                             \
438                    );                                            \
439    _zzq_result;                                                  \
440    })
441
442#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
443  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
444    volatile unsigned long int __addr;                            \
445    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
446                     /* %RAX = guest_NRADDR */                    \
447                     "xchgq %%rcx,%%rcx"                          \
448                     : "=a" (__addr)                              \
449                     :                                            \
450                     : "cc", "memory"                             \
451                    );                                            \
452    _zzq_orig->nraddr = __addr;                                   \
453  }
454
455#define VALGRIND_CALL_NOREDIR_RAX                                 \
456                     __SPECIAL_INSTRUCTION_PREAMBLE               \
457                     /* call-noredir *%RAX */                     \
458                     "xchgq %%rdx,%%rdx\n\t"
459
460#define VALGRIND_VEX_INJECT_IR()                                 \
461 do {                                                            \
462    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
463                     "xchgq %%rdi,%%rdi\n\t"                     \
464                     : : : "cc", "memory"                        \
465                    );                                           \
466 } while (0)
467
468#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
469
470/* ------------------------- amd64-Win64 ------------------------- */
471
472#if defined(PLAT_amd64_win64) && !defined(__GNUC__)
473
474#error Unsupported compiler.
475
476#endif /* PLAT_amd64_win64 */
477
478/* ------------------------ ppc32-linux ------------------------ */
479
480#if defined(PLAT_ppc32_linux)
481
482typedef
483   struct {
484      unsigned int nraddr; /* where's the code? */
485   }
486   OrigFn;
487
488#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
489                    "rlwinm 0,0,3,0,31  ; rlwinm 0,0,13,0,31\n\t" \
490                    "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
491
492#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
493        _zzq_default, _zzq_request,                               \
494        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
495                                                                  \
496    __extension__                                                 \
497  ({         unsigned int  _zzq_args[6];                          \
498             unsigned int  _zzq_result;                           \
499             unsigned int* _zzq_ptr;                              \
500    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
501    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
502    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
503    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
504    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
505    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
506    _zzq_ptr = _zzq_args;                                         \
507    __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
508                     "mr 4,%2\n\t" /*ptr*/                        \
509                     __SPECIAL_INSTRUCTION_PREAMBLE               \
510                     /* %R3 = client_request ( %R4 ) */           \
511                     "or 1,1,1\n\t"                               \
512                     "mr %0,3"     /*result*/                     \
513                     : "=b" (_zzq_result)                         \
514                     : "b" (_zzq_default), "b" (_zzq_ptr)         \
515                     : "cc", "memory", "r3", "r4");               \
516    _zzq_result;                                                  \
517    })
518
519#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
520  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
521    unsigned int __addr;                                          \
522    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
523                     /* %R3 = guest_NRADDR */                     \
524                     "or 2,2,2\n\t"                               \
525                     "mr %0,3"                                    \
526                     : "=b" (__addr)                              \
527                     :                                            \
528                     : "cc", "memory", "r3"                       \
529                    );                                            \
530    _zzq_orig->nraddr = __addr;                                   \
531  }
532
533#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
534                     __SPECIAL_INSTRUCTION_PREAMBLE               \
535                     /* branch-and-link-to-noredir *%R11 */       \
536                     "or 3,3,3\n\t"
537
538#define VALGRIND_VEX_INJECT_IR()                                 \
539 do {                                                            \
540    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
541                     "or 5,5,5\n\t"                              \
542                    );                                           \
543 } while (0)
544
545#endif /* PLAT_ppc32_linux */
546
547/* ------------------------ ppc64-linux ------------------------ */
548
549#if defined(PLAT_ppc64be_linux)
550
551typedef
552   struct {
553      unsigned long int nraddr; /* where's the code? */
554      unsigned long int r2;  /* what tocptr do we need? */
555   }
556   OrigFn;
557
558#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
559                     "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
560                     "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
561
562#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
563        _zzq_default, _zzq_request,                               \
564        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
565                                                                  \
566  __extension__                                                   \
567  ({         unsigned long int  _zzq_args[6];                     \
568             unsigned long int  _zzq_result;                      \
569             unsigned long int* _zzq_ptr;                         \
570    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
571    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
572    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
573    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
574    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
575    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
576    _zzq_ptr = _zzq_args;                                         \
577    __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
578                     "mr 4,%2\n\t" /*ptr*/                        \
579                     __SPECIAL_INSTRUCTION_PREAMBLE               \
580                     /* %R3 = client_request ( %R4 ) */           \
581                     "or 1,1,1\n\t"                               \
582                     "mr %0,3"     /*result*/                     \
583                     : "=b" (_zzq_result)                         \
584                     : "b" (_zzq_default), "b" (_zzq_ptr)         \
585                     : "cc", "memory", "r3", "r4");               \
586    _zzq_result;                                                  \
587  })
588
589#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
590  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
591    unsigned long int __addr;                                     \
592    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
593                     /* %R3 = guest_NRADDR */                     \
594                     "or 2,2,2\n\t"                               \
595                     "mr %0,3"                                    \
596                     : "=b" (__addr)                              \
597                     :                                            \
598                     : "cc", "memory", "r3"                       \
599                    );                                            \
600    _zzq_orig->nraddr = __addr;                                   \
601    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
602                     /* %R3 = guest_NRADDR_GPR2 */                \
603                     "or 4,4,4\n\t"                               \
604                     "mr %0,3"                                    \
605                     : "=b" (__addr)                              \
606                     :                                            \
607                     : "cc", "memory", "r3"                       \
608                    );                                            \
609    _zzq_orig->r2 = __addr;                                       \
610  }
611
612#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
613                     __SPECIAL_INSTRUCTION_PREAMBLE               \
614                     /* branch-and-link-to-noredir *%R11 */       \
615                     "or 3,3,3\n\t"
616
617#define VALGRIND_VEX_INJECT_IR()                                 \
618 do {                                                            \
619    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
620                     "or 5,5,5\n\t"                              \
621                    );                                           \
622 } while (0)
623
624#endif /* PLAT_ppc64be_linux */
625
626#if defined(PLAT_ppc64le_linux)
627
628typedef
629   struct {
630      unsigned long int nraddr; /* where's the code? */
631      unsigned long int r2;     /* what tocptr do we need? */
632   }
633   OrigFn;
634
635#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
636                     "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
637                     "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
638
639#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
640        _zzq_default, _zzq_request,                               \
641        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
642                                                                  \
643  __extension__                                                   \
644  ({         unsigned long int  _zzq_args[6];                     \
645             unsigned long int  _zzq_result;                      \
646             unsigned long int* _zzq_ptr;                         \
647    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
648    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
649    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
650    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
651    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
652    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
653    _zzq_ptr = _zzq_args;                                         \
654    __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
655                     "mr 4,%2\n\t" /*ptr*/                        \
656                     __SPECIAL_INSTRUCTION_PREAMBLE               \
657                     /* %R3 = client_request ( %R4 ) */           \
658                     "or 1,1,1\n\t"                               \
659                     "mr %0,3"     /*result*/                     \
660                     : "=b" (_zzq_result)                         \
661                     : "b" (_zzq_default), "b" (_zzq_ptr)         \
662                     : "cc", "memory", "r3", "r4");               \
663    _zzq_result;                                                  \
664  })
665
666#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
667  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
668    unsigned long int __addr;                                     \
669    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
670                     /* %R3 = guest_NRADDR */                     \
671                     "or 2,2,2\n\t"                               \
672                     "mr %0,3"                                    \
673                     : "=b" (__addr)                              \
674                     :                                            \
675                     : "cc", "memory", "r3"                       \
676                    );                                            \
677    _zzq_orig->nraddr = __addr;                                   \
678    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
679                     /* %R3 = guest_NRADDR_GPR2 */                \
680                     "or 4,4,4\n\t"                               \
681                     "mr %0,3"                                    \
682                     : "=b" (__addr)                              \
683                     :                                            \
684                     : "cc", "memory", "r3"                       \
685                    );                                            \
686    _zzq_orig->r2 = __addr;                                       \
687  }
688
689#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                   \
690                     __SPECIAL_INSTRUCTION_PREAMBLE               \
691                     /* branch-and-link-to-noredir *%R12 */       \
692                     "or 3,3,3\n\t"
693
694#define VALGRIND_VEX_INJECT_IR()                                 \
695 do {                                                            \
696    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
697                     "or 5,5,5\n\t"                              \
698                    );                                           \
699 } while (0)
700
701#endif /* PLAT_ppc64le_linux */
702
703/* ------------------------- arm-linux ------------------------- */
704
705#if defined(PLAT_arm_linux)
706
707typedef
708   struct {
709      unsigned int nraddr; /* where's the code? */
710   }
711   OrigFn;
712
713#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
714            "mov r12, r12, ror #3  ; mov r12, r12, ror #13 \n\t"  \
715            "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
716
717#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
718        _zzq_default, _zzq_request,                               \
719        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
720                                                                  \
721  __extension__                                                   \
722  ({volatile unsigned int  _zzq_args[6];                          \
723    volatile unsigned int  _zzq_result;                           \
724    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
725    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
726    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
727    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
728    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
729    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
730    __asm__ volatile("mov r3, %1\n\t" /*default*/                 \
731                     "mov r4, %2\n\t" /*ptr*/                     \
732                     __SPECIAL_INSTRUCTION_PREAMBLE               \
733                     /* R3 = client_request ( R4 ) */             \
734                     "orr r10, r10, r10\n\t"                      \
735                     "mov %0, r3"     /*result*/                  \
736                     : "=r" (_zzq_result)                         \
737                     : "r" (_zzq_default), "r" (&_zzq_args[0])    \
738                     : "cc","memory", "r3", "r4");                \
739    _zzq_result;                                                  \
740  })
741
742#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
743  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
744    unsigned int __addr;                                          \
745    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
746                     /* R3 = guest_NRADDR */                      \
747                     "orr r11, r11, r11\n\t"                      \
748                     "mov %0, r3"                                 \
749                     : "=r" (__addr)                              \
750                     :                                            \
751                     : "cc", "memory", "r3"                       \
752                    );                                            \
753    _zzq_orig->nraddr = __addr;                                   \
754  }
755
756#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                    \
757                     __SPECIAL_INSTRUCTION_PREAMBLE               \
758                     /* branch-and-link-to-noredir *%R4 */        \
759                     "orr r12, r12, r12\n\t"
760
761#define VALGRIND_VEX_INJECT_IR()                                 \
762 do {                                                            \
763    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
764                     "orr r9, r9, r9\n\t"                        \
765                     : : : "cc", "memory"                        \
766                    );                                           \
767 } while (0)
768
769#endif /* PLAT_arm_linux */
770
771/* ------------------------ arm64-linux ------------------------- */
772
773#if defined(PLAT_arm64_linux)
774
775typedef
776   struct {
777      unsigned long int nraddr; /* where's the code? */
778   }
779   OrigFn;
780
781#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
782            "ror x12, x12, #3  ;  ror x12, x12, #13 \n\t"         \
783            "ror x12, x12, #51 ;  ror x12, x12, #61 \n\t"
784
785#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
786        _zzq_default, _zzq_request,                               \
787        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
788                                                                  \
789  __extension__                                                   \
790  ({volatile unsigned long int  _zzq_args[6];                     \
791    volatile unsigned long int  _zzq_result;                      \
792    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
793    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
794    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
795    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
796    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
797    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
798    __asm__ volatile("mov x3, %1\n\t" /*default*/                 \
799                     "mov x4, %2\n\t" /*ptr*/                     \
800                     __SPECIAL_INSTRUCTION_PREAMBLE               \
801                     /* X3 = client_request ( X4 ) */             \
802                     "orr x10, x10, x10\n\t"                      \
803                     "mov %0, x3"     /*result*/                  \
804                     : "=r" (_zzq_result)                         \
805                     : "r" ((unsigned long int)(_zzq_default)),   \
806                       "r" (&_zzq_args[0])                        \
807                     : "cc","memory", "x3", "x4");                \
808    _zzq_result;                                                  \
809  })
810
811#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
812  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
813    unsigned long int __addr;                                     \
814    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
815                     /* X3 = guest_NRADDR */                      \
816                     "orr x11, x11, x11\n\t"                      \
817                     "mov %0, x3"                                 \
818                     : "=r" (__addr)                              \
819                     :                                            \
820                     : "cc", "memory", "x3"                       \
821                    );                                            \
822    _zzq_orig->nraddr = __addr;                                   \
823  }
824
825#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                    \
826                     __SPECIAL_INSTRUCTION_PREAMBLE               \
827                     /* branch-and-link-to-noredir X8 */          \
828                     "orr x12, x12, x12\n\t"
829
830#define VALGRIND_VEX_INJECT_IR()                                 \
831 do {                                                            \
832    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
833                     "orr x9, x9, x9\n\t"                        \
834                     : : : "cc", "memory"                        \
835                    );                                           \
836 } while (0)
837
838#endif /* PLAT_arm64_linux */
839
840/* ------------------------ s390x-linux ------------------------ */
841
842#if defined(PLAT_s390x_linux)
843
844typedef
845  struct {
846     unsigned long int nraddr; /* where's the code? */
847  }
848  OrigFn;
849
850/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
851 * code. This detection is implemented in platform specific toIR.c
852 * (e.g. VEX/priv/guest_s390_decoder.c).
853 */
854#define __SPECIAL_INSTRUCTION_PREAMBLE                           \
855                     "lr 15,15\n\t"                              \
856                     "lr 1,1\n\t"                                \
857                     "lr 2,2\n\t"                                \
858                     "lr 3,3\n\t"
859
860#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
861#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
862#define __CALL_NO_REDIR_CODE  "lr 4,4\n\t"
863#define __VEX_INJECT_IR_CODE  "lr 5,5\n\t"
864
865#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                         \
866       _zzq_default, _zzq_request,                               \
867       _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
868  __extension__                                                  \
869 ({volatile unsigned long int _zzq_args[6];                      \
870   volatile unsigned long int _zzq_result;                       \
871   _zzq_args[0] = (unsigned long int)(_zzq_request);             \
872   _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
873   _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
874   _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
875   _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
876   _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
877   __asm__ volatile(/* r2 = args */                              \
878                    "lgr 2,%1\n\t"                               \
879                    /* r3 = default */                           \
880                    "lgr 3,%2\n\t"                               \
881                    __SPECIAL_INSTRUCTION_PREAMBLE               \
882                    __CLIENT_REQUEST_CODE                        \
883                    /* results = r3 */                           \
884                    "lgr %0, 3\n\t"                              \
885                    : "=d" (_zzq_result)                         \
886                    : "a" (&_zzq_args[0]),                       \
887                      "0" ((unsigned long int)_zzq_default)      \
888                    : "cc", "2", "3", "memory"                   \
889                   );                                            \
890   _zzq_result;                                                  \
891 })
892
893#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                      \
894 { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
895   volatile unsigned long int __addr;                            \
896   __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
897                    __GET_NR_CONTEXT_CODE                        \
898                    "lgr %0, 3\n\t"                              \
899                    : "=a" (__addr)                              \
900                    :                                            \
901                    : "cc", "3", "memory"                        \
902                   );                                            \
903   _zzq_orig->nraddr = __addr;                                   \
904 }
905
906#define VALGRIND_CALL_NOREDIR_R1                                 \
907                    __SPECIAL_INSTRUCTION_PREAMBLE               \
908                    __CALL_NO_REDIR_CODE
909
910#define VALGRIND_VEX_INJECT_IR()                                 \
911 do {                                                            \
912    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
913                     __VEX_INJECT_IR_CODE);                      \
914 } while (0)
915
916#endif /* PLAT_s390x_linux */
917
918/* ------------------------- mips32-linux ---------------- */
919
920#if defined(PLAT_mips32_linux)
921
922typedef
923   struct {
924      unsigned int nraddr; /* where's the code? */
925   }
926   OrigFn;
927
928/* .word  0x342
929 * .word  0x742
930 * .word  0xC2
931 * .word  0x4C2*/
932#define __SPECIAL_INSTRUCTION_PREAMBLE          \
933                     "srl $0, $0, 13\n\t"       \
934                     "srl $0, $0, 29\n\t"       \
935                     "srl $0, $0, 3\n\t"        \
936                     "srl $0, $0, 19\n\t"
937
938#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
939       _zzq_default, _zzq_request,                                \
940       _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)     \
941  __extension__                                                   \
942  ({ volatile unsigned int _zzq_args[6];                          \
943    volatile unsigned int _zzq_result;                            \
944    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
945    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
946    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
947    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
948    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
949    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
950        __asm__ volatile("move $11, %1\n\t" /*default*/           \
951                     "move $12, %2\n\t" /*ptr*/                   \
952                     __SPECIAL_INSTRUCTION_PREAMBLE               \
953                     /* T3 = client_request ( T4 ) */             \
954                     "or $13, $13, $13\n\t"                       \
955                     "move %0, $11\n\t"     /*result*/            \
956                     : "=r" (_zzq_result)                         \
957                     : "r" (_zzq_default), "r" (&_zzq_args[0])    \
958                     : "$11", "$12", "memory");                   \
959    _zzq_result;                                                  \
960  })
961
962#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
963  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
964    volatile unsigned int __addr;                                 \
965    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
966                     /* %t9 = guest_NRADDR */                     \
967                     "or $14, $14, $14\n\t"                       \
968                     "move %0, $11"     /*result*/                \
969                     : "=r" (__addr)                              \
970                     :                                            \
971                     : "$11"                                      \
972                    );                                            \
973    _zzq_orig->nraddr = __addr;                                   \
974  }
975
976#define VALGRIND_CALL_NOREDIR_T9                                 \
977                     __SPECIAL_INSTRUCTION_PREAMBLE              \
978                     /* call-noredir *%t9 */                     \
979                     "or $15, $15, $15\n\t"
980
981#define VALGRIND_VEX_INJECT_IR()                                 \
982 do {                                                            \
983    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
984                     "or $11, $11, $11\n\t"                      \
985                    );                                           \
986 } while (0)
987
988
989#endif /* PLAT_mips32_linux */
990
991/* ------------------------- mips64-linux ---------------- */
992
993#if defined(PLAT_mips64_linux)
994
995typedef
996   struct {
997      unsigned long nraddr; /* where's the code? */
998   }
999   OrigFn;
1000
1001/* dsll $0,$0, 3
1002 * dsll $0,$0, 13
1003 * dsll $0,$0, 29
1004 * dsll $0,$0, 19*/
1005#define __SPECIAL_INSTRUCTION_PREAMBLE                              \
1006                     "dsll $0,$0, 3 ; dsll $0,$0,13\n\t"            \
1007                     "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
1008
1009#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                            \
1010       _zzq_default, _zzq_request,                                  \
1011       _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)       \
1012  __extension__                                                     \
1013  ({ volatile unsigned long int _zzq_args[6];                       \
1014    volatile unsigned long int _zzq_result;                         \
1015    _zzq_args[0] = (unsigned long int)(_zzq_request);               \
1016    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                  \
1017    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                  \
1018    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                  \
1019    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                  \
1020    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                  \
1021        __asm__ volatile("move $11, %1\n\t" /*default*/             \
1022                         "move $12, %2\n\t" /*ptr*/                 \
1023                         __SPECIAL_INSTRUCTION_PREAMBLE             \
1024                         /* $11 = client_request ( $12 ) */         \
1025                         "or $13, $13, $13\n\t"                     \
1026                         "move %0, $11\n\t"     /*result*/          \
1027                         : "=r" (_zzq_result)                       \
1028                         : "r" (_zzq_default), "r" (&_zzq_args[0])  \
1029                         : "$11", "$12", "memory");                 \
1030    _zzq_result;                                                    \
1031  })
1032
1033#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                         \
1034  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                     \
1035    volatile unsigned long int __addr;                              \
1036    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
1037                     /* $11 = guest_NRADDR */                       \
1038                     "or $14, $14, $14\n\t"                         \
1039                     "move %0, $11"     /*result*/                  \
1040                     : "=r" (__addr)                                \
1041                     :                                              \
1042                     : "$11");                                      \
1043    _zzq_orig->nraddr = __addr;                                     \
1044  }
1045
1046#define VALGRIND_CALL_NOREDIR_T9                                    \
1047                     __SPECIAL_INSTRUCTION_PREAMBLE                 \
1048                     /* call-noredir $25 */                         \
1049                     "or $15, $15, $15\n\t"
1050
1051#define VALGRIND_VEX_INJECT_IR()                                    \
1052 do {                                                               \
1053    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
1054                     "or $11, $11, $11\n\t"                         \
1055                    );                                              \
1056 } while (0)
1057
1058#endif /* PLAT_mips64_linux */
1059
1060#if defined(PLAT_nanomips_linux)
1061
1062typedef
1063   struct {
1064      unsigned int nraddr; /* where's the code? */
1065   }
1066   OrigFn;
1067/*
1068   8000 c04d  srl  zero, zero, 13
1069   8000 c05d  srl  zero, zero, 29
1070   8000 c043  srl  zero, zero,  3
1071   8000 c053  srl  zero, zero, 19
1072*/
1073
1074#define __SPECIAL_INSTRUCTION_PREAMBLE "srl[32] $zero, $zero, 13 \n\t" \
1075                                       "srl[32] $zero, $zero, 29 \n\t" \
1076                                       "srl[32] $zero, $zero, 3  \n\t" \
1077                                       "srl[32] $zero, $zero, 19 \n\t"
1078
1079#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
1080       _zzq_default, _zzq_request,                                \
1081       _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)     \
1082  __extension__                                                   \
1083  ({ volatile unsigned int _zzq_args[6];                          \
1084    volatile unsigned int _zzq_result;                            \
1085    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
1086    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
1087    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
1088    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
1089    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
1090    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
1091    __asm__ volatile("move $a7, %1\n\t" /* default */             \
1092                     "move $t0, %2\n\t" /* ptr */                 \
1093                     __SPECIAL_INSTRUCTION_PREAMBLE               \
1094                     /* $a7 = client_request( $t0 ) */            \
1095                     "or[32] $t0, $t0, $t0\n\t"                   \
1096                     "move %0, $a7\n\t"     /* result */          \
1097                     : "=r" (_zzq_result)                         \
1098                     : "r" (_zzq_default), "r" (&_zzq_args[0])    \
1099                     : "$a7", "$t0", "memory");                   \
1100    _zzq_result;                                                  \
1101  })
1102
1103#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                         \
1104  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                     \
1105    volatile unsigned long int __addr;                              \
1106    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
1107                     /* $a7 = guest_NRADDR */                       \
1108                     "or[32] $t1, $t1, $t1\n\t"                     \
1109                     "move %0, $a7"     /*result*/                  \
1110                     : "=r" (__addr)                                \
1111                     :                                              \
1112                     : "$a7");                                      \
1113    _zzq_orig->nraddr = __addr;                                     \
1114  }
1115
1116#define VALGRIND_CALL_NOREDIR_T9                                    \
1117                     __SPECIAL_INSTRUCTION_PREAMBLE                 \
1118                     /* call-noredir $25 */                         \
1119                     "or[32] $t2, $t2, $t2\n\t"
1120
1121#define VALGRIND_VEX_INJECT_IR()                                    \
1122 do {                                                               \
1123    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
1124                     "or[32] $t3, $t3, $t3\n\t"                     \
1125                    );                                              \
1126 } while (0)
1127
1128#endif
1129/* Insert assembly code for other platforms here... */
1130
1131#endif /* NVALGRIND */
1132
1133
1134/* ------------------------------------------------------------------ */
1135/* PLATFORM SPECIFICS for FUNCTION WRAPPING.  This is all very        */
1136/* ugly.  It's the least-worst tradeoff I can think of.               */
1137/* ------------------------------------------------------------------ */
1138
1139/* This section defines magic (a.k.a appalling-hack) macros for doing
1140   guaranteed-no-redirection macros, so as to get from function
1141   wrappers to the functions they are wrapping.  The whole point is to
1142   construct standard call sequences, but to do the call itself with a
1143   special no-redirect call pseudo-instruction that the JIT
1144   understands and handles specially.  This section is long and
1145   repetitious, and I can't see a way to make it shorter.
1146
1147   The naming scheme is as follows:
1148
1149      CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
1150
1151   'W' stands for "word" and 'v' for "void".  Hence there are
1152   different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
1153   and for each, the possibility of returning a word-typed result, or
1154   no result.
1155*/
1156
1157/* Use these to write the name of your wrapper.  NOTE: duplicates
1158   VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h.  NOTE also: inserts
1159   the default behaviour equivalance class tag "0000" into the name.
1160   See pub_tool_redir.h for details -- normally you don't need to
1161   think about this, though. */
1162
1163/* Use an extra level of macroisation so as to ensure the soname/fnname
1164   args are fully macro-expanded before pasting them together. */
1165#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
1166
1167#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname)                    \
1168   VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
1169
1170#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname)                    \
1171   VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
1172
1173/* Use this macro from within a wrapper function to collect the
1174   context (address and possibly other info) of the original function.
1175   Once you have that you can then use it in one of the CALL_FN_
1176   macros.  The type of the argument _lval is OrigFn. */
1177#define VALGRIND_GET_ORIG_FN(_lval)  VALGRIND_GET_NR_CONTEXT(_lval)
1178
1179/* Also provide end-user facilities for function replacement, rather
1180   than wrapping.  A replacement function differs from a wrapper in
1181   that it has no way to get hold of the original function being
1182   called, and hence no way to call onwards to it.  In a replacement
1183   function, VALGRIND_GET_ORIG_FN always returns zero. */
1184
1185#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname)                 \
1186   VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1187
1188#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname)                 \
1189   VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1190
1191/* Derivatives of the main macros below, for calling functions
1192   returning void. */
1193
1194#define CALL_FN_v_v(fnptr)                                        \
1195   do { volatile unsigned long _junk;                             \
1196        CALL_FN_W_v(_junk,fnptr); } while (0)
1197
1198#define CALL_FN_v_W(fnptr, arg1)                                  \
1199   do { volatile unsigned long _junk;                             \
1200        CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1201
1202#define CALL_FN_v_WW(fnptr, arg1,arg2)                            \
1203   do { volatile unsigned long _junk;                             \
1204        CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1205
1206#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3)                      \
1207   do { volatile unsigned long _junk;                             \
1208        CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1209
1210#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4)                \
1211   do { volatile unsigned long _junk;                             \
1212        CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1213
1214#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5)             \
1215   do { volatile unsigned long _junk;                             \
1216        CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1217
1218#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6)        \
1219   do { volatile unsigned long _junk;                             \
1220        CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1221
1222#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7)   \
1223   do { volatile unsigned long _junk;                             \
1224        CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1225
1226/* ----------------- x86-{linux,darwin,solaris} ---------------- */
1227
1228#if defined(PLAT_x86_linux)  ||  defined(PLAT_x86_darwin) \
1229    ||  defined(PLAT_x86_solaris)  || defined(PLAT_x86_freebsd)
1230
1231/* These regs are trashed by the hidden call.  No need to mention eax
1232   as gcc can already see that, plus causes gcc to bomb. */
1233#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1234
1235/* Macros to save and align the stack before making a function
1236   call and restore it afterwards as gcc may not keep the stack
1237   pointer aligned if it doesn't realise calls are being made
1238   to other functions. */
1239
1240#define VALGRIND_ALIGN_STACK               \
1241      "movl %%esp,%%edi\n\t"               \
1242      "andl $0xfffffff0,%%esp\n\t"
1243#define VALGRIND_RESTORE_STACK             \
1244      "movl %%edi,%%esp\n\t"
1245
1246/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1247   long) == 4. */
1248
1249#define CALL_FN_W_v(lval, orig)                                   \
1250   do {                                                           \
1251      volatile OrigFn        _orig = (orig);                      \
1252      volatile unsigned long _argvec[1];                          \
1253      volatile unsigned long _res;                                \
1254      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1255      __asm__ volatile(                                           \
1256         VALGRIND_ALIGN_STACK                                     \
1257         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1258         VALGRIND_CALL_NOREDIR_EAX                                \
1259         VALGRIND_RESTORE_STACK                                   \
1260         : /*out*/   "=a" (_res)                                  \
1261         : /*in*/    "a" (&_argvec[0])                            \
1262         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1263      );                                                          \
1264      lval = (__typeof__(lval)) _res;                             \
1265   } while (0)
1266
1267#define CALL_FN_W_W(lval, orig, arg1)                             \
1268   do {                                                           \
1269      volatile OrigFn        _orig = (orig);                      \
1270      volatile unsigned long _argvec[2];                          \
1271      volatile unsigned long _res;                                \
1272      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1273      _argvec[1] = (unsigned long)(arg1);                         \
1274      __asm__ volatile(                                           \
1275         VALGRIND_ALIGN_STACK                                     \
1276         "subl $12, %%esp\n\t"                                    \
1277         "pushl 4(%%eax)\n\t"                                     \
1278         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1279         VALGRIND_CALL_NOREDIR_EAX                                \
1280         VALGRIND_RESTORE_STACK                                   \
1281         : /*out*/   "=a" (_res)                                  \
1282         : /*in*/    "a" (&_argvec[0])                            \
1283         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1284      );                                                          \
1285      lval = (__typeof__(lval)) _res;                             \
1286   } while (0)
1287
1288#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
1289   do {                                                           \
1290      volatile OrigFn        _orig = (orig);                      \
1291      volatile unsigned long _argvec[3];                          \
1292      volatile unsigned long _res;                                \
1293      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1294      _argvec[1] = (unsigned long)(arg1);                         \
1295      _argvec[2] = (unsigned long)(arg2);                         \
1296      __asm__ volatile(                                           \
1297         VALGRIND_ALIGN_STACK                                     \
1298         "subl $8, %%esp\n\t"                                     \
1299         "pushl 8(%%eax)\n\t"                                     \
1300         "pushl 4(%%eax)\n\t"                                     \
1301         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1302         VALGRIND_CALL_NOREDIR_EAX                                \
1303         VALGRIND_RESTORE_STACK                                   \
1304         : /*out*/   "=a" (_res)                                  \
1305         : /*in*/    "a" (&_argvec[0])                            \
1306         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1307      );                                                          \
1308      lval = (__typeof__(lval)) _res;                             \
1309   } while (0)
1310
1311#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
1312   do {                                                           \
1313      volatile OrigFn        _orig = (orig);                      \
1314      volatile unsigned long _argvec[4];                          \
1315      volatile unsigned long _res;                                \
1316      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1317      _argvec[1] = (unsigned long)(arg1);                         \
1318      _argvec[2] = (unsigned long)(arg2);                         \
1319      _argvec[3] = (unsigned long)(arg3);                         \
1320      __asm__ volatile(                                           \
1321         VALGRIND_ALIGN_STACK                                     \
1322         "subl $4, %%esp\n\t"                                     \
1323         "pushl 12(%%eax)\n\t"                                    \
1324         "pushl 8(%%eax)\n\t"                                     \
1325         "pushl 4(%%eax)\n\t"                                     \
1326         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1327         VALGRIND_CALL_NOREDIR_EAX                                \
1328         VALGRIND_RESTORE_STACK                                   \
1329         : /*out*/   "=a" (_res)                                  \
1330         : /*in*/    "a" (&_argvec[0])                            \
1331         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1332      );                                                          \
1333      lval = (__typeof__(lval)) _res;                             \
1334   } while (0)
1335
1336#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
1337   do {                                                           \
1338      volatile OrigFn        _orig = (orig);                      \
1339      volatile unsigned long _argvec[5];                          \
1340      volatile unsigned long _res;                                \
1341      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1342      _argvec[1] = (unsigned long)(arg1);                         \
1343      _argvec[2] = (unsigned long)(arg2);                         \
1344      _argvec[3] = (unsigned long)(arg3);                         \
1345      _argvec[4] = (unsigned long)(arg4);                         \
1346      __asm__ volatile(                                           \
1347         VALGRIND_ALIGN_STACK                                     \
1348         "pushl 16(%%eax)\n\t"                                    \
1349         "pushl 12(%%eax)\n\t"                                    \
1350         "pushl 8(%%eax)\n\t"                                     \
1351         "pushl 4(%%eax)\n\t"                                     \
1352         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1353         VALGRIND_CALL_NOREDIR_EAX                                \
1354         VALGRIND_RESTORE_STACK                                   \
1355         : /*out*/   "=a" (_res)                                  \
1356         : /*in*/    "a" (&_argvec[0])                            \
1357         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1358      );                                                          \
1359      lval = (__typeof__(lval)) _res;                             \
1360   } while (0)
1361
1362#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
1363   do {                                                           \
1364      volatile OrigFn        _orig = (orig);                      \
1365      volatile unsigned long _argvec[6];                          \
1366      volatile unsigned long _res;                                \
1367      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1368      _argvec[1] = (unsigned long)(arg1);                         \
1369      _argvec[2] = (unsigned long)(arg2);                         \
1370      _argvec[3] = (unsigned long)(arg3);                         \
1371      _argvec[4] = (unsigned long)(arg4);                         \
1372      _argvec[5] = (unsigned long)(arg5);                         \
1373      __asm__ volatile(                                           \
1374         VALGRIND_ALIGN_STACK                                     \
1375         "subl $12, %%esp\n\t"                                    \
1376         "pushl 20(%%eax)\n\t"                                    \
1377         "pushl 16(%%eax)\n\t"                                    \
1378         "pushl 12(%%eax)\n\t"                                    \
1379         "pushl 8(%%eax)\n\t"                                     \
1380         "pushl 4(%%eax)\n\t"                                     \
1381         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1382         VALGRIND_CALL_NOREDIR_EAX                                \
1383         VALGRIND_RESTORE_STACK                                   \
1384         : /*out*/   "=a" (_res)                                  \
1385         : /*in*/    "a" (&_argvec[0])                            \
1386         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1387      );                                                          \
1388      lval = (__typeof__(lval)) _res;                             \
1389   } while (0)
1390
1391#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
1392   do {                                                           \
1393      volatile OrigFn        _orig = (orig);                      \
1394      volatile unsigned long _argvec[7];                          \
1395      volatile unsigned long _res;                                \
1396      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1397      _argvec[1] = (unsigned long)(arg1);                         \
1398      _argvec[2] = (unsigned long)(arg2);                         \
1399      _argvec[3] = (unsigned long)(arg3);                         \
1400      _argvec[4] = (unsigned long)(arg4);                         \
1401      _argvec[5] = (unsigned long)(arg5);                         \
1402      _argvec[6] = (unsigned long)(arg6);                         \
1403      __asm__ volatile(                                           \
1404         VALGRIND_ALIGN_STACK                                     \
1405         "subl $8, %%esp\n\t"                                     \
1406         "pushl 24(%%eax)\n\t"                                    \
1407         "pushl 20(%%eax)\n\t"                                    \
1408         "pushl 16(%%eax)\n\t"                                    \
1409         "pushl 12(%%eax)\n\t"                                    \
1410         "pushl 8(%%eax)\n\t"                                     \
1411         "pushl 4(%%eax)\n\t"                                     \
1412         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1413         VALGRIND_CALL_NOREDIR_EAX                                \
1414         VALGRIND_RESTORE_STACK                                   \
1415         : /*out*/   "=a" (_res)                                  \
1416         : /*in*/    "a" (&_argvec[0])                            \
1417         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1418      );                                                          \
1419      lval = (__typeof__(lval)) _res;                             \
1420   } while (0)
1421
1422#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1423                                 arg7)                            \
1424   do {                                                           \
1425      volatile OrigFn        _orig = (orig);                      \
1426      volatile unsigned long _argvec[8];                          \
1427      volatile unsigned long _res;                                \
1428      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1429      _argvec[1] = (unsigned long)(arg1);                         \
1430      _argvec[2] = (unsigned long)(arg2);                         \
1431      _argvec[3] = (unsigned long)(arg3);                         \
1432      _argvec[4] = (unsigned long)(arg4);                         \
1433      _argvec[5] = (unsigned long)(arg5);                         \
1434      _argvec[6] = (unsigned long)(arg6);                         \
1435      _argvec[7] = (unsigned long)(arg7);                         \
1436      __asm__ volatile(                                           \
1437         VALGRIND_ALIGN_STACK                                     \
1438         "subl $4, %%esp\n\t"                                     \
1439         "pushl 28(%%eax)\n\t"                                    \
1440         "pushl 24(%%eax)\n\t"                                    \
1441         "pushl 20(%%eax)\n\t"                                    \
1442         "pushl 16(%%eax)\n\t"                                    \
1443         "pushl 12(%%eax)\n\t"                                    \
1444         "pushl 8(%%eax)\n\t"                                     \
1445         "pushl 4(%%eax)\n\t"                                     \
1446         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1447         VALGRIND_CALL_NOREDIR_EAX                                \
1448         VALGRIND_RESTORE_STACK                                   \
1449         : /*out*/   "=a" (_res)                                  \
1450         : /*in*/    "a" (&_argvec[0])                            \
1451         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1452      );                                                          \
1453      lval = (__typeof__(lval)) _res;                             \
1454   } while (0)
1455
1456#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1457                                 arg7,arg8)                       \
1458   do {                                                           \
1459      volatile OrigFn        _orig = (orig);                      \
1460      volatile unsigned long _argvec[9];                          \
1461      volatile unsigned long _res;                                \
1462      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1463      _argvec[1] = (unsigned long)(arg1);                         \
1464      _argvec[2] = (unsigned long)(arg2);                         \
1465      _argvec[3] = (unsigned long)(arg3);                         \
1466      _argvec[4] = (unsigned long)(arg4);                         \
1467      _argvec[5] = (unsigned long)(arg5);                         \
1468      _argvec[6] = (unsigned long)(arg6);                         \
1469      _argvec[7] = (unsigned long)(arg7);                         \
1470      _argvec[8] = (unsigned long)(arg8);                         \
1471      __asm__ volatile(                                           \
1472         VALGRIND_ALIGN_STACK                                     \
1473         "pushl 32(%%eax)\n\t"                                    \
1474         "pushl 28(%%eax)\n\t"                                    \
1475         "pushl 24(%%eax)\n\t"                                    \
1476         "pushl 20(%%eax)\n\t"                                    \
1477         "pushl 16(%%eax)\n\t"                                    \
1478         "pushl 12(%%eax)\n\t"                                    \
1479         "pushl 8(%%eax)\n\t"                                     \
1480         "pushl 4(%%eax)\n\t"                                     \
1481         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1482         VALGRIND_CALL_NOREDIR_EAX                                \
1483         VALGRIND_RESTORE_STACK                                   \
1484         : /*out*/   "=a" (_res)                                  \
1485         : /*in*/    "a" (&_argvec[0])                            \
1486         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1487      );                                                          \
1488      lval = (__typeof__(lval)) _res;                             \
1489   } while (0)
1490
1491#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1492                                 arg7,arg8,arg9)                  \
1493   do {                                                           \
1494      volatile OrigFn        _orig = (orig);                      \
1495      volatile unsigned long _argvec[10];                         \
1496      volatile unsigned long _res;                                \
1497      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1498      _argvec[1] = (unsigned long)(arg1);                         \
1499      _argvec[2] = (unsigned long)(arg2);                         \
1500      _argvec[3] = (unsigned long)(arg3);                         \
1501      _argvec[4] = (unsigned long)(arg4);                         \
1502      _argvec[5] = (unsigned long)(arg5);                         \
1503      _argvec[6] = (unsigned long)(arg6);                         \
1504      _argvec[7] = (unsigned long)(arg7);                         \
1505      _argvec[8] = (unsigned long)(arg8);                         \
1506      _argvec[9] = (unsigned long)(arg9);                         \
1507      __asm__ volatile(                                           \
1508         VALGRIND_ALIGN_STACK                                     \
1509         "subl $12, %%esp\n\t"                                    \
1510         "pushl 36(%%eax)\n\t"                                    \
1511         "pushl 32(%%eax)\n\t"                                    \
1512         "pushl 28(%%eax)\n\t"                                    \
1513         "pushl 24(%%eax)\n\t"                                    \
1514         "pushl 20(%%eax)\n\t"                                    \
1515         "pushl 16(%%eax)\n\t"                                    \
1516         "pushl 12(%%eax)\n\t"                                    \
1517         "pushl 8(%%eax)\n\t"                                     \
1518         "pushl 4(%%eax)\n\t"                                     \
1519         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1520         VALGRIND_CALL_NOREDIR_EAX                                \
1521         VALGRIND_RESTORE_STACK                                   \
1522         : /*out*/   "=a" (_res)                                  \
1523         : /*in*/    "a" (&_argvec[0])                            \
1524         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1525      );                                                          \
1526      lval = (__typeof__(lval)) _res;                             \
1527   } while (0)
1528
1529#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1530                                  arg7,arg8,arg9,arg10)           \
1531   do {                                                           \
1532      volatile OrigFn        _orig = (orig);                      \
1533      volatile unsigned long _argvec[11];                         \
1534      volatile unsigned long _res;                                \
1535      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1536      _argvec[1] = (unsigned long)(arg1);                         \
1537      _argvec[2] = (unsigned long)(arg2);                         \
1538      _argvec[3] = (unsigned long)(arg3);                         \
1539      _argvec[4] = (unsigned long)(arg4);                         \
1540      _argvec[5] = (unsigned long)(arg5);                         \
1541      _argvec[6] = (unsigned long)(arg6);                         \
1542      _argvec[7] = (unsigned long)(arg7);                         \
1543      _argvec[8] = (unsigned long)(arg8);                         \
1544      _argvec[9] = (unsigned long)(arg9);                         \
1545      _argvec[10] = (unsigned long)(arg10);                       \
1546      __asm__ volatile(                                           \
1547         VALGRIND_ALIGN_STACK                                     \
1548         "subl $8, %%esp\n\t"                                     \
1549         "pushl 40(%%eax)\n\t"                                    \
1550         "pushl 36(%%eax)\n\t"                                    \
1551         "pushl 32(%%eax)\n\t"                                    \
1552         "pushl 28(%%eax)\n\t"                                    \
1553         "pushl 24(%%eax)\n\t"                                    \
1554         "pushl 20(%%eax)\n\t"                                    \
1555         "pushl 16(%%eax)\n\t"                                    \
1556         "pushl 12(%%eax)\n\t"                                    \
1557         "pushl 8(%%eax)\n\t"                                     \
1558         "pushl 4(%%eax)\n\t"                                     \
1559         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1560         VALGRIND_CALL_NOREDIR_EAX                                \
1561         VALGRIND_RESTORE_STACK                                   \
1562         : /*out*/   "=a" (_res)                                  \
1563         : /*in*/    "a" (&_argvec[0])                            \
1564         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1565      );                                                          \
1566      lval = (__typeof__(lval)) _res;                             \
1567   } while (0)
1568
1569#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
1570                                  arg6,arg7,arg8,arg9,arg10,      \
1571                                  arg11)                          \
1572   do {                                                           \
1573      volatile OrigFn        _orig = (orig);                      \
1574      volatile unsigned long _argvec[12];                         \
1575      volatile unsigned long _res;                                \
1576      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1577      _argvec[1] = (unsigned long)(arg1);                         \
1578      _argvec[2] = (unsigned long)(arg2);                         \
1579      _argvec[3] = (unsigned long)(arg3);                         \
1580      _argvec[4] = (unsigned long)(arg4);                         \
1581      _argvec[5] = (unsigned long)(arg5);                         \
1582      _argvec[6] = (unsigned long)(arg6);                         \
1583      _argvec[7] = (unsigned long)(arg7);                         \
1584      _argvec[8] = (unsigned long)(arg8);                         \
1585      _argvec[9] = (unsigned long)(arg9);                         \
1586      _argvec[10] = (unsigned long)(arg10);                       \
1587      _argvec[11] = (unsigned long)(arg11);                       \
1588      __asm__ volatile(                                           \
1589         VALGRIND_ALIGN_STACK                                     \
1590         "subl $4, %%esp\n\t"                                     \
1591         "pushl 44(%%eax)\n\t"                                    \
1592         "pushl 40(%%eax)\n\t"                                    \
1593         "pushl 36(%%eax)\n\t"                                    \
1594         "pushl 32(%%eax)\n\t"                                    \
1595         "pushl 28(%%eax)\n\t"                                    \
1596         "pushl 24(%%eax)\n\t"                                    \
1597         "pushl 20(%%eax)\n\t"                                    \
1598         "pushl 16(%%eax)\n\t"                                    \
1599         "pushl 12(%%eax)\n\t"                                    \
1600         "pushl 8(%%eax)\n\t"                                     \
1601         "pushl 4(%%eax)\n\t"                                     \
1602         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1603         VALGRIND_CALL_NOREDIR_EAX                                \
1604         VALGRIND_RESTORE_STACK                                   \
1605         : /*out*/   "=a" (_res)                                  \
1606         : /*in*/    "a" (&_argvec[0])                            \
1607         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1608      );                                                          \
1609      lval = (__typeof__(lval)) _res;                             \
1610   } while (0)
1611
1612#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
1613                                  arg6,arg7,arg8,arg9,arg10,      \
1614                                  arg11,arg12)                    \
1615   do {                                                           \
1616      volatile OrigFn        _orig = (orig);                      \
1617      volatile unsigned long _argvec[13];                         \
1618      volatile unsigned long _res;                                \
1619      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1620      _argvec[1] = (unsigned long)(arg1);                         \
1621      _argvec[2] = (unsigned long)(arg2);                         \
1622      _argvec[3] = (unsigned long)(arg3);                         \
1623      _argvec[4] = (unsigned long)(arg4);                         \
1624      _argvec[5] = (unsigned long)(arg5);                         \
1625      _argvec[6] = (unsigned long)(arg6);                         \
1626      _argvec[7] = (unsigned long)(arg7);                         \
1627      _argvec[8] = (unsigned long)(arg8);                         \
1628      _argvec[9] = (unsigned long)(arg9);                         \
1629      _argvec[10] = (unsigned long)(arg10);                       \
1630      _argvec[11] = (unsigned long)(arg11);                       \
1631      _argvec[12] = (unsigned long)(arg12);                       \
1632      __asm__ volatile(                                           \
1633         VALGRIND_ALIGN_STACK                                     \
1634         "pushl 48(%%eax)\n\t"                                    \
1635         "pushl 44(%%eax)\n\t"                                    \
1636         "pushl 40(%%eax)\n\t"                                    \
1637         "pushl 36(%%eax)\n\t"                                    \
1638         "pushl 32(%%eax)\n\t"                                    \
1639         "pushl 28(%%eax)\n\t"                                    \
1640         "pushl 24(%%eax)\n\t"                                    \
1641         "pushl 20(%%eax)\n\t"                                    \
1642         "pushl 16(%%eax)\n\t"                                    \
1643         "pushl 12(%%eax)\n\t"                                    \
1644         "pushl 8(%%eax)\n\t"                                     \
1645         "pushl 4(%%eax)\n\t"                                     \
1646         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1647         VALGRIND_CALL_NOREDIR_EAX                                \
1648         VALGRIND_RESTORE_STACK                                   \
1649         : /*out*/   "=a" (_res)                                  \
1650         : /*in*/    "a" (&_argvec[0])                            \
1651         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1652      );                                                          \
1653      lval = (__typeof__(lval)) _res;                             \
1654   } while (0)
1655
1656#endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_solaris */
1657
1658/* ---------------- amd64-{linux,darwin,solaris} --------------- */
1659
1660#if defined(PLAT_amd64_linux)  ||  defined(PLAT_amd64_darwin) \
1661    ||  defined(PLAT_amd64_solaris)  ||  defined(PLAT_amd64_freebsd)
1662
1663/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1664
1665/* These regs are trashed by the hidden call. */
1666#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi",       \
1667                            "rdi", "r8", "r9", "r10", "r11"
1668
1669/* This is all pretty complex.  It's so as to make stack unwinding
1670   work reliably.  See bug 243270.  The basic problem is the sub and
1671   add of 128 of %rsp in all of the following macros.  If gcc believes
1672   the CFA is in %rsp, then unwinding may fail, because what's at the
1673   CFA is not what gcc "expected" when it constructs the CFIs for the
1674   places where the macros are instantiated.
1675
1676   But we can't just add a CFI annotation to increase the CFA offset
1677   by 128, to match the sub of 128 from %rsp, because we don't know
1678   whether gcc has chosen %rsp as the CFA at that point, or whether it
1679   has chosen some other register (eg, %rbp).  In the latter case,
1680   adding a CFI annotation to change the CFA offset is simply wrong.
1681
1682   So the solution is to get hold of the CFA using
1683   __builtin_dwarf_cfa(), put it in a known register, and add a
1684   CFI annotation to say what the register is.  We choose %rbp for
1685   this (perhaps perversely), because:
1686
1687   (1) %rbp is already subject to unwinding.  If a new register was
1688       chosen then the unwinder would have to unwind it in all stack
1689       traces, which is expensive, and
1690
1691   (2) %rbp is already subject to precise exception updates in the
1692       JIT.  If a new register was chosen, we'd have to have precise
1693       exceptions for it too, which reduces performance of the
1694       generated code.
1695
1696   However .. one extra complication.  We can't just whack the result
1697   of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
1698   list of trashed registers at the end of the inline assembly
1699   fragments; gcc won't allow %rbp to appear in that list.  Hence
1700   instead we need to stash %rbp in %r15 for the duration of the asm,
1701   and say that %r15 is trashed instead.  gcc seems happy to go with
1702   that.
1703
1704   Oh .. and this all needs to be conditionalised so that it is
1705   unchanged from before this commit, when compiled with older gccs
1706   that don't support __builtin_dwarf_cfa.  Furthermore, since
1707   this header file is freestanding, it has to be independent of
1708   config.h, and so the following conditionalisation cannot depend on
1709   configure time checks.
1710
1711   Although it's not clear from
1712   'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1713   this expression excludes Darwin.
1714   .cfi directives in Darwin assembly appear to be completely
1715   different and I haven't investigated how they work.
1716
1717   For even more entertainment value, note we have to use the
1718   completely undocumented __builtin_dwarf_cfa(), which appears to
1719   really compute the CFA, whereas __builtin_frame_address(0) claims
1720   to but actually doesn't.  See
1721   https://bugs.kde.org/show_bug.cgi?id=243270#c47
1722*/
1723#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
1724#  define __FRAME_POINTER                                         \
1725      ,"r"(__builtin_dwarf_cfa())
1726#  define VALGRIND_CFI_PROLOGUE                                   \
1727      "movq %%rbp, %%r15\n\t"                                     \
1728      "movq %2, %%rbp\n\t"                                        \
1729      ".cfi_remember_state\n\t"                                   \
1730      ".cfi_def_cfa rbp, 0\n\t"
1731#  define VALGRIND_CFI_EPILOGUE                                   \
1732      "movq %%r15, %%rbp\n\t"                                     \
1733      ".cfi_restore_state\n\t"
1734#else
1735#  define __FRAME_POINTER
1736#  define VALGRIND_CFI_PROLOGUE
1737#  define VALGRIND_CFI_EPILOGUE
1738#endif
1739
1740/* Macros to save and align the stack before making a function
1741   call and restore it afterwards as gcc may not keep the stack
1742   pointer aligned if it doesn't realise calls are being made
1743   to other functions. */
1744
1745#define VALGRIND_ALIGN_STACK               \
1746      "movq %%rsp,%%r14\n\t"               \
1747      "andq $0xfffffffffffffff0,%%rsp\n\t"
1748#define VALGRIND_RESTORE_STACK             \
1749      "movq %%r14,%%rsp\n\t"
1750
1751/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1752   long) == 8. */
1753
1754/* NB 9 Sept 07.  There is a nasty kludge here in all these CALL_FN_
1755   macros.  In order not to trash the stack redzone, we need to drop
1756   %rsp by 128 before the hidden call, and restore afterwards.  The
1757   nastyness is that it is only by luck that the stack still appears
1758   to be unwindable during the hidden call - since then the behaviour
1759   of any routine using this macro does not match what the CFI data
1760   says.  Sigh.
1761
1762   Why is this important?  Imagine that a wrapper has a stack
1763   allocated local, and passes to the hidden call, a pointer to it.
1764   Because gcc does not know about the hidden call, it may allocate
1765   that local in the redzone.  Unfortunately the hidden call may then
1766   trash it before it comes to use it.  So we must step clear of the
1767   redzone, for the duration of the hidden call, to make it safe.
1768
1769   Probably the same problem afflicts the other redzone-style ABIs too
1770   (ppc64-linux); but for those, the stack is
1771   self describing (none of this CFI nonsense) so at least messing
1772   with the stack pointer doesn't give a danger of non-unwindable
1773   stack. */
1774
1775#define CALL_FN_W_v(lval, orig)                                        \
1776   do {                                                                \
1777      volatile OrigFn        _orig = (orig);                           \
1778      volatile unsigned long _argvec[1];                               \
1779      volatile unsigned long _res;                                     \
1780      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1781      __asm__ volatile(                                                \
1782         VALGRIND_CFI_PROLOGUE                                         \
1783         VALGRIND_ALIGN_STACK                                          \
1784         "subq $128,%%rsp\n\t"                                         \
1785         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1786         VALGRIND_CALL_NOREDIR_RAX                                     \
1787         VALGRIND_RESTORE_STACK                                        \
1788         VALGRIND_CFI_EPILOGUE                                         \
1789         : /*out*/   "=a" (_res)                                       \
1790         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1791         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1792      );                                                               \
1793      lval = (__typeof__(lval)) _res;                                  \
1794   } while (0)
1795
1796#define CALL_FN_W_W(lval, orig, arg1)                                  \
1797   do {                                                                \
1798      volatile OrigFn        _orig = (orig);                           \
1799      volatile unsigned long _argvec[2];                               \
1800      volatile unsigned long _res;                                     \
1801      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1802      _argvec[1] = (unsigned long)(arg1);                              \
1803      __asm__ volatile(                                                \
1804         VALGRIND_CFI_PROLOGUE                                         \
1805         VALGRIND_ALIGN_STACK                                          \
1806         "subq $128,%%rsp\n\t"                                         \
1807         "movq 8(%%rax), %%rdi\n\t"                                    \
1808         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1809         VALGRIND_CALL_NOREDIR_RAX                                     \
1810         VALGRIND_RESTORE_STACK                                        \
1811         VALGRIND_CFI_EPILOGUE                                         \
1812         : /*out*/   "=a" (_res)                                       \
1813         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1814         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1815      );                                                               \
1816      lval = (__typeof__(lval)) _res;                                  \
1817   } while (0)
1818
1819#define CALL_FN_W_WW(lval, orig, arg1,arg2)                            \
1820   do {                                                                \
1821      volatile OrigFn        _orig = (orig);                           \
1822      volatile unsigned long _argvec[3];                               \
1823      volatile unsigned long _res;                                     \
1824      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1825      _argvec[1] = (unsigned long)(arg1);                              \
1826      _argvec[2] = (unsigned long)(arg2);                              \
1827      __asm__ volatile(                                                \
1828         VALGRIND_CFI_PROLOGUE                                         \
1829         VALGRIND_ALIGN_STACK                                          \
1830         "subq $128,%%rsp\n\t"                                         \
1831         "movq 16(%%rax), %%rsi\n\t"                                   \
1832         "movq 8(%%rax), %%rdi\n\t"                                    \
1833         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1834         VALGRIND_CALL_NOREDIR_RAX                                     \
1835         VALGRIND_RESTORE_STACK                                        \
1836         VALGRIND_CFI_EPILOGUE                                         \
1837         : /*out*/   "=a" (_res)                                       \
1838         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1839         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1840      );                                                               \
1841      lval = (__typeof__(lval)) _res;                                  \
1842   } while (0)
1843
1844#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                      \
1845   do {                                                                \
1846      volatile OrigFn        _orig = (orig);                           \
1847      volatile unsigned long _argvec[4];                               \
1848      volatile unsigned long _res;                                     \
1849      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1850      _argvec[1] = (unsigned long)(arg1);                              \
1851      _argvec[2] = (unsigned long)(arg2);                              \
1852      _argvec[3] = (unsigned long)(arg3);                              \
1853      __asm__ volatile(                                                \
1854         VALGRIND_CFI_PROLOGUE                                         \
1855         VALGRIND_ALIGN_STACK                                          \
1856         "subq $128,%%rsp\n\t"                                         \
1857         "movq 24(%%rax), %%rdx\n\t"                                   \
1858         "movq 16(%%rax), %%rsi\n\t"                                   \
1859         "movq 8(%%rax), %%rdi\n\t"                                    \
1860         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1861         VALGRIND_CALL_NOREDIR_RAX                                     \
1862         VALGRIND_RESTORE_STACK                                        \
1863         VALGRIND_CFI_EPILOGUE                                         \
1864         : /*out*/   "=a" (_res)                                       \
1865         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1866         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1867      );                                                               \
1868      lval = (__typeof__(lval)) _res;                                  \
1869   } while (0)
1870
1871#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)                \
1872   do {                                                                \
1873      volatile OrigFn        _orig = (orig);                           \
1874      volatile unsigned long _argvec[5];                               \
1875      volatile unsigned long _res;                                     \
1876      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1877      _argvec[1] = (unsigned long)(arg1);                              \
1878      _argvec[2] = (unsigned long)(arg2);                              \
1879      _argvec[3] = (unsigned long)(arg3);                              \
1880      _argvec[4] = (unsigned long)(arg4);                              \
1881      __asm__ volatile(                                                \
1882         VALGRIND_CFI_PROLOGUE                                         \
1883         VALGRIND_ALIGN_STACK                                          \
1884         "subq $128,%%rsp\n\t"                                         \
1885         "movq 32(%%rax), %%rcx\n\t"                                   \
1886         "movq 24(%%rax), %%rdx\n\t"                                   \
1887         "movq 16(%%rax), %%rsi\n\t"                                   \
1888         "movq 8(%%rax), %%rdi\n\t"                                    \
1889         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1890         VALGRIND_CALL_NOREDIR_RAX                                     \
1891         VALGRIND_RESTORE_STACK                                        \
1892         VALGRIND_CFI_EPILOGUE                                         \
1893         : /*out*/   "=a" (_res)                                       \
1894         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1895         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1896      );                                                               \
1897      lval = (__typeof__(lval)) _res;                                  \
1898   } while (0)
1899
1900#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)             \
1901   do {                                                                \
1902      volatile OrigFn        _orig = (orig);                           \
1903      volatile unsigned long _argvec[6];                               \
1904      volatile unsigned long _res;                                     \
1905      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1906      _argvec[1] = (unsigned long)(arg1);                              \
1907      _argvec[2] = (unsigned long)(arg2);                              \
1908      _argvec[3] = (unsigned long)(arg3);                              \
1909      _argvec[4] = (unsigned long)(arg4);                              \
1910      _argvec[5] = (unsigned long)(arg5);                              \
1911      __asm__ volatile(                                                \
1912         VALGRIND_CFI_PROLOGUE                                         \
1913         VALGRIND_ALIGN_STACK                                          \
1914         "subq $128,%%rsp\n\t"                                         \
1915         "movq 40(%%rax), %%r8\n\t"                                    \
1916         "movq 32(%%rax), %%rcx\n\t"                                   \
1917         "movq 24(%%rax), %%rdx\n\t"                                   \
1918         "movq 16(%%rax), %%rsi\n\t"                                   \
1919         "movq 8(%%rax), %%rdi\n\t"                                    \
1920         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1921         VALGRIND_CALL_NOREDIR_RAX                                     \
1922         VALGRIND_RESTORE_STACK                                        \
1923         VALGRIND_CFI_EPILOGUE                                         \
1924         : /*out*/   "=a" (_res)                                       \
1925         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1926         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1927      );                                                               \
1928      lval = (__typeof__(lval)) _res;                                  \
1929   } while (0)
1930
1931#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)        \
1932   do {                                                                \
1933      volatile OrigFn        _orig = (orig);                           \
1934      volatile unsigned long _argvec[7];                               \
1935      volatile unsigned long _res;                                     \
1936      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1937      _argvec[1] = (unsigned long)(arg1);                              \
1938      _argvec[2] = (unsigned long)(arg2);                              \
1939      _argvec[3] = (unsigned long)(arg3);                              \
1940      _argvec[4] = (unsigned long)(arg4);                              \
1941      _argvec[5] = (unsigned long)(arg5);                              \
1942      _argvec[6] = (unsigned long)(arg6);                              \
1943      __asm__ volatile(                                                \
1944         VALGRIND_CFI_PROLOGUE                                         \
1945         VALGRIND_ALIGN_STACK                                          \
1946         "subq $128,%%rsp\n\t"                                         \
1947         "movq 48(%%rax), %%r9\n\t"                                    \
1948         "movq 40(%%rax), %%r8\n\t"                                    \
1949         "movq 32(%%rax), %%rcx\n\t"                                   \
1950         "movq 24(%%rax), %%rdx\n\t"                                   \
1951         "movq 16(%%rax), %%rsi\n\t"                                   \
1952         "movq 8(%%rax), %%rdi\n\t"                                    \
1953         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1954         VALGRIND_CALL_NOREDIR_RAX                                     \
1955         VALGRIND_RESTORE_STACK                                        \
1956         VALGRIND_CFI_EPILOGUE                                         \
1957         : /*out*/   "=a" (_res)                                       \
1958         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1959         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1960      );                                                               \
1961      lval = (__typeof__(lval)) _res;                                  \
1962   } while (0)
1963
1964#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
1965                                 arg7)                                 \
1966   do {                                                                \
1967      volatile OrigFn        _orig = (orig);                           \
1968      volatile unsigned long _argvec[8];                               \
1969      volatile unsigned long _res;                                     \
1970      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1971      _argvec[1] = (unsigned long)(arg1);                              \
1972      _argvec[2] = (unsigned long)(arg2);                              \
1973      _argvec[3] = (unsigned long)(arg3);                              \
1974      _argvec[4] = (unsigned long)(arg4);                              \
1975      _argvec[5] = (unsigned long)(arg5);                              \
1976      _argvec[6] = (unsigned long)(arg6);                              \
1977      _argvec[7] = (unsigned long)(arg7);                              \
1978      __asm__ volatile(                                                \
1979         VALGRIND_CFI_PROLOGUE                                         \
1980         VALGRIND_ALIGN_STACK                                          \
1981         "subq $136,%%rsp\n\t"                                         \
1982         "pushq 56(%%rax)\n\t"                                         \
1983         "movq 48(%%rax), %%r9\n\t"                                    \
1984         "movq 40(%%rax), %%r8\n\t"                                    \
1985         "movq 32(%%rax), %%rcx\n\t"                                   \
1986         "movq 24(%%rax), %%rdx\n\t"                                   \
1987         "movq 16(%%rax), %%rsi\n\t"                                   \
1988         "movq 8(%%rax), %%rdi\n\t"                                    \
1989         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1990         VALGRIND_CALL_NOREDIR_RAX                                     \
1991         VALGRIND_RESTORE_STACK                                        \
1992         VALGRIND_CFI_EPILOGUE                                         \
1993         : /*out*/   "=a" (_res)                                       \
1994         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1995         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1996      );                                                               \
1997      lval = (__typeof__(lval)) _res;                                  \
1998   } while (0)
1999
2000#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
2001                                 arg7,arg8)                            \
2002   do {                                                                \
2003      volatile OrigFn        _orig = (orig);                           \
2004      volatile unsigned long _argvec[9];                               \
2005      volatile unsigned long _res;                                     \
2006      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2007      _argvec[1] = (unsigned long)(arg1);                              \
2008      _argvec[2] = (unsigned long)(arg2);                              \
2009      _argvec[3] = (unsigned long)(arg3);                              \
2010      _argvec[4] = (unsigned long)(arg4);                              \
2011      _argvec[5] = (unsigned long)(arg5);                              \
2012      _argvec[6] = (unsigned long)(arg6);                              \
2013      _argvec[7] = (unsigned long)(arg7);                              \
2014      _argvec[8] = (unsigned long)(arg8);                              \
2015      __asm__ volatile(                                                \
2016         VALGRIND_CFI_PROLOGUE                                         \
2017         VALGRIND_ALIGN_STACK                                          \
2018         "subq $128,%%rsp\n\t"                                         \
2019         "pushq 64(%%rax)\n\t"                                         \
2020         "pushq 56(%%rax)\n\t"                                         \
2021         "movq 48(%%rax), %%r9\n\t"                                    \
2022         "movq 40(%%rax), %%r8\n\t"                                    \
2023         "movq 32(%%rax), %%rcx\n\t"                                   \
2024         "movq 24(%%rax), %%rdx\n\t"                                   \
2025         "movq 16(%%rax), %%rsi\n\t"                                   \
2026         "movq 8(%%rax), %%rdi\n\t"                                    \
2027         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2028         VALGRIND_CALL_NOREDIR_RAX                                     \
2029         VALGRIND_RESTORE_STACK                                        \
2030         VALGRIND_CFI_EPILOGUE                                         \
2031         : /*out*/   "=a" (_res)                                       \
2032         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2033         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2034      );                                                               \
2035      lval = (__typeof__(lval)) _res;                                  \
2036   } while (0)
2037
2038#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
2039                                 arg7,arg8,arg9)                       \
2040   do {                                                                \
2041      volatile OrigFn        _orig = (orig);                           \
2042      volatile unsigned long _argvec[10];                              \
2043      volatile unsigned long _res;                                     \
2044      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2045      _argvec[1] = (unsigned long)(arg1);                              \
2046      _argvec[2] = (unsigned long)(arg2);                              \
2047      _argvec[3] = (unsigned long)(arg3);                              \
2048      _argvec[4] = (unsigned long)(arg4);                              \
2049      _argvec[5] = (unsigned long)(arg5);                              \
2050      _argvec[6] = (unsigned long)(arg6);                              \
2051      _argvec[7] = (unsigned long)(arg7);                              \
2052      _argvec[8] = (unsigned long)(arg8);                              \
2053      _argvec[9] = (unsigned long)(arg9);                              \
2054      __asm__ volatile(                                                \
2055         VALGRIND_CFI_PROLOGUE                                         \
2056         VALGRIND_ALIGN_STACK                                          \
2057         "subq $136,%%rsp\n\t"                                         \
2058         "pushq 72(%%rax)\n\t"                                         \
2059         "pushq 64(%%rax)\n\t"                                         \
2060         "pushq 56(%%rax)\n\t"                                         \
2061         "movq 48(%%rax), %%r9\n\t"                                    \
2062         "movq 40(%%rax), %%r8\n\t"                                    \
2063         "movq 32(%%rax), %%rcx\n\t"                                   \
2064         "movq 24(%%rax), %%rdx\n\t"                                   \
2065         "movq 16(%%rax), %%rsi\n\t"                                   \
2066         "movq 8(%%rax), %%rdi\n\t"                                    \
2067         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2068         VALGRIND_CALL_NOREDIR_RAX                                     \
2069         VALGRIND_RESTORE_STACK                                        \
2070         VALGRIND_CFI_EPILOGUE                                         \
2071         : /*out*/   "=a" (_res)                                       \
2072         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2073         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2074      );                                                               \
2075      lval = (__typeof__(lval)) _res;                                  \
2076   } while (0)
2077
2078#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
2079                                  arg7,arg8,arg9,arg10)                \
2080   do {                                                                \
2081      volatile OrigFn        _orig = (orig);                           \
2082      volatile unsigned long _argvec[11];                              \
2083      volatile unsigned long _res;                                     \
2084      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2085      _argvec[1] = (unsigned long)(arg1);                              \
2086      _argvec[2] = (unsigned long)(arg2);                              \
2087      _argvec[3] = (unsigned long)(arg3);                              \
2088      _argvec[4] = (unsigned long)(arg4);                              \
2089      _argvec[5] = (unsigned long)(arg5);                              \
2090      _argvec[6] = (unsigned long)(arg6);                              \
2091      _argvec[7] = (unsigned long)(arg7);                              \
2092      _argvec[8] = (unsigned long)(arg8);                              \
2093      _argvec[9] = (unsigned long)(arg9);                              \
2094      _argvec[10] = (unsigned long)(arg10);                            \
2095      __asm__ volatile(                                                \
2096         VALGRIND_CFI_PROLOGUE                                         \
2097         VALGRIND_ALIGN_STACK                                          \
2098         "subq $128,%%rsp\n\t"                                         \
2099         "pushq 80(%%rax)\n\t"                                         \
2100         "pushq 72(%%rax)\n\t"                                         \
2101         "pushq 64(%%rax)\n\t"                                         \
2102         "pushq 56(%%rax)\n\t"                                         \
2103         "movq 48(%%rax), %%r9\n\t"                                    \
2104         "movq 40(%%rax), %%r8\n\t"                                    \
2105         "movq 32(%%rax), %%rcx\n\t"                                   \
2106         "movq 24(%%rax), %%rdx\n\t"                                   \
2107         "movq 16(%%rax), %%rsi\n\t"                                   \
2108         "movq 8(%%rax), %%rdi\n\t"                                    \
2109         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2110         VALGRIND_CALL_NOREDIR_RAX                                     \
2111         VALGRIND_RESTORE_STACK                                        \
2112         VALGRIND_CFI_EPILOGUE                                         \
2113         : /*out*/   "=a" (_res)                                       \
2114         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2115         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2116      );                                                               \
2117      lval = (__typeof__(lval)) _res;                                  \
2118   } while (0)
2119
2120#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
2121                                  arg7,arg8,arg9,arg10,arg11)          \
2122   do {                                                                \
2123      volatile OrigFn        _orig = (orig);                           \
2124      volatile unsigned long _argvec[12];                              \
2125      volatile unsigned long _res;                                     \
2126      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2127      _argvec[1] = (unsigned long)(arg1);                              \
2128      _argvec[2] = (unsigned long)(arg2);                              \
2129      _argvec[3] = (unsigned long)(arg3);                              \
2130      _argvec[4] = (unsigned long)(arg4);                              \
2131      _argvec[5] = (unsigned long)(arg5);                              \
2132      _argvec[6] = (unsigned long)(arg6);                              \
2133      _argvec[7] = (unsigned long)(arg7);                              \
2134      _argvec[8] = (unsigned long)(arg8);                              \
2135      _argvec[9] = (unsigned long)(arg9);                              \
2136      _argvec[10] = (unsigned long)(arg10);                            \
2137      _argvec[11] = (unsigned long)(arg11);                            \
2138      __asm__ volatile(                                                \
2139         VALGRIND_CFI_PROLOGUE                                         \
2140         VALGRIND_ALIGN_STACK                                          \
2141         "subq $136,%%rsp\n\t"                                         \
2142         "pushq 88(%%rax)\n\t"                                         \
2143         "pushq 80(%%rax)\n\t"                                         \
2144         "pushq 72(%%rax)\n\t"                                         \
2145         "pushq 64(%%rax)\n\t"                                         \
2146         "pushq 56(%%rax)\n\t"                                         \
2147         "movq 48(%%rax), %%r9\n\t"                                    \
2148         "movq 40(%%rax), %%r8\n\t"                                    \
2149         "movq 32(%%rax), %%rcx\n\t"                                   \
2150         "movq 24(%%rax), %%rdx\n\t"                                   \
2151         "movq 16(%%rax), %%rsi\n\t"                                   \
2152         "movq 8(%%rax), %%rdi\n\t"                                    \
2153         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2154         VALGRIND_CALL_NOREDIR_RAX                                     \
2155         VALGRIND_RESTORE_STACK                                        \
2156         VALGRIND_CFI_EPILOGUE                                         \
2157         : /*out*/   "=a" (_res)                                       \
2158         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2159         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2160      );                                                               \
2161      lval = (__typeof__(lval)) _res;                                  \
2162   } while (0)
2163
2164#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
2165                                arg7,arg8,arg9,arg10,arg11,arg12)      \
2166   do {                                                                \
2167      volatile OrigFn        _orig = (orig);                           \
2168      volatile unsigned long _argvec[13];                              \
2169      volatile unsigned long _res;                                     \
2170      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2171      _argvec[1] = (unsigned long)(arg1);                              \
2172      _argvec[2] = (unsigned long)(arg2);                              \
2173      _argvec[3] = (unsigned long)(arg3);                              \
2174      _argvec[4] = (unsigned long)(arg4);                              \
2175      _argvec[5] = (unsigned long)(arg5);                              \
2176      _argvec[6] = (unsigned long)(arg6);                              \
2177      _argvec[7] = (unsigned long)(arg7);                              \
2178      _argvec[8] = (unsigned long)(arg8);                              \
2179      _argvec[9] = (unsigned long)(arg9);                              \
2180      _argvec[10] = (unsigned long)(arg10);                            \
2181      _argvec[11] = (unsigned long)(arg11);                            \
2182      _argvec[12] = (unsigned long)(arg12);                            \
2183      __asm__ volatile(                                                \
2184         VALGRIND_CFI_PROLOGUE                                         \
2185         VALGRIND_ALIGN_STACK                                          \
2186         "subq $128,%%rsp\n\t"                                         \
2187         "pushq 96(%%rax)\n\t"                                         \
2188         "pushq 88(%%rax)\n\t"                                         \
2189         "pushq 80(%%rax)\n\t"                                         \
2190         "pushq 72(%%rax)\n\t"                                         \
2191         "pushq 64(%%rax)\n\t"                                         \
2192         "pushq 56(%%rax)\n\t"                                         \
2193         "movq 48(%%rax), %%r9\n\t"                                    \
2194         "movq 40(%%rax), %%r8\n\t"                                    \
2195         "movq 32(%%rax), %%rcx\n\t"                                   \
2196         "movq 24(%%rax), %%rdx\n\t"                                   \
2197         "movq 16(%%rax), %%rsi\n\t"                                   \
2198         "movq 8(%%rax), %%rdi\n\t"                                    \
2199         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2200         VALGRIND_CALL_NOREDIR_RAX                                     \
2201         VALGRIND_RESTORE_STACK                                        \
2202         VALGRIND_CFI_EPILOGUE                                         \
2203         : /*out*/   "=a" (_res)                                       \
2204         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2205         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2206      );                                                               \
2207      lval = (__typeof__(lval)) _res;                                  \
2208   } while (0)
2209
2210#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
2211
2212/* ------------------------ ppc32-linux ------------------------ */
2213
2214#if defined(PLAT_ppc32_linux)
2215
2216/* This is useful for finding out about the on-stack stuff:
2217
2218   extern int f9  ( int,int,int,int,int,int,int,int,int );
2219   extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2220   extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2221   extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2222
2223   int g9 ( void ) {
2224      return f9(11,22,33,44,55,66,77,88,99);
2225   }
2226   int g10 ( void ) {
2227      return f10(11,22,33,44,55,66,77,88,99,110);
2228   }
2229   int g11 ( void ) {
2230      return f11(11,22,33,44,55,66,77,88,99,110,121);
2231   }
2232   int g12 ( void ) {
2233      return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2234   }
2235*/
2236
2237/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2238
2239/* These regs are trashed by the hidden call. */
2240#define __CALLER_SAVED_REGS                                       \
2241   "lr", "ctr", "xer",                                            \
2242   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
2243   "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
2244   "r11", "r12", "r13"
2245
2246/* Macros to save and align the stack before making a function
2247   call and restore it afterwards as gcc may not keep the stack
2248   pointer aligned if it doesn't realise calls are being made
2249   to other functions. */
2250
2251#define VALGRIND_ALIGN_STACK               \
2252      "mr 28,1\n\t"                        \
2253      "rlwinm 1,1,0,0,27\n\t"
2254#define VALGRIND_RESTORE_STACK             \
2255      "mr 1,28\n\t"
2256
2257/* These CALL_FN_ macros assume that on ppc32-linux,
2258   sizeof(unsigned long) == 4. */
2259
2260#define CALL_FN_W_v(lval, orig)                                   \
2261   do {                                                           \
2262      volatile OrigFn        _orig = (orig);                      \
2263      volatile unsigned long _argvec[1];                          \
2264      volatile unsigned long _res;                                \
2265      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2266      __asm__ volatile(                                           \
2267         VALGRIND_ALIGN_STACK                                     \
2268         "mr 11,%1\n\t"                                           \
2269         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2270         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2271         VALGRIND_RESTORE_STACK                                   \
2272         "mr %0,3"                                                \
2273         : /*out*/   "=r" (_res)                                  \
2274         : /*in*/    "r" (&_argvec[0])                            \
2275         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2276      );                                                          \
2277      lval = (__typeof__(lval)) _res;                             \
2278   } while (0)
2279
2280#define CALL_FN_W_W(lval, orig, arg1)                             \
2281   do {                                                           \
2282      volatile OrigFn        _orig = (orig);                      \
2283      volatile unsigned long _argvec[2];                          \
2284      volatile unsigned long _res;                                \
2285      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2286      _argvec[1] = (unsigned long)arg1;                           \
2287      __asm__ volatile(                                           \
2288         VALGRIND_ALIGN_STACK                                     \
2289         "mr 11,%1\n\t"                                           \
2290         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2291         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2292         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2293         VALGRIND_RESTORE_STACK                                   \
2294         "mr %0,3"                                                \
2295         : /*out*/   "=r" (_res)                                  \
2296         : /*in*/    "r" (&_argvec[0])                            \
2297         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2298      );                                                          \
2299      lval = (__typeof__(lval)) _res;                             \
2300   } while (0)
2301
2302#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
2303   do {                                                           \
2304      volatile OrigFn        _orig = (orig);                      \
2305      volatile unsigned long _argvec[3];                          \
2306      volatile unsigned long _res;                                \
2307      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2308      _argvec[1] = (unsigned long)arg1;                           \
2309      _argvec[2] = (unsigned long)arg2;                           \
2310      __asm__ volatile(                                           \
2311         VALGRIND_ALIGN_STACK                                     \
2312         "mr 11,%1\n\t"                                           \
2313         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2314         "lwz 4,8(11)\n\t"                                        \
2315         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2316         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2317         VALGRIND_RESTORE_STACK                                   \
2318         "mr %0,3"                                                \
2319         : /*out*/   "=r" (_res)                                  \
2320         : /*in*/    "r" (&_argvec[0])                            \
2321         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2322      );                                                          \
2323      lval = (__typeof__(lval)) _res;                             \
2324   } while (0)
2325
2326#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2327   do {                                                           \
2328      volatile OrigFn        _orig = (orig);                      \
2329      volatile unsigned long _argvec[4];                          \
2330      volatile unsigned long _res;                                \
2331      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2332      _argvec[1] = (unsigned long)arg1;                           \
2333      _argvec[2] = (unsigned long)arg2;                           \
2334      _argvec[3] = (unsigned long)arg3;                           \
2335      __asm__ volatile(                                           \
2336         VALGRIND_ALIGN_STACK                                     \
2337         "mr 11,%1\n\t"                                           \
2338         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2339         "lwz 4,8(11)\n\t"                                        \
2340         "lwz 5,12(11)\n\t"                                       \
2341         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2342         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2343         VALGRIND_RESTORE_STACK                                   \
2344         "mr %0,3"                                                \
2345         : /*out*/   "=r" (_res)                                  \
2346         : /*in*/    "r" (&_argvec[0])                            \
2347         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2348      );                                                          \
2349      lval = (__typeof__(lval)) _res;                             \
2350   } while (0)
2351
2352#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2353   do {                                                           \
2354      volatile OrigFn        _orig = (orig);                      \
2355      volatile unsigned long _argvec[5];                          \
2356      volatile unsigned long _res;                                \
2357      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2358      _argvec[1] = (unsigned long)arg1;                           \
2359      _argvec[2] = (unsigned long)arg2;                           \
2360      _argvec[3] = (unsigned long)arg3;                           \
2361      _argvec[4] = (unsigned long)arg4;                           \
2362      __asm__ volatile(                                           \
2363         VALGRIND_ALIGN_STACK                                     \
2364         "mr 11,%1\n\t"                                           \
2365         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2366         "lwz 4,8(11)\n\t"                                        \
2367         "lwz 5,12(11)\n\t"                                       \
2368         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2369         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2370         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2371         VALGRIND_RESTORE_STACK                                   \
2372         "mr %0,3"                                                \
2373         : /*out*/   "=r" (_res)                                  \
2374         : /*in*/    "r" (&_argvec[0])                            \
2375         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2376      );                                                          \
2377      lval = (__typeof__(lval)) _res;                             \
2378   } while (0)
2379
2380#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2381   do {                                                           \
2382      volatile OrigFn        _orig = (orig);                      \
2383      volatile unsigned long _argvec[6];                          \
2384      volatile unsigned long _res;                                \
2385      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2386      _argvec[1] = (unsigned long)arg1;                           \
2387      _argvec[2] = (unsigned long)arg2;                           \
2388      _argvec[3] = (unsigned long)arg3;                           \
2389      _argvec[4] = (unsigned long)arg4;                           \
2390      _argvec[5] = (unsigned long)arg5;                           \
2391      __asm__ volatile(                                           \
2392         VALGRIND_ALIGN_STACK                                     \
2393         "mr 11,%1\n\t"                                           \
2394         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2395         "lwz 4,8(11)\n\t"                                        \
2396         "lwz 5,12(11)\n\t"                                       \
2397         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2398         "lwz 7,20(11)\n\t"                                       \
2399         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2400         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2401         VALGRIND_RESTORE_STACK                                   \
2402         "mr %0,3"                                                \
2403         : /*out*/   "=r" (_res)                                  \
2404         : /*in*/    "r" (&_argvec[0])                            \
2405         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2406      );                                                          \
2407      lval = (__typeof__(lval)) _res;                             \
2408   } while (0)
2409
2410#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2411   do {                                                           \
2412      volatile OrigFn        _orig = (orig);                      \
2413      volatile unsigned long _argvec[7];                          \
2414      volatile unsigned long _res;                                \
2415      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2416      _argvec[1] = (unsigned long)arg1;                           \
2417      _argvec[2] = (unsigned long)arg2;                           \
2418      _argvec[3] = (unsigned long)arg3;                           \
2419      _argvec[4] = (unsigned long)arg4;                           \
2420      _argvec[5] = (unsigned long)arg5;                           \
2421      _argvec[6] = (unsigned long)arg6;                           \
2422      __asm__ volatile(                                           \
2423         VALGRIND_ALIGN_STACK                                     \
2424         "mr 11,%1\n\t"                                           \
2425         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2426         "lwz 4,8(11)\n\t"                                        \
2427         "lwz 5,12(11)\n\t"                                       \
2428         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2429         "lwz 7,20(11)\n\t"                                       \
2430         "lwz 8,24(11)\n\t"                                       \
2431         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2432         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2433         VALGRIND_RESTORE_STACK                                   \
2434         "mr %0,3"                                                \
2435         : /*out*/   "=r" (_res)                                  \
2436         : /*in*/    "r" (&_argvec[0])                            \
2437         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2438      );                                                          \
2439      lval = (__typeof__(lval)) _res;                             \
2440   } while (0)
2441
2442#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2443                                 arg7)                            \
2444   do {                                                           \
2445      volatile OrigFn        _orig = (orig);                      \
2446      volatile unsigned long _argvec[8];                          \
2447      volatile unsigned long _res;                                \
2448      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2449      _argvec[1] = (unsigned long)arg1;                           \
2450      _argvec[2] = (unsigned long)arg2;                           \
2451      _argvec[3] = (unsigned long)arg3;                           \
2452      _argvec[4] = (unsigned long)arg4;                           \
2453      _argvec[5] = (unsigned long)arg5;                           \
2454      _argvec[6] = (unsigned long)arg6;                           \
2455      _argvec[7] = (unsigned long)arg7;                           \
2456      __asm__ volatile(                                           \
2457         VALGRIND_ALIGN_STACK                                     \
2458         "mr 11,%1\n\t"                                           \
2459         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2460         "lwz 4,8(11)\n\t"                                        \
2461         "lwz 5,12(11)\n\t"                                       \
2462         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2463         "lwz 7,20(11)\n\t"                                       \
2464         "lwz 8,24(11)\n\t"                                       \
2465         "lwz 9,28(11)\n\t"                                       \
2466         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2467         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2468         VALGRIND_RESTORE_STACK                                   \
2469         "mr %0,3"                                                \
2470         : /*out*/   "=r" (_res)                                  \
2471         : /*in*/    "r" (&_argvec[0])                            \
2472         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2473      );                                                          \
2474      lval = (__typeof__(lval)) _res;                             \
2475   } while (0)
2476
2477#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2478                                 arg7,arg8)                       \
2479   do {                                                           \
2480      volatile OrigFn        _orig = (orig);                      \
2481      volatile unsigned long _argvec[9];                          \
2482      volatile unsigned long _res;                                \
2483      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2484      _argvec[1] = (unsigned long)arg1;                           \
2485      _argvec[2] = (unsigned long)arg2;                           \
2486      _argvec[3] = (unsigned long)arg3;                           \
2487      _argvec[4] = (unsigned long)arg4;                           \
2488      _argvec[5] = (unsigned long)arg5;                           \
2489      _argvec[6] = (unsigned long)arg6;                           \
2490      _argvec[7] = (unsigned long)arg7;                           \
2491      _argvec[8] = (unsigned long)arg8;                           \
2492      __asm__ volatile(                                           \
2493         VALGRIND_ALIGN_STACK                                     \
2494         "mr 11,%1\n\t"                                           \
2495         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2496         "lwz 4,8(11)\n\t"                                        \
2497         "lwz 5,12(11)\n\t"                                       \
2498         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2499         "lwz 7,20(11)\n\t"                                       \
2500         "lwz 8,24(11)\n\t"                                       \
2501         "lwz 9,28(11)\n\t"                                       \
2502         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2503         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2504         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2505         VALGRIND_RESTORE_STACK                                   \
2506         "mr %0,3"                                                \
2507         : /*out*/   "=r" (_res)                                  \
2508         : /*in*/    "r" (&_argvec[0])                            \
2509         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2510      );                                                          \
2511      lval = (__typeof__(lval)) _res;                             \
2512   } while (0)
2513
2514#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2515                                 arg7,arg8,arg9)                  \
2516   do {                                                           \
2517      volatile OrigFn        _orig = (orig);                      \
2518      volatile unsigned long _argvec[10];                         \
2519      volatile unsigned long _res;                                \
2520      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2521      _argvec[1] = (unsigned long)arg1;                           \
2522      _argvec[2] = (unsigned long)arg2;                           \
2523      _argvec[3] = (unsigned long)arg3;                           \
2524      _argvec[4] = (unsigned long)arg4;                           \
2525      _argvec[5] = (unsigned long)arg5;                           \
2526      _argvec[6] = (unsigned long)arg6;                           \
2527      _argvec[7] = (unsigned long)arg7;                           \
2528      _argvec[8] = (unsigned long)arg8;                           \
2529      _argvec[9] = (unsigned long)arg9;                           \
2530      __asm__ volatile(                                           \
2531         VALGRIND_ALIGN_STACK                                     \
2532         "mr 11,%1\n\t"                                           \
2533         "addi 1,1,-16\n\t"                                       \
2534         /* arg9 */                                               \
2535         "lwz 3,36(11)\n\t"                                       \
2536         "stw 3,8(1)\n\t"                                         \
2537         /* args1-8 */                                            \
2538         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2539         "lwz 4,8(11)\n\t"                                        \
2540         "lwz 5,12(11)\n\t"                                       \
2541         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2542         "lwz 7,20(11)\n\t"                                       \
2543         "lwz 8,24(11)\n\t"                                       \
2544         "lwz 9,28(11)\n\t"                                       \
2545         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2546         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2547         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2548         VALGRIND_RESTORE_STACK                                   \
2549         "mr %0,3"                                                \
2550         : /*out*/   "=r" (_res)                                  \
2551         : /*in*/    "r" (&_argvec[0])                            \
2552         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2553      );                                                          \
2554      lval = (__typeof__(lval)) _res;                             \
2555   } while (0)
2556
2557#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2558                                  arg7,arg8,arg9,arg10)           \
2559   do {                                                           \
2560      volatile OrigFn        _orig = (orig);                      \
2561      volatile unsigned long _argvec[11];                         \
2562      volatile unsigned long _res;                                \
2563      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2564      _argvec[1] = (unsigned long)arg1;                           \
2565      _argvec[2] = (unsigned long)arg2;                           \
2566      _argvec[3] = (unsigned long)arg3;                           \
2567      _argvec[4] = (unsigned long)arg4;                           \
2568      _argvec[5] = (unsigned long)arg5;                           \
2569      _argvec[6] = (unsigned long)arg6;                           \
2570      _argvec[7] = (unsigned long)arg7;                           \
2571      _argvec[8] = (unsigned long)arg8;                           \
2572      _argvec[9] = (unsigned long)arg9;                           \
2573      _argvec[10] = (unsigned long)arg10;                         \
2574      __asm__ volatile(                                           \
2575         VALGRIND_ALIGN_STACK                                     \
2576         "mr 11,%1\n\t"                                           \
2577         "addi 1,1,-16\n\t"                                       \
2578         /* arg10 */                                              \
2579         "lwz 3,40(11)\n\t"                                       \
2580         "stw 3,12(1)\n\t"                                        \
2581         /* arg9 */                                               \
2582         "lwz 3,36(11)\n\t"                                       \
2583         "stw 3,8(1)\n\t"                                         \
2584         /* args1-8 */                                            \
2585         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2586         "lwz 4,8(11)\n\t"                                        \
2587         "lwz 5,12(11)\n\t"                                       \
2588         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2589         "lwz 7,20(11)\n\t"                                       \
2590         "lwz 8,24(11)\n\t"                                       \
2591         "lwz 9,28(11)\n\t"                                       \
2592         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2593         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2594         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2595         VALGRIND_RESTORE_STACK                                   \
2596         "mr %0,3"                                                \
2597         : /*out*/   "=r" (_res)                                  \
2598         : /*in*/    "r" (&_argvec[0])                            \
2599         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2600      );                                                          \
2601      lval = (__typeof__(lval)) _res;                             \
2602   } while (0)
2603
2604#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2605                                  arg7,arg8,arg9,arg10,arg11)     \
2606   do {                                                           \
2607      volatile OrigFn        _orig = (orig);                      \
2608      volatile unsigned long _argvec[12];                         \
2609      volatile unsigned long _res;                                \
2610      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2611      _argvec[1] = (unsigned long)arg1;                           \
2612      _argvec[2] = (unsigned long)arg2;                           \
2613      _argvec[3] = (unsigned long)arg3;                           \
2614      _argvec[4] = (unsigned long)arg4;                           \
2615      _argvec[5] = (unsigned long)arg5;                           \
2616      _argvec[6] = (unsigned long)arg6;                           \
2617      _argvec[7] = (unsigned long)arg7;                           \
2618      _argvec[8] = (unsigned long)arg8;                           \
2619      _argvec[9] = (unsigned long)arg9;                           \
2620      _argvec[10] = (unsigned long)arg10;                         \
2621      _argvec[11] = (unsigned long)arg11;                         \
2622      __asm__ volatile(                                           \
2623         VALGRIND_ALIGN_STACK                                     \
2624         "mr 11,%1\n\t"                                           \
2625         "addi 1,1,-32\n\t"                                       \
2626         /* arg11 */                                              \
2627         "lwz 3,44(11)\n\t"                                       \
2628         "stw 3,16(1)\n\t"                                        \
2629         /* arg10 */                                              \
2630         "lwz 3,40(11)\n\t"                                       \
2631         "stw 3,12(1)\n\t"                                        \
2632         /* arg9 */                                               \
2633         "lwz 3,36(11)\n\t"                                       \
2634         "stw 3,8(1)\n\t"                                         \
2635         /* args1-8 */                                            \
2636         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2637         "lwz 4,8(11)\n\t"                                        \
2638         "lwz 5,12(11)\n\t"                                       \
2639         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2640         "lwz 7,20(11)\n\t"                                       \
2641         "lwz 8,24(11)\n\t"                                       \
2642         "lwz 9,28(11)\n\t"                                       \
2643         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2644         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2645         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2646         VALGRIND_RESTORE_STACK                                   \
2647         "mr %0,3"                                                \
2648         : /*out*/   "=r" (_res)                                  \
2649         : /*in*/    "r" (&_argvec[0])                            \
2650         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2651      );                                                          \
2652      lval = (__typeof__(lval)) _res;                             \
2653   } while (0)
2654
2655#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2656                                arg7,arg8,arg9,arg10,arg11,arg12) \
2657   do {                                                           \
2658      volatile OrigFn        _orig = (orig);                      \
2659      volatile unsigned long _argvec[13];                         \
2660      volatile unsigned long _res;                                \
2661      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2662      _argvec[1] = (unsigned long)arg1;                           \
2663      _argvec[2] = (unsigned long)arg2;                           \
2664      _argvec[3] = (unsigned long)arg3;                           \
2665      _argvec[4] = (unsigned long)arg4;                           \
2666      _argvec[5] = (unsigned long)arg5;                           \
2667      _argvec[6] = (unsigned long)arg6;                           \
2668      _argvec[7] = (unsigned long)arg7;                           \
2669      _argvec[8] = (unsigned long)arg8;                           \
2670      _argvec[9] = (unsigned long)arg9;                           \
2671      _argvec[10] = (unsigned long)arg10;                         \
2672      _argvec[11] = (unsigned long)arg11;                         \
2673      _argvec[12] = (unsigned long)arg12;                         \
2674      __asm__ volatile(                                           \
2675         VALGRIND_ALIGN_STACK                                     \
2676         "mr 11,%1\n\t"                                           \
2677         "addi 1,1,-32\n\t"                                       \
2678         /* arg12 */                                              \
2679         "lwz 3,48(11)\n\t"                                       \
2680         "stw 3,20(1)\n\t"                                        \
2681         /* arg11 */                                              \
2682         "lwz 3,44(11)\n\t"                                       \
2683         "stw 3,16(1)\n\t"                                        \
2684         /* arg10 */                                              \
2685         "lwz 3,40(11)\n\t"                                       \
2686         "stw 3,12(1)\n\t"                                        \
2687         /* arg9 */                                               \
2688         "lwz 3,36(11)\n\t"                                       \
2689         "stw 3,8(1)\n\t"                                         \
2690         /* args1-8 */                                            \
2691         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2692         "lwz 4,8(11)\n\t"                                        \
2693         "lwz 5,12(11)\n\t"                                       \
2694         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2695         "lwz 7,20(11)\n\t"                                       \
2696         "lwz 8,24(11)\n\t"                                       \
2697         "lwz 9,28(11)\n\t"                                       \
2698         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2699         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2700         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2701         VALGRIND_RESTORE_STACK                                   \
2702         "mr %0,3"                                                \
2703         : /*out*/   "=r" (_res)                                  \
2704         : /*in*/    "r" (&_argvec[0])                            \
2705         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2706      );                                                          \
2707      lval = (__typeof__(lval)) _res;                             \
2708   } while (0)
2709
2710#endif /* PLAT_ppc32_linux */
2711
2712/* ------------------------ ppc64-linux ------------------------ */
2713
2714#if defined(PLAT_ppc64be_linux)
2715
2716/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2717
2718/* These regs are trashed by the hidden call. */
2719#define __CALLER_SAVED_REGS                                       \
2720   "lr", "ctr", "xer",                                            \
2721   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
2722   "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",         \
2723   "r11", "r12", "r13"
2724
2725/* Macros to save and align the stack before making a function
2726   call and restore it afterwards as gcc may not keep the stack
2727   pointer aligned if it doesn't realise calls are being made
2728   to other functions. */
2729
2730#define VALGRIND_ALIGN_STACK               \
2731      "mr 28,1\n\t"                        \
2732      "rldicr 1,1,0,59\n\t"
2733#define VALGRIND_RESTORE_STACK             \
2734      "mr 1,28\n\t"
2735
2736/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2737   long) == 8. */
2738
2739#define CALL_FN_W_v(lval, orig)                                   \
2740   do {                                                           \
2741      volatile OrigFn        _orig = (orig);                      \
2742      volatile unsigned long _argvec[3+0];                        \
2743      volatile unsigned long _res;                                \
2744      /* _argvec[0] holds current r2 across the call */           \
2745      _argvec[1] = (unsigned long)_orig.r2;                       \
2746      _argvec[2] = (unsigned long)_orig.nraddr;                   \
2747      __asm__ volatile(                                           \
2748         VALGRIND_ALIGN_STACK                                     \
2749         "mr 11,%1\n\t"                                           \
2750         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2751         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2752         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2753         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2754         "mr 11,%1\n\t"                                           \
2755         "mr %0,3\n\t"                                            \
2756         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2757         VALGRIND_RESTORE_STACK                                   \
2758         : /*out*/   "=r" (_res)                                  \
2759         : /*in*/    "r" (&_argvec[2])                            \
2760         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2761      );                                                          \
2762      lval = (__typeof__(lval)) _res;                             \
2763   } while (0)
2764
2765#define CALL_FN_W_W(lval, orig, arg1)                             \
2766   do {                                                           \
2767      volatile OrigFn        _orig = (orig);                      \
2768      volatile unsigned long _argvec[3+1];                        \
2769      volatile unsigned long _res;                                \
2770      /* _argvec[0] holds current r2 across the call */           \
2771      _argvec[1]   = (unsigned long)_orig.r2;                     \
2772      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2773      _argvec[2+1] = (unsigned long)arg1;                         \
2774      __asm__ volatile(                                           \
2775         VALGRIND_ALIGN_STACK                                     \
2776         "mr 11,%1\n\t"                                           \
2777         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2778         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2779         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2780         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2781         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2782         "mr 11,%1\n\t"                                           \
2783         "mr %0,3\n\t"                                            \
2784         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2785         VALGRIND_RESTORE_STACK                                   \
2786         : /*out*/   "=r" (_res)                                  \
2787         : /*in*/    "r" (&_argvec[2])                            \
2788         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2789      );                                                          \
2790      lval = (__typeof__(lval)) _res;                             \
2791   } while (0)
2792
2793#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
2794   do {                                                           \
2795      volatile OrigFn        _orig = (orig);                      \
2796      volatile unsigned long _argvec[3+2];                        \
2797      volatile unsigned long _res;                                \
2798      /* _argvec[0] holds current r2 across the call */           \
2799      _argvec[1]   = (unsigned long)_orig.r2;                     \
2800      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2801      _argvec[2+1] = (unsigned long)arg1;                         \
2802      _argvec[2+2] = (unsigned long)arg2;                         \
2803      __asm__ volatile(                                           \
2804         VALGRIND_ALIGN_STACK                                     \
2805         "mr 11,%1\n\t"                                           \
2806         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2807         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2808         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2809         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2810         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2811         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2812         "mr 11,%1\n\t"                                           \
2813         "mr %0,3\n\t"                                            \
2814         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2815         VALGRIND_RESTORE_STACK                                   \
2816         : /*out*/   "=r" (_res)                                  \
2817         : /*in*/    "r" (&_argvec[2])                            \
2818         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2819      );                                                          \
2820      lval = (__typeof__(lval)) _res;                             \
2821   } while (0)
2822
2823#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2824   do {                                                           \
2825      volatile OrigFn        _orig = (orig);                      \
2826      volatile unsigned long _argvec[3+3];                        \
2827      volatile unsigned long _res;                                \
2828      /* _argvec[0] holds current r2 across the call */           \
2829      _argvec[1]   = (unsigned long)_orig.r2;                     \
2830      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2831      _argvec[2+1] = (unsigned long)arg1;                         \
2832      _argvec[2+2] = (unsigned long)arg2;                         \
2833      _argvec[2+3] = (unsigned long)arg3;                         \
2834      __asm__ volatile(                                           \
2835         VALGRIND_ALIGN_STACK                                     \
2836         "mr 11,%1\n\t"                                           \
2837         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2838         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2839         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2840         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2841         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2842         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2843         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2844         "mr 11,%1\n\t"                                           \
2845         "mr %0,3\n\t"                                            \
2846         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2847         VALGRIND_RESTORE_STACK                                   \
2848         : /*out*/   "=r" (_res)                                  \
2849         : /*in*/    "r" (&_argvec[2])                            \
2850         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2851      );                                                          \
2852      lval = (__typeof__(lval)) _res;                             \
2853   } while (0)
2854
2855#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2856   do {                                                           \
2857      volatile OrigFn        _orig = (orig);                      \
2858      volatile unsigned long _argvec[3+4];                        \
2859      volatile unsigned long _res;                                \
2860      /* _argvec[0] holds current r2 across the call */           \
2861      _argvec[1]   = (unsigned long)_orig.r2;                     \
2862      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2863      _argvec[2+1] = (unsigned long)arg1;                         \
2864      _argvec[2+2] = (unsigned long)arg2;                         \
2865      _argvec[2+3] = (unsigned long)arg3;                         \
2866      _argvec[2+4] = (unsigned long)arg4;                         \
2867      __asm__ volatile(                                           \
2868         VALGRIND_ALIGN_STACK                                     \
2869         "mr 11,%1\n\t"                                           \
2870         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2871         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2872         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2873         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2874         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2875         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2876         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2877         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2878         "mr 11,%1\n\t"                                           \
2879         "mr %0,3\n\t"                                            \
2880         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2881         VALGRIND_RESTORE_STACK                                   \
2882         : /*out*/   "=r" (_res)                                  \
2883         : /*in*/    "r" (&_argvec[2])                            \
2884         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2885      );                                                          \
2886      lval = (__typeof__(lval)) _res;                             \
2887   } while (0)
2888
2889#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2890   do {                                                           \
2891      volatile OrigFn        _orig = (orig);                      \
2892      volatile unsigned long _argvec[3+5];                        \
2893      volatile unsigned long _res;                                \
2894      /* _argvec[0] holds current r2 across the call */           \
2895      _argvec[1]   = (unsigned long)_orig.r2;                     \
2896      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2897      _argvec[2+1] = (unsigned long)arg1;                         \
2898      _argvec[2+2] = (unsigned long)arg2;                         \
2899      _argvec[2+3] = (unsigned long)arg3;                         \
2900      _argvec[2+4] = (unsigned long)arg4;                         \
2901      _argvec[2+5] = (unsigned long)arg5;                         \
2902      __asm__ volatile(                                           \
2903         VALGRIND_ALIGN_STACK                                     \
2904         "mr 11,%1\n\t"                                           \
2905         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2906         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2907         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2908         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2909         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2910         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2911         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2912         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2913         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2914         "mr 11,%1\n\t"                                           \
2915         "mr %0,3\n\t"                                            \
2916         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2917         VALGRIND_RESTORE_STACK                                   \
2918         : /*out*/   "=r" (_res)                                  \
2919         : /*in*/    "r" (&_argvec[2])                            \
2920         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2921      );                                                          \
2922      lval = (__typeof__(lval)) _res;                             \
2923   } while (0)
2924
2925#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2926   do {                                                           \
2927      volatile OrigFn        _orig = (orig);                      \
2928      volatile unsigned long _argvec[3+6];                        \
2929      volatile unsigned long _res;                                \
2930      /* _argvec[0] holds current r2 across the call */           \
2931      _argvec[1]   = (unsigned long)_orig.r2;                     \
2932      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2933      _argvec[2+1] = (unsigned long)arg1;                         \
2934      _argvec[2+2] = (unsigned long)arg2;                         \
2935      _argvec[2+3] = (unsigned long)arg3;                         \
2936      _argvec[2+4] = (unsigned long)arg4;                         \
2937      _argvec[2+5] = (unsigned long)arg5;                         \
2938      _argvec[2+6] = (unsigned long)arg6;                         \
2939      __asm__ volatile(                                           \
2940         VALGRIND_ALIGN_STACK                                     \
2941         "mr 11,%1\n\t"                                           \
2942         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2943         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2944         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2945         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2946         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2947         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2948         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2949         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2950         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2951         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2952         "mr 11,%1\n\t"                                           \
2953         "mr %0,3\n\t"                                            \
2954         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2955         VALGRIND_RESTORE_STACK                                   \
2956         : /*out*/   "=r" (_res)                                  \
2957         : /*in*/    "r" (&_argvec[2])                            \
2958         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2959      );                                                          \
2960      lval = (__typeof__(lval)) _res;                             \
2961   } while (0)
2962
2963#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2964                                 arg7)                            \
2965   do {                                                           \
2966      volatile OrigFn        _orig = (orig);                      \
2967      volatile unsigned long _argvec[3+7];                        \
2968      volatile unsigned long _res;                                \
2969      /* _argvec[0] holds current r2 across the call */           \
2970      _argvec[1]   = (unsigned long)_orig.r2;                     \
2971      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2972      _argvec[2+1] = (unsigned long)arg1;                         \
2973      _argvec[2+2] = (unsigned long)arg2;                         \
2974      _argvec[2+3] = (unsigned long)arg3;                         \
2975      _argvec[2+4] = (unsigned long)arg4;                         \
2976      _argvec[2+5] = (unsigned long)arg5;                         \
2977      _argvec[2+6] = (unsigned long)arg6;                         \
2978      _argvec[2+7] = (unsigned long)arg7;                         \
2979      __asm__ volatile(                                           \
2980         VALGRIND_ALIGN_STACK                                     \
2981         "mr 11,%1\n\t"                                           \
2982         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2983         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2984         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2985         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2986         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2987         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2988         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2989         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2990         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2991         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2992         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2993         "mr 11,%1\n\t"                                           \
2994         "mr %0,3\n\t"                                            \
2995         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2996         VALGRIND_RESTORE_STACK                                   \
2997         : /*out*/   "=r" (_res)                                  \
2998         : /*in*/    "r" (&_argvec[2])                            \
2999         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3000      );                                                          \
3001      lval = (__typeof__(lval)) _res;                             \
3002   } while (0)
3003
3004#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3005                                 arg7,arg8)                       \
3006   do {                                                           \
3007      volatile OrigFn        _orig = (orig);                      \
3008      volatile unsigned long _argvec[3+8];                        \
3009      volatile unsigned long _res;                                \
3010      /* _argvec[0] holds current r2 across the call */           \
3011      _argvec[1]   = (unsigned long)_orig.r2;                     \
3012      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3013      _argvec[2+1] = (unsigned long)arg1;                         \
3014      _argvec[2+2] = (unsigned long)arg2;                         \
3015      _argvec[2+3] = (unsigned long)arg3;                         \
3016      _argvec[2+4] = (unsigned long)arg4;                         \
3017      _argvec[2+5] = (unsigned long)arg5;                         \
3018      _argvec[2+6] = (unsigned long)arg6;                         \
3019      _argvec[2+7] = (unsigned long)arg7;                         \
3020      _argvec[2+8] = (unsigned long)arg8;                         \
3021      __asm__ volatile(                                           \
3022         VALGRIND_ALIGN_STACK                                     \
3023         "mr 11,%1\n\t"                                           \
3024         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3025         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3026         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3027         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3028         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3029         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3030         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3031         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3032         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3033         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3034         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3035         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3036         "mr 11,%1\n\t"                                           \
3037         "mr %0,3\n\t"                                            \
3038         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3039         VALGRIND_RESTORE_STACK                                   \
3040         : /*out*/   "=r" (_res)                                  \
3041         : /*in*/    "r" (&_argvec[2])                            \
3042         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3043      );                                                          \
3044      lval = (__typeof__(lval)) _res;                             \
3045   } while (0)
3046
3047#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3048                                 arg7,arg8,arg9)                  \
3049   do {                                                           \
3050      volatile OrigFn        _orig = (orig);                      \
3051      volatile unsigned long _argvec[3+9];                        \
3052      volatile unsigned long _res;                                \
3053      /* _argvec[0] holds current r2 across the call */           \
3054      _argvec[1]   = (unsigned long)_orig.r2;                     \
3055      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3056      _argvec[2+1] = (unsigned long)arg1;                         \
3057      _argvec[2+2] = (unsigned long)arg2;                         \
3058      _argvec[2+3] = (unsigned long)arg3;                         \
3059      _argvec[2+4] = (unsigned long)arg4;                         \
3060      _argvec[2+5] = (unsigned long)arg5;                         \
3061      _argvec[2+6] = (unsigned long)arg6;                         \
3062      _argvec[2+7] = (unsigned long)arg7;                         \
3063      _argvec[2+8] = (unsigned long)arg8;                         \
3064      _argvec[2+9] = (unsigned long)arg9;                         \
3065      __asm__ volatile(                                           \
3066         VALGRIND_ALIGN_STACK                                     \
3067         "mr 11,%1\n\t"                                           \
3068         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3069         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3070         "addi 1,1,-128\n\t"  /* expand stack frame */            \
3071         /* arg9 */                                               \
3072         "ld  3,72(11)\n\t"                                       \
3073         "std 3,112(1)\n\t"                                       \
3074         /* args1-8 */                                            \
3075         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3076         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3077         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3078         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3079         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3080         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3081         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3082         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3083         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3084         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3085         "mr 11,%1\n\t"                                           \
3086         "mr %0,3\n\t"                                            \
3087         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3088         VALGRIND_RESTORE_STACK                                   \
3089         : /*out*/   "=r" (_res)                                  \
3090         : /*in*/    "r" (&_argvec[2])                            \
3091         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3092      );                                                          \
3093      lval = (__typeof__(lval)) _res;                             \
3094   } while (0)
3095
3096#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3097                                  arg7,arg8,arg9,arg10)           \
3098   do {                                                           \
3099      volatile OrigFn        _orig = (orig);                      \
3100      volatile unsigned long _argvec[3+10];                       \
3101      volatile unsigned long _res;                                \
3102      /* _argvec[0] holds current r2 across the call */           \
3103      _argvec[1]   = (unsigned long)_orig.r2;                     \
3104      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3105      _argvec[2+1] = (unsigned long)arg1;                         \
3106      _argvec[2+2] = (unsigned long)arg2;                         \
3107      _argvec[2+3] = (unsigned long)arg3;                         \
3108      _argvec[2+4] = (unsigned long)arg4;                         \
3109      _argvec[2+5] = (unsigned long)arg5;                         \
3110      _argvec[2+6] = (unsigned long)arg6;                         \
3111      _argvec[2+7] = (unsigned long)arg7;                         \
3112      _argvec[2+8] = (unsigned long)arg8;                         \
3113      _argvec[2+9] = (unsigned long)arg9;                         \
3114      _argvec[2+10] = (unsigned long)arg10;                       \
3115      __asm__ volatile(                                           \
3116         VALGRIND_ALIGN_STACK                                     \
3117         "mr 11,%1\n\t"                                           \
3118         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3119         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3120         "addi 1,1,-128\n\t"  /* expand stack frame */            \
3121         /* arg10 */                                              \
3122         "ld  3,80(11)\n\t"                                       \
3123         "std 3,120(1)\n\t"                                       \
3124         /* arg9 */                                               \
3125         "ld  3,72(11)\n\t"                                       \
3126         "std 3,112(1)\n\t"                                       \
3127         /* args1-8 */                                            \
3128         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3129         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3130         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3131         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3132         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3133         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3134         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3135         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3136         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3137         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3138         "mr 11,%1\n\t"                                           \
3139         "mr %0,3\n\t"                                            \
3140         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3141         VALGRIND_RESTORE_STACK                                   \
3142         : /*out*/   "=r" (_res)                                  \
3143         : /*in*/    "r" (&_argvec[2])                            \
3144         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3145      );                                                          \
3146      lval = (__typeof__(lval)) _res;                             \
3147   } while (0)
3148
3149#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3150                                  arg7,arg8,arg9,arg10,arg11)     \
3151   do {                                                           \
3152      volatile OrigFn        _orig = (orig);                      \
3153      volatile unsigned long _argvec[3+11];                       \
3154      volatile unsigned long _res;                                \
3155      /* _argvec[0] holds current r2 across the call */           \
3156      _argvec[1]   = (unsigned long)_orig.r2;                     \
3157      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3158      _argvec[2+1] = (unsigned long)arg1;                         \
3159      _argvec[2+2] = (unsigned long)arg2;                         \
3160      _argvec[2+3] = (unsigned long)arg3;                         \
3161      _argvec[2+4] = (unsigned long)arg4;                         \
3162      _argvec[2+5] = (unsigned long)arg5;                         \
3163      _argvec[2+6] = (unsigned long)arg6;                         \
3164      _argvec[2+7] = (unsigned long)arg7;                         \
3165      _argvec[2+8] = (unsigned long)arg8;                         \
3166      _argvec[2+9] = (unsigned long)arg9;                         \
3167      _argvec[2+10] = (unsigned long)arg10;                       \
3168      _argvec[2+11] = (unsigned long)arg11;                       \
3169      __asm__ volatile(                                           \
3170         VALGRIND_ALIGN_STACK                                     \
3171         "mr 11,%1\n\t"                                           \
3172         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3173         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3174         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3175         /* arg11 */                                              \
3176         "ld  3,88(11)\n\t"                                       \
3177         "std 3,128(1)\n\t"                                       \
3178         /* arg10 */                                              \
3179         "ld  3,80(11)\n\t"                                       \
3180         "std 3,120(1)\n\t"                                       \
3181         /* arg9 */                                               \
3182         "ld  3,72(11)\n\t"                                       \
3183         "std 3,112(1)\n\t"                                       \
3184         /* args1-8 */                                            \
3185         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3186         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3187         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3188         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3189         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3190         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3191         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3192         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3193         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3194         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3195         "mr 11,%1\n\t"                                           \
3196         "mr %0,3\n\t"                                            \
3197         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3198         VALGRIND_RESTORE_STACK                                   \
3199         : /*out*/   "=r" (_res)                                  \
3200         : /*in*/    "r" (&_argvec[2])                            \
3201         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3202      );                                                          \
3203      lval = (__typeof__(lval)) _res;                             \
3204   } while (0)
3205
3206#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3207                                arg7,arg8,arg9,arg10,arg11,arg12) \
3208   do {                                                           \
3209      volatile OrigFn        _orig = (orig);                      \
3210      volatile unsigned long _argvec[3+12];                       \
3211      volatile unsigned long _res;                                \
3212      /* _argvec[0] holds current r2 across the call */           \
3213      _argvec[1]   = (unsigned long)_orig.r2;                     \
3214      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3215      _argvec[2+1] = (unsigned long)arg1;                         \
3216      _argvec[2+2] = (unsigned long)arg2;                         \
3217      _argvec[2+3] = (unsigned long)arg3;                         \
3218      _argvec[2+4] = (unsigned long)arg4;                         \
3219      _argvec[2+5] = (unsigned long)arg5;                         \
3220      _argvec[2+6] = (unsigned long)arg6;                         \
3221      _argvec[2+7] = (unsigned long)arg7;                         \
3222      _argvec[2+8] = (unsigned long)arg8;                         \
3223      _argvec[2+9] = (unsigned long)arg9;                         \
3224      _argvec[2+10] = (unsigned long)arg10;                       \
3225      _argvec[2+11] = (unsigned long)arg11;                       \
3226      _argvec[2+12] = (unsigned long)arg12;                       \
3227      __asm__ volatile(                                           \
3228         VALGRIND_ALIGN_STACK                                     \
3229         "mr 11,%1\n\t"                                           \
3230         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3231         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3232         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3233         /* arg12 */                                              \
3234         "ld  3,96(11)\n\t"                                       \
3235         "std 3,136(1)\n\t"                                       \
3236         /* arg11 */                                              \
3237         "ld  3,88(11)\n\t"                                       \
3238         "std 3,128(1)\n\t"                                       \
3239         /* arg10 */                                              \
3240         "ld  3,80(11)\n\t"                                       \
3241         "std 3,120(1)\n\t"                                       \
3242         /* arg9 */                                               \
3243         "ld  3,72(11)\n\t"                                       \
3244         "std 3,112(1)\n\t"                                       \
3245         /* args1-8 */                                            \
3246         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3247         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3248         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3249         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3250         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3251         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3252         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3253         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3254         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3255         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3256         "mr 11,%1\n\t"                                           \
3257         "mr %0,3\n\t"                                            \
3258         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3259         VALGRIND_RESTORE_STACK                                   \
3260         : /*out*/   "=r" (_res)                                  \
3261         : /*in*/    "r" (&_argvec[2])                            \
3262         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3263      );                                                          \
3264      lval = (__typeof__(lval)) _res;                             \
3265   } while (0)
3266
3267#endif /* PLAT_ppc64be_linux */
3268
3269/* ------------------------- ppc64le-linux ----------------------- */
3270#if defined(PLAT_ppc64le_linux)
3271
3272/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3273
3274/* These regs are trashed by the hidden call. */
3275#define __CALLER_SAVED_REGS                                       \
3276   "lr", "ctr", "xer",                                            \
3277   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
3278   "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",         \
3279   "r11", "r12", "r13"
3280
3281/* Macros to save and align the stack before making a function
3282   call and restore it afterwards as gcc may not keep the stack
3283   pointer aligned if it doesn't realise calls are being made
3284   to other functions. */
3285
3286#define VALGRIND_ALIGN_STACK               \
3287      "mr 28,1\n\t"                        \
3288      "rldicr 1,1,0,59\n\t"
3289#define VALGRIND_RESTORE_STACK             \
3290      "mr 1,28\n\t"
3291
3292/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
3293   long) == 8. */
3294
3295#define CALL_FN_W_v(lval, orig)                                   \
3296   do {                                                           \
3297      volatile OrigFn        _orig = (orig);                      \
3298      volatile unsigned long _argvec[3+0];                        \
3299      volatile unsigned long _res;                                \
3300      /* _argvec[0] holds current r2 across the call */           \
3301      _argvec[1] = (unsigned long)_orig.r2;                       \
3302      _argvec[2] = (unsigned long)_orig.nraddr;                   \
3303      __asm__ volatile(                                           \
3304         VALGRIND_ALIGN_STACK                                     \
3305         "mr 12,%1\n\t"                                           \
3306         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3307         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3308         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3309         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3310         "mr 12,%1\n\t"                                           \
3311         "mr %0,3\n\t"                                            \
3312         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3313         VALGRIND_RESTORE_STACK                                   \
3314         : /*out*/   "=r" (_res)                                  \
3315         : /*in*/    "r" (&_argvec[2])                            \
3316         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3317      );                                                          \
3318      lval = (__typeof__(lval)) _res;                             \
3319   } while (0)
3320
3321#define CALL_FN_W_W(lval, orig, arg1)                             \
3322   do {                                                           \
3323      volatile OrigFn        _orig = (orig);                      \
3324      volatile unsigned long _argvec[3+1];                        \
3325      volatile unsigned long _res;                                \
3326      /* _argvec[0] holds current r2 across the call */           \
3327      _argvec[1]   = (unsigned long)_orig.r2;                     \
3328      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3329      _argvec[2+1] = (unsigned long)arg1;                         \
3330      __asm__ volatile(                                           \
3331         VALGRIND_ALIGN_STACK                                     \
3332         "mr 12,%1\n\t"                                           \
3333         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3334         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3335         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3336         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3337         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3338         "mr 12,%1\n\t"                                           \
3339         "mr %0,3\n\t"                                            \
3340         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3341         VALGRIND_RESTORE_STACK                                   \
3342         : /*out*/   "=r" (_res)                                  \
3343         : /*in*/    "r" (&_argvec[2])                            \
3344         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3345      );                                                          \
3346      lval = (__typeof__(lval)) _res;                             \
3347   } while (0)
3348
3349#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
3350   do {                                                           \
3351      volatile OrigFn        _orig = (orig);                      \
3352      volatile unsigned long _argvec[3+2];                        \
3353      volatile unsigned long _res;                                \
3354      /* _argvec[0] holds current r2 across the call */           \
3355      _argvec[1]   = (unsigned long)_orig.r2;                     \
3356      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3357      _argvec[2+1] = (unsigned long)arg1;                         \
3358      _argvec[2+2] = (unsigned long)arg2;                         \
3359      __asm__ volatile(                                           \
3360         VALGRIND_ALIGN_STACK                                     \
3361         "mr 12,%1\n\t"                                           \
3362         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3363         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3364         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3365         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3366         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3367         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3368         "mr 12,%1\n\t"                                           \
3369         "mr %0,3\n\t"                                            \
3370         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3371         VALGRIND_RESTORE_STACK                                   \
3372         : /*out*/   "=r" (_res)                                  \
3373         : /*in*/    "r" (&_argvec[2])                            \
3374         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3375      );                                                          \
3376      lval = (__typeof__(lval)) _res;                             \
3377   } while (0)
3378
3379#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
3380   do {                                                           \
3381      volatile OrigFn        _orig = (orig);                      \
3382      volatile unsigned long _argvec[3+3];                        \
3383      volatile unsigned long _res;                                \
3384      /* _argvec[0] holds current r2 across the call */           \
3385      _argvec[1]   = (unsigned long)_orig.r2;                     \
3386      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3387      _argvec[2+1] = (unsigned long)arg1;                         \
3388      _argvec[2+2] = (unsigned long)arg2;                         \
3389      _argvec[2+3] = (unsigned long)arg3;                         \
3390      __asm__ volatile(                                           \
3391         VALGRIND_ALIGN_STACK                                     \
3392         "mr 12,%1\n\t"                                           \
3393         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3394         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3395         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3396         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3397         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3398         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3399         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3400         "mr 12,%1\n\t"                                           \
3401         "mr %0,3\n\t"                                            \
3402         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3403         VALGRIND_RESTORE_STACK                                   \
3404         : /*out*/   "=r" (_res)                                  \
3405         : /*in*/    "r" (&_argvec[2])                            \
3406         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3407      );                                                          \
3408      lval = (__typeof__(lval)) _res;                             \
3409   } while (0)
3410
3411#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
3412   do {                                                           \
3413      volatile OrigFn        _orig = (orig);                      \
3414      volatile unsigned long _argvec[3+4];                        \
3415      volatile unsigned long _res;                                \
3416      /* _argvec[0] holds current r2 across the call */           \
3417      _argvec[1]   = (unsigned long)_orig.r2;                     \
3418      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3419      _argvec[2+1] = (unsigned long)arg1;                         \
3420      _argvec[2+2] = (unsigned long)arg2;                         \
3421      _argvec[2+3] = (unsigned long)arg3;                         \
3422      _argvec[2+4] = (unsigned long)arg4;                         \
3423      __asm__ volatile(                                           \
3424         VALGRIND_ALIGN_STACK                                     \
3425         "mr 12,%1\n\t"                                           \
3426         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3427         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3428         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3429         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3430         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3431         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3432         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3433         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3434         "mr 12,%1\n\t"                                           \
3435         "mr %0,3\n\t"                                            \
3436         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3437         VALGRIND_RESTORE_STACK                                   \
3438         : /*out*/   "=r" (_res)                                  \
3439         : /*in*/    "r" (&_argvec[2])                            \
3440         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3441      );                                                          \
3442      lval = (__typeof__(lval)) _res;                             \
3443   } while (0)
3444
3445#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
3446   do {                                                           \
3447      volatile OrigFn        _orig = (orig);                      \
3448      volatile unsigned long _argvec[3+5];                        \
3449      volatile unsigned long _res;                                \
3450      /* _argvec[0] holds current r2 across the call */           \
3451      _argvec[1]   = (unsigned long)_orig.r2;                     \
3452      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3453      _argvec[2+1] = (unsigned long)arg1;                         \
3454      _argvec[2+2] = (unsigned long)arg2;                         \
3455      _argvec[2+3] = (unsigned long)arg3;                         \
3456      _argvec[2+4] = (unsigned long)arg4;                         \
3457      _argvec[2+5] = (unsigned long)arg5;                         \
3458      __asm__ volatile(                                           \
3459         VALGRIND_ALIGN_STACK                                     \
3460         "mr 12,%1\n\t"                                           \
3461         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3462         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3463         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3464         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3465         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3466         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3467         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3468         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3469         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3470         "mr 12,%1\n\t"                                           \
3471         "mr %0,3\n\t"                                            \
3472         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3473         VALGRIND_RESTORE_STACK                                   \
3474         : /*out*/   "=r" (_res)                                  \
3475         : /*in*/    "r" (&_argvec[2])                            \
3476         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3477      );                                                          \
3478      lval = (__typeof__(lval)) _res;                             \
3479   } while (0)
3480
3481#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
3482   do {                                                           \
3483      volatile OrigFn        _orig = (orig);                      \
3484      volatile unsigned long _argvec[3+6];                        \
3485      volatile unsigned long _res;                                \
3486      /* _argvec[0] holds current r2 across the call */           \
3487      _argvec[1]   = (unsigned long)_orig.r2;                     \
3488      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3489      _argvec[2+1] = (unsigned long)arg1;                         \
3490      _argvec[2+2] = (unsigned long)arg2;                         \
3491      _argvec[2+3] = (unsigned long)arg3;                         \
3492      _argvec[2+4] = (unsigned long)arg4;                         \
3493      _argvec[2+5] = (unsigned long)arg5;                         \
3494      _argvec[2+6] = (unsigned long)arg6;                         \
3495      __asm__ volatile(                                           \
3496         VALGRIND_ALIGN_STACK                                     \
3497         "mr 12,%1\n\t"                                           \
3498         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3499         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3500         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3501         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3502         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3503         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3504         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3505         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3506         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3507         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3508         "mr 12,%1\n\t"                                           \
3509         "mr %0,3\n\t"                                            \
3510         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3511         VALGRIND_RESTORE_STACK                                   \
3512         : /*out*/   "=r" (_res)                                  \
3513         : /*in*/    "r" (&_argvec[2])                            \
3514         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3515      );                                                          \
3516      lval = (__typeof__(lval)) _res;                             \
3517   } while (0)
3518
3519#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3520                                 arg7)                            \
3521   do {                                                           \
3522      volatile OrigFn        _orig = (orig);                      \
3523      volatile unsigned long _argvec[3+7];                        \
3524      volatile unsigned long _res;                                \
3525      /* _argvec[0] holds current r2 across the call */           \
3526      _argvec[1]   = (unsigned long)_orig.r2;                     \
3527      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3528      _argvec[2+1] = (unsigned long)arg1;                         \
3529      _argvec[2+2] = (unsigned long)arg2;                         \
3530      _argvec[2+3] = (unsigned long)arg3;                         \
3531      _argvec[2+4] = (unsigned long)arg4;                         \
3532      _argvec[2+5] = (unsigned long)arg5;                         \
3533      _argvec[2+6] = (unsigned long)arg6;                         \
3534      _argvec[2+7] = (unsigned long)arg7;                         \
3535      __asm__ volatile(                                           \
3536         VALGRIND_ALIGN_STACK                                     \
3537         "mr 12,%1\n\t"                                           \
3538         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3539         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3540         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3541         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3542         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3543         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3544         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3545         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3546         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3547         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3548         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3549         "mr 12,%1\n\t"                                           \
3550         "mr %0,3\n\t"                                            \
3551         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3552         VALGRIND_RESTORE_STACK                                   \
3553         : /*out*/   "=r" (_res)                                  \
3554         : /*in*/    "r" (&_argvec[2])                            \
3555         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3556      );                                                          \
3557      lval = (__typeof__(lval)) _res;                             \
3558   } while (0)
3559
3560#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3561                                 arg7,arg8)                       \
3562   do {                                                           \
3563      volatile OrigFn        _orig = (orig);                      \
3564      volatile unsigned long _argvec[3+8];                        \
3565      volatile unsigned long _res;                                \
3566      /* _argvec[0] holds current r2 across the call */           \
3567      _argvec[1]   = (unsigned long)_orig.r2;                     \
3568      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3569      _argvec[2+1] = (unsigned long)arg1;                         \
3570      _argvec[2+2] = (unsigned long)arg2;                         \
3571      _argvec[2+3] = (unsigned long)arg3;                         \
3572      _argvec[2+4] = (unsigned long)arg4;                         \
3573      _argvec[2+5] = (unsigned long)arg5;                         \
3574      _argvec[2+6] = (unsigned long)arg6;                         \
3575      _argvec[2+7] = (unsigned long)arg7;                         \
3576      _argvec[2+8] = (unsigned long)arg8;                         \
3577      __asm__ volatile(                                           \
3578         VALGRIND_ALIGN_STACK                                     \
3579         "mr 12,%1\n\t"                                           \
3580         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3581         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3582         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3583         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3584         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3585         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3586         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3587         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3588         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3589         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3590         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3591         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3592         "mr 12,%1\n\t"                                           \
3593         "mr %0,3\n\t"                                            \
3594         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3595         VALGRIND_RESTORE_STACK                                   \
3596         : /*out*/   "=r" (_res)                                  \
3597         : /*in*/    "r" (&_argvec[2])                            \
3598         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3599      );                                                          \
3600      lval = (__typeof__(lval)) _res;                             \
3601   } while (0)
3602
3603#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3604                                 arg7,arg8,arg9)                  \
3605   do {                                                           \
3606      volatile OrigFn        _orig = (orig);                      \
3607      volatile unsigned long _argvec[3+9];                        \
3608      volatile unsigned long _res;                                \
3609      /* _argvec[0] holds current r2 across the call */           \
3610      _argvec[1]   = (unsigned long)_orig.r2;                     \
3611      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3612      _argvec[2+1] = (unsigned long)arg1;                         \
3613      _argvec[2+2] = (unsigned long)arg2;                         \
3614      _argvec[2+3] = (unsigned long)arg3;                         \
3615      _argvec[2+4] = (unsigned long)arg4;                         \
3616      _argvec[2+5] = (unsigned long)arg5;                         \
3617      _argvec[2+6] = (unsigned long)arg6;                         \
3618      _argvec[2+7] = (unsigned long)arg7;                         \
3619      _argvec[2+8] = (unsigned long)arg8;                         \
3620      _argvec[2+9] = (unsigned long)arg9;                         \
3621      __asm__ volatile(                                           \
3622         VALGRIND_ALIGN_STACK                                     \
3623         "mr 12,%1\n\t"                                           \
3624         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3625         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3626         "addi 1,1,-128\n\t"  /* expand stack frame */            \
3627         /* arg9 */                                               \
3628         "ld  3,72(12)\n\t"                                       \
3629         "std 3,96(1)\n\t"                                        \
3630         /* args1-8 */                                            \
3631         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3632         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3633         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3634         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3635         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3636         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3637         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3638         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3639         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3640         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3641         "mr 12,%1\n\t"                                           \
3642         "mr %0,3\n\t"                                            \
3643         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3644         VALGRIND_RESTORE_STACK                                   \
3645         : /*out*/   "=r" (_res)                                  \
3646         : /*in*/    "r" (&_argvec[2])                            \
3647         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3648      );                                                          \
3649      lval = (__typeof__(lval)) _res;                             \
3650   } while (0)
3651
3652#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3653                                  arg7,arg8,arg9,arg10)           \
3654   do {                                                           \
3655      volatile OrigFn        _orig = (orig);                      \
3656      volatile unsigned long _argvec[3+10];                       \
3657      volatile unsigned long _res;                                \
3658      /* _argvec[0] holds current r2 across the call */           \
3659      _argvec[1]   = (unsigned long)_orig.r2;                     \
3660      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3661      _argvec[2+1] = (unsigned long)arg1;                         \
3662      _argvec[2+2] = (unsigned long)arg2;                         \
3663      _argvec[2+3] = (unsigned long)arg3;                         \
3664      _argvec[2+4] = (unsigned long)arg4;                         \
3665      _argvec[2+5] = (unsigned long)arg5;                         \
3666      _argvec[2+6] = (unsigned long)arg6;                         \
3667      _argvec[2+7] = (unsigned long)arg7;                         \
3668      _argvec[2+8] = (unsigned long)arg8;                         \
3669      _argvec[2+9] = (unsigned long)arg9;                         \
3670      _argvec[2+10] = (unsigned long)arg10;                       \
3671      __asm__ volatile(                                           \
3672         VALGRIND_ALIGN_STACK                                     \
3673         "mr 12,%1\n\t"                                           \
3674         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3675         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3676         "addi 1,1,-128\n\t"  /* expand stack frame */            \
3677         /* arg10 */                                              \
3678         "ld  3,80(12)\n\t"                                       \
3679         "std 3,104(1)\n\t"                                       \
3680         /* arg9 */                                               \
3681         "ld  3,72(12)\n\t"                                       \
3682         "std 3,96(1)\n\t"                                        \
3683         /* args1-8 */                                            \
3684         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3685         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3686         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3687         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3688         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3689         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3690         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3691         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3692         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3693         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3694         "mr 12,%1\n\t"                                           \
3695         "mr %0,3\n\t"                                            \
3696         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3697         VALGRIND_RESTORE_STACK                                   \
3698         : /*out*/   "=r" (_res)                                  \
3699         : /*in*/    "r" (&_argvec[2])                            \
3700         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3701      );                                                          \
3702      lval = (__typeof__(lval)) _res;                             \
3703   } while (0)
3704
3705#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3706                                  arg7,arg8,arg9,arg10,arg11)     \
3707   do {                                                           \
3708      volatile OrigFn        _orig = (orig);                      \
3709      volatile unsigned long _argvec[3+11];                       \
3710      volatile unsigned long _res;                                \
3711      /* _argvec[0] holds current r2 across the call */           \
3712      _argvec[1]   = (unsigned long)_orig.r2;                     \
3713      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3714      _argvec[2+1] = (unsigned long)arg1;                         \
3715      _argvec[2+2] = (unsigned long)arg2;                         \
3716      _argvec[2+3] = (unsigned long)arg3;                         \
3717      _argvec[2+4] = (unsigned long)arg4;                         \
3718      _argvec[2+5] = (unsigned long)arg5;                         \
3719      _argvec[2+6] = (unsigned long)arg6;                         \
3720      _argvec[2+7] = (unsigned long)arg7;                         \
3721      _argvec[2+8] = (unsigned long)arg8;                         \
3722      _argvec[2+9] = (unsigned long)arg9;                         \
3723      _argvec[2+10] = (unsigned long)arg10;                       \
3724      _argvec[2+11] = (unsigned long)arg11;                       \
3725      __asm__ volatile(                                           \
3726         VALGRIND_ALIGN_STACK                                     \
3727         "mr 12,%1\n\t"                                           \
3728         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3729         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3730         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3731         /* arg11 */                                              \
3732         "ld  3,88(12)\n\t"                                       \
3733         "std 3,112(1)\n\t"                                       \
3734         /* arg10 */                                              \
3735         "ld  3,80(12)\n\t"                                       \
3736         "std 3,104(1)\n\t"                                       \
3737         /* arg9 */                                               \
3738         "ld  3,72(12)\n\t"                                       \
3739         "std 3,96(1)\n\t"                                        \
3740         /* args1-8 */                                            \
3741         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3742         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3743         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3744         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3745         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3746         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3747         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3748         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3749         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3750         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3751         "mr 12,%1\n\t"                                           \
3752         "mr %0,3\n\t"                                            \
3753         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3754         VALGRIND_RESTORE_STACK                                   \
3755         : /*out*/   "=r" (_res)                                  \
3756         : /*in*/    "r" (&_argvec[2])                            \
3757         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3758      );                                                          \
3759      lval = (__typeof__(lval)) _res;                             \
3760   } while (0)
3761
3762#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3763                                arg7,arg8,arg9,arg10,arg11,arg12) \
3764   do {                                                           \
3765      volatile OrigFn        _orig = (orig);                      \
3766      volatile unsigned long _argvec[3+12];                       \
3767      volatile unsigned long _res;                                \
3768      /* _argvec[0] holds current r2 across the call */           \
3769      _argvec[1]   = (unsigned long)_orig.r2;                     \
3770      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3771      _argvec[2+1] = (unsigned long)arg1;                         \
3772      _argvec[2+2] = (unsigned long)arg2;                         \
3773      _argvec[2+3] = (unsigned long)arg3;                         \
3774      _argvec[2+4] = (unsigned long)arg4;                         \
3775      _argvec[2+5] = (unsigned long)arg5;                         \
3776      _argvec[2+6] = (unsigned long)arg6;                         \
3777      _argvec[2+7] = (unsigned long)arg7;                         \
3778      _argvec[2+8] = (unsigned long)arg8;                         \
3779      _argvec[2+9] = (unsigned long)arg9;                         \
3780      _argvec[2+10] = (unsigned long)arg10;                       \
3781      _argvec[2+11] = (unsigned long)arg11;                       \
3782      _argvec[2+12] = (unsigned long)arg12;                       \
3783      __asm__ volatile(                                           \
3784         VALGRIND_ALIGN_STACK                                     \
3785         "mr 12,%1\n\t"                                           \
3786         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3787         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3788         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3789         /* arg12 */                                              \
3790         "ld  3,96(12)\n\t"                                       \
3791         "std 3,120(1)\n\t"                                       \
3792         /* arg11 */                                              \
3793         "ld  3,88(12)\n\t"                                       \
3794         "std 3,112(1)\n\t"                                       \
3795         /* arg10 */                                              \
3796         "ld  3,80(12)\n\t"                                       \
3797         "std 3,104(1)\n\t"                                       \
3798         /* arg9 */                                               \
3799         "ld  3,72(12)\n\t"                                       \
3800         "std 3,96(1)\n\t"                                        \
3801         /* args1-8 */                                            \
3802         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3803         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3804         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3805         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3806         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3807         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3808         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3809         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3810         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3811         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3812         "mr 12,%1\n\t"                                           \
3813         "mr %0,3\n\t"                                            \
3814         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3815         VALGRIND_RESTORE_STACK                                   \
3816         : /*out*/   "=r" (_res)                                  \
3817         : /*in*/    "r" (&_argvec[2])                            \
3818         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3819      );                                                          \
3820      lval = (__typeof__(lval)) _res;                             \
3821   } while (0)
3822
3823#endif /* PLAT_ppc64le_linux */
3824
3825/* ------------------------- arm-linux ------------------------- */
3826
3827#if defined(PLAT_arm_linux)
3828
3829/* These regs are trashed by the hidden call. */
3830#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4", "r12", "r14"
3831
3832/* Macros to save and align the stack before making a function
3833   call and restore it afterwards as gcc may not keep the stack
3834   pointer aligned if it doesn't realise calls are being made
3835   to other functions. */
3836
3837/* This is a bit tricky.  We store the original stack pointer in r10
3838   as it is callee-saves.  gcc doesn't allow the use of r11 for some
3839   reason.  Also, we can't directly "bic" the stack pointer in thumb
3840   mode since r13 isn't an allowed register number in that context.
3841   So use r4 as a temporary, since that is about to get trashed
3842   anyway, just after each use of this macro.  Side effect is we need
3843   to be very careful about any future changes, since
3844   VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
3845#define VALGRIND_ALIGN_STACK               \
3846      "mov r10, sp\n\t"                    \
3847      "mov r4,  sp\n\t"                    \
3848      "bic r4,  r4, #7\n\t"                \
3849      "mov sp,  r4\n\t"
3850#define VALGRIND_RESTORE_STACK             \
3851      "mov sp,  r10\n\t"
3852
3853/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3854   long) == 4. */
3855
3856#define CALL_FN_W_v(lval, orig)                                   \
3857   do {                                                           \
3858      volatile OrigFn        _orig = (orig);                      \
3859      volatile unsigned long _argvec[1];                          \
3860      volatile unsigned long _res;                                \
3861      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3862      __asm__ volatile(                                           \
3863         VALGRIND_ALIGN_STACK                                     \
3864         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3865         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3866         VALGRIND_RESTORE_STACK                                   \
3867         "mov %0, r0\n"                                           \
3868         : /*out*/   "=r" (_res)                                  \
3869         : /*in*/    "0" (&_argvec[0])                            \
3870         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3871      );                                                          \
3872      lval = (__typeof__(lval)) _res;                             \
3873   } while (0)
3874
3875#define CALL_FN_W_W(lval, orig, arg1)                             \
3876   do {                                                           \
3877      volatile OrigFn        _orig = (orig);                      \
3878      volatile unsigned long _argvec[2];                          \
3879      volatile unsigned long _res;                                \
3880      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3881      _argvec[1] = (unsigned long)(arg1);                         \
3882      __asm__ volatile(                                           \
3883         VALGRIND_ALIGN_STACK                                     \
3884         "ldr r0, [%1, #4] \n\t"                                  \
3885         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3886         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3887         VALGRIND_RESTORE_STACK                                   \
3888         "mov %0, r0\n"                                           \
3889         : /*out*/   "=r" (_res)                                  \
3890         : /*in*/    "0" (&_argvec[0])                            \
3891         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3892      );                                                          \
3893      lval = (__typeof__(lval)) _res;                             \
3894   } while (0)
3895
3896#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
3897   do {                                                           \
3898      volatile OrigFn        _orig = (orig);                      \
3899      volatile unsigned long _argvec[3];                          \
3900      volatile unsigned long _res;                                \
3901      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3902      _argvec[1] = (unsigned long)(arg1);                         \
3903      _argvec[2] = (unsigned long)(arg2);                         \
3904      __asm__ volatile(                                           \
3905         VALGRIND_ALIGN_STACK                                     \
3906         "ldr r0, [%1, #4] \n\t"                                  \
3907         "ldr r1, [%1, #8] \n\t"                                  \
3908         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3909         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3910         VALGRIND_RESTORE_STACK                                   \
3911         "mov %0, r0\n"                                           \
3912         : /*out*/   "=r" (_res)                                  \
3913         : /*in*/    "0" (&_argvec[0])                            \
3914         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3915      );                                                          \
3916      lval = (__typeof__(lval)) _res;                             \
3917   } while (0)
3918
3919#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
3920   do {                                                           \
3921      volatile OrigFn        _orig = (orig);                      \
3922      volatile unsigned long _argvec[4];                          \
3923      volatile unsigned long _res;                                \
3924      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3925      _argvec[1] = (unsigned long)(arg1);                         \
3926      _argvec[2] = (unsigned long)(arg2);                         \
3927      _argvec[3] = (unsigned long)(arg3);                         \
3928      __asm__ volatile(                                           \
3929         VALGRIND_ALIGN_STACK                                     \
3930         "ldr r0, [%1, #4] \n\t"                                  \
3931         "ldr r1, [%1, #8] \n\t"                                  \
3932         "ldr r2, [%1, #12] \n\t"                                 \
3933         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3934         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3935         VALGRIND_RESTORE_STACK                                   \
3936         "mov %0, r0\n"                                           \
3937         : /*out*/   "=r" (_res)                                  \
3938         : /*in*/    "0" (&_argvec[0])                            \
3939         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3940      );                                                          \
3941      lval = (__typeof__(lval)) _res;                             \
3942   } while (0)
3943
3944#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
3945   do {                                                           \
3946      volatile OrigFn        _orig = (orig);                      \
3947      volatile unsigned long _argvec[5];                          \
3948      volatile unsigned long _res;                                \
3949      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3950      _argvec[1] = (unsigned long)(arg1);                         \
3951      _argvec[2] = (unsigned long)(arg2);                         \
3952      _argvec[3] = (unsigned long)(arg3);                         \
3953      _argvec[4] = (unsigned long)(arg4);                         \
3954      __asm__ volatile(                                           \
3955         VALGRIND_ALIGN_STACK                                     \
3956         "ldr r0, [%1, #4] \n\t"                                  \
3957         "ldr r1, [%1, #8] \n\t"                                  \
3958         "ldr r2, [%1, #12] \n\t"                                 \
3959         "ldr r3, [%1, #16] \n\t"                                 \
3960         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3961         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3962         VALGRIND_RESTORE_STACK                                   \
3963         "mov %0, r0"                                             \
3964         : /*out*/   "=r" (_res)                                  \
3965         : /*in*/    "0" (&_argvec[0])                            \
3966         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3967      );                                                          \
3968      lval = (__typeof__(lval)) _res;                             \
3969   } while (0)
3970
3971#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
3972   do {                                                           \
3973      volatile OrigFn        _orig = (orig);                      \
3974      volatile unsigned long _argvec[6];                          \
3975      volatile unsigned long _res;                                \
3976      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3977      _argvec[1] = (unsigned long)(arg1);                         \
3978      _argvec[2] = (unsigned long)(arg2);                         \
3979      _argvec[3] = (unsigned long)(arg3);                         \
3980      _argvec[4] = (unsigned long)(arg4);                         \
3981      _argvec[5] = (unsigned long)(arg5);                         \
3982      __asm__ volatile(                                           \
3983         VALGRIND_ALIGN_STACK                                     \
3984         "sub sp, sp, #4 \n\t"                                    \
3985         "ldr r0, [%1, #20] \n\t"                                 \
3986         "push {r0} \n\t"                                         \
3987         "ldr r0, [%1, #4] \n\t"                                  \
3988         "ldr r1, [%1, #8] \n\t"                                  \
3989         "ldr r2, [%1, #12] \n\t"                                 \
3990         "ldr r3, [%1, #16] \n\t"                                 \
3991         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3992         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3993         VALGRIND_RESTORE_STACK                                   \
3994         "mov %0, r0"                                             \
3995         : /*out*/   "=r" (_res)                                  \
3996         : /*in*/    "0" (&_argvec[0])                            \
3997         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3998      );                                                          \
3999      lval = (__typeof__(lval)) _res;                             \
4000   } while (0)
4001
4002#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
4003   do {                                                           \
4004      volatile OrigFn        _orig = (orig);                      \
4005      volatile unsigned long _argvec[7];                          \
4006      volatile unsigned long _res;                                \
4007      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4008      _argvec[1] = (unsigned long)(arg1);                         \
4009      _argvec[2] = (unsigned long)(arg2);                         \
4010      _argvec[3] = (unsigned long)(arg3);                         \
4011      _argvec[4] = (unsigned long)(arg4);                         \
4012      _argvec[5] = (unsigned long)(arg5);                         \
4013      _argvec[6] = (unsigned long)(arg6);                         \
4014      __asm__ volatile(                                           \
4015         VALGRIND_ALIGN_STACK                                     \
4016         "ldr r0, [%1, #20] \n\t"                                 \
4017         "ldr r1, [%1, #24] \n\t"                                 \
4018         "push {r0, r1} \n\t"                                     \
4019         "ldr r0, [%1, #4] \n\t"                                  \
4020         "ldr r1, [%1, #8] \n\t"                                  \
4021         "ldr r2, [%1, #12] \n\t"                                 \
4022         "ldr r3, [%1, #16] \n\t"                                 \
4023         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4024         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4025         VALGRIND_RESTORE_STACK                                   \
4026         "mov %0, r0"                                             \
4027         : /*out*/   "=r" (_res)                                  \
4028         : /*in*/    "0" (&_argvec[0])                            \
4029         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4030      );                                                          \
4031      lval = (__typeof__(lval)) _res;                             \
4032   } while (0)
4033
4034#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4035                                 arg7)                            \
4036   do {                                                           \
4037      volatile OrigFn        _orig = (orig);                      \
4038      volatile unsigned long _argvec[8];                          \
4039      volatile unsigned long _res;                                \
4040      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4041      _argvec[1] = (unsigned long)(arg1);                         \
4042      _argvec[2] = (unsigned long)(arg2);                         \
4043      _argvec[3] = (unsigned long)(arg3);                         \
4044      _argvec[4] = (unsigned long)(arg4);                         \
4045      _argvec[5] = (unsigned long)(arg5);                         \
4046      _argvec[6] = (unsigned long)(arg6);                         \
4047      _argvec[7] = (unsigned long)(arg7);                         \
4048      __asm__ volatile(                                           \
4049         VALGRIND_ALIGN_STACK                                     \
4050         "sub sp, sp, #4 \n\t"                                    \
4051         "ldr r0, [%1, #20] \n\t"                                 \
4052         "ldr r1, [%1, #24] \n\t"                                 \
4053         "ldr r2, [%1, #28] \n\t"                                 \
4054         "push {r0, r1, r2} \n\t"                                 \
4055         "ldr r0, [%1, #4] \n\t"                                  \
4056         "ldr r1, [%1, #8] \n\t"                                  \
4057         "ldr r2, [%1, #12] \n\t"                                 \
4058         "ldr r3, [%1, #16] \n\t"                                 \
4059         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4060         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4061         VALGRIND_RESTORE_STACK                                   \
4062         "mov %0, r0"                                             \
4063         : /*out*/   "=r" (_res)                                  \
4064         : /*in*/    "0" (&_argvec[0])                            \
4065         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4066      );                                                          \
4067      lval = (__typeof__(lval)) _res;                             \
4068   } while (0)
4069
4070#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4071                                 arg7,arg8)                       \
4072   do {                                                           \
4073      volatile OrigFn        _orig = (orig);                      \
4074      volatile unsigned long _argvec[9];                          \
4075      volatile unsigned long _res;                                \
4076      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4077      _argvec[1] = (unsigned long)(arg1);                         \
4078      _argvec[2] = (unsigned long)(arg2);                         \
4079      _argvec[3] = (unsigned long)(arg3);                         \
4080      _argvec[4] = (unsigned long)(arg4);                         \
4081      _argvec[5] = (unsigned long)(arg5);                         \
4082      _argvec[6] = (unsigned long)(arg6);                         \
4083      _argvec[7] = (unsigned long)(arg7);                         \
4084      _argvec[8] = (unsigned long)(arg8);                         \
4085      __asm__ volatile(                                           \
4086         VALGRIND_ALIGN_STACK                                     \
4087         "ldr r0, [%1, #20] \n\t"                                 \
4088         "ldr r1, [%1, #24] \n\t"                                 \
4089         "ldr r2, [%1, #28] \n\t"                                 \
4090         "ldr r3, [%1, #32] \n\t"                                 \
4091         "push {r0, r1, r2, r3} \n\t"                             \
4092         "ldr r0, [%1, #4] \n\t"                                  \
4093         "ldr r1, [%1, #8] \n\t"                                  \
4094         "ldr r2, [%1, #12] \n\t"                                 \
4095         "ldr r3, [%1, #16] \n\t"                                 \
4096         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4097         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4098         VALGRIND_RESTORE_STACK                                   \
4099         "mov %0, r0"                                             \
4100         : /*out*/   "=r" (_res)                                  \
4101         : /*in*/    "0" (&_argvec[0])                            \
4102         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4103      );                                                          \
4104      lval = (__typeof__(lval)) _res;                             \
4105   } while (0)
4106
4107#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4108                                 arg7,arg8,arg9)                  \
4109   do {                                                           \
4110      volatile OrigFn        _orig = (orig);                      \
4111      volatile unsigned long _argvec[10];                         \
4112      volatile unsigned long _res;                                \
4113      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4114      _argvec[1] = (unsigned long)(arg1);                         \
4115      _argvec[2] = (unsigned long)(arg2);                         \
4116      _argvec[3] = (unsigned long)(arg3);                         \
4117      _argvec[4] = (unsigned long)(arg4);                         \
4118      _argvec[5] = (unsigned long)(arg5);                         \
4119      _argvec[6] = (unsigned long)(arg6);                         \
4120      _argvec[7] = (unsigned long)(arg7);                         \
4121      _argvec[8] = (unsigned long)(arg8);                         \
4122      _argvec[9] = (unsigned long)(arg9);                         \
4123      __asm__ volatile(                                           \
4124         VALGRIND_ALIGN_STACK                                     \
4125         "sub sp, sp, #4 \n\t"                                    \
4126         "ldr r0, [%1, #20] \n\t"                                 \
4127         "ldr r1, [%1, #24] \n\t"                                 \
4128         "ldr r2, [%1, #28] \n\t"                                 \
4129         "ldr r3, [%1, #32] \n\t"                                 \
4130         "ldr r4, [%1, #36] \n\t"                                 \
4131         "push {r0, r1, r2, r3, r4} \n\t"                         \
4132         "ldr r0, [%1, #4] \n\t"                                  \
4133         "ldr r1, [%1, #8] \n\t"                                  \
4134         "ldr r2, [%1, #12] \n\t"                                 \
4135         "ldr r3, [%1, #16] \n\t"                                 \
4136         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4137         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4138         VALGRIND_RESTORE_STACK                                   \
4139         "mov %0, r0"                                             \
4140         : /*out*/   "=r" (_res)                                  \
4141         : /*in*/    "0" (&_argvec[0])                            \
4142         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4143      );                                                          \
4144      lval = (__typeof__(lval)) _res;                             \
4145   } while (0)
4146
4147#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4148                                  arg7,arg8,arg9,arg10)           \
4149   do {                                                           \
4150      volatile OrigFn        _orig = (orig);                      \
4151      volatile unsigned long _argvec[11];                         \
4152      volatile unsigned long _res;                                \
4153      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4154      _argvec[1] = (unsigned long)(arg1);                         \
4155      _argvec[2] = (unsigned long)(arg2);                         \
4156      _argvec[3] = (unsigned long)(arg3);                         \
4157      _argvec[4] = (unsigned long)(arg4);                         \
4158      _argvec[5] = (unsigned long)(arg5);                         \
4159      _argvec[6] = (unsigned long)(arg6);                         \
4160      _argvec[7] = (unsigned long)(arg7);                         \
4161      _argvec[8] = (unsigned long)(arg8);                         \
4162      _argvec[9] = (unsigned long)(arg9);                         \
4163      _argvec[10] = (unsigned long)(arg10);                       \
4164      __asm__ volatile(                                           \
4165         VALGRIND_ALIGN_STACK                                     \
4166         "ldr r0, [%1, #40] \n\t"                                 \
4167         "push {r0} \n\t"                                         \
4168         "ldr r0, [%1, #20] \n\t"                                 \
4169         "ldr r1, [%1, #24] \n\t"                                 \
4170         "ldr r2, [%1, #28] \n\t"                                 \
4171         "ldr r3, [%1, #32] \n\t"                                 \
4172         "ldr r4, [%1, #36] \n\t"                                 \
4173         "push {r0, r1, r2, r3, r4} \n\t"                         \
4174         "ldr r0, [%1, #4] \n\t"                                  \
4175         "ldr r1, [%1, #8] \n\t"                                  \
4176         "ldr r2, [%1, #12] \n\t"                                 \
4177         "ldr r3, [%1, #16] \n\t"                                 \
4178         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4179         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4180         VALGRIND_RESTORE_STACK                                   \
4181         "mov %0, r0"                                             \
4182         : /*out*/   "=r" (_res)                                  \
4183         : /*in*/    "0" (&_argvec[0])                            \
4184         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4185      );                                                          \
4186      lval = (__typeof__(lval)) _res;                             \
4187   } while (0)
4188
4189#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
4190                                  arg6,arg7,arg8,arg9,arg10,      \
4191                                  arg11)                          \
4192   do {                                                           \
4193      volatile OrigFn        _orig = (orig);                      \
4194      volatile unsigned long _argvec[12];                         \
4195      volatile unsigned long _res;                                \
4196      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4197      _argvec[1] = (unsigned long)(arg1);                         \
4198      _argvec[2] = (unsigned long)(arg2);                         \
4199      _argvec[3] = (unsigned long)(arg3);                         \
4200      _argvec[4] = (unsigned long)(arg4);                         \
4201      _argvec[5] = (unsigned long)(arg5);                         \
4202      _argvec[6] = (unsigned long)(arg6);                         \
4203      _argvec[7] = (unsigned long)(arg7);                         \
4204      _argvec[8] = (unsigned long)(arg8);                         \
4205      _argvec[9] = (unsigned long)(arg9);                         \
4206      _argvec[10] = (unsigned long)(arg10);                       \
4207      _argvec[11] = (unsigned long)(arg11);                       \
4208      __asm__ volatile(                                           \
4209         VALGRIND_ALIGN_STACK                                     \
4210         "sub sp, sp, #4 \n\t"                                    \
4211         "ldr r0, [%1, #40] \n\t"                                 \
4212         "ldr r1, [%1, #44] \n\t"                                 \
4213         "push {r0, r1} \n\t"                                     \
4214         "ldr r0, [%1, #20] \n\t"                                 \
4215         "ldr r1, [%1, #24] \n\t"                                 \
4216         "ldr r2, [%1, #28] \n\t"                                 \
4217         "ldr r3, [%1, #32] \n\t"                                 \
4218         "ldr r4, [%1, #36] \n\t"                                 \
4219         "push {r0, r1, r2, r3, r4} \n\t"                         \
4220         "ldr r0, [%1, #4] \n\t"                                  \
4221         "ldr r1, [%1, #8] \n\t"                                  \
4222         "ldr r2, [%1, #12] \n\t"                                 \
4223         "ldr r3, [%1, #16] \n\t"                                 \
4224         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4225         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4226         VALGRIND_RESTORE_STACK                                   \
4227         "mov %0, r0"                                             \
4228         : /*out*/   "=r" (_res)                                  \
4229         : /*in*/    "0" (&_argvec[0])                            \
4230         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4231      );                                                          \
4232      lval = (__typeof__(lval)) _res;                             \
4233   } while (0)
4234
4235#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
4236                                  arg6,arg7,arg8,arg9,arg10,      \
4237                                  arg11,arg12)                    \
4238   do {                                                           \
4239      volatile OrigFn        _orig = (orig);                      \
4240      volatile unsigned long _argvec[13];                         \
4241      volatile unsigned long _res;                                \
4242      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4243      _argvec[1] = (unsigned long)(arg1);                         \
4244      _argvec[2] = (unsigned long)(arg2);                         \
4245      _argvec[3] = (unsigned long)(arg3);                         \
4246      _argvec[4] = (unsigned long)(arg4);                         \
4247      _argvec[5] = (unsigned long)(arg5);                         \
4248      _argvec[6] = (unsigned long)(arg6);                         \
4249      _argvec[7] = (unsigned long)(arg7);                         \
4250      _argvec[8] = (unsigned long)(arg8);                         \
4251      _argvec[9] = (unsigned long)(arg9);                         \
4252      _argvec[10] = (unsigned long)(arg10);                       \
4253      _argvec[11] = (unsigned long)(arg11);                       \
4254      _argvec[12] = (unsigned long)(arg12);                       \
4255      __asm__ volatile(                                           \
4256         VALGRIND_ALIGN_STACK                                     \
4257         "ldr r0, [%1, #40] \n\t"                                 \
4258         "ldr r1, [%1, #44] \n\t"                                 \
4259         "ldr r2, [%1, #48] \n\t"                                 \
4260         "push {r0, r1, r2} \n\t"                                 \
4261         "ldr r0, [%1, #20] \n\t"                                 \
4262         "ldr r1, [%1, #24] \n\t"                                 \
4263         "ldr r2, [%1, #28] \n\t"                                 \
4264         "ldr r3, [%1, #32] \n\t"                                 \
4265         "ldr r4, [%1, #36] \n\t"                                 \
4266         "push {r0, r1, r2, r3, r4} \n\t"                         \
4267         "ldr r0, [%1, #4] \n\t"                                  \
4268         "ldr r1, [%1, #8] \n\t"                                  \
4269         "ldr r2, [%1, #12] \n\t"                                 \
4270         "ldr r3, [%1, #16] \n\t"                                 \
4271         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4272         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4273         VALGRIND_RESTORE_STACK                                   \
4274         "mov %0, r0"                                             \
4275         : /*out*/   "=r" (_res)                                  \
4276         : /*in*/    "0" (&_argvec[0])                            \
4277         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4278      );                                                          \
4279      lval = (__typeof__(lval)) _res;                             \
4280   } while (0)
4281
4282#endif /* PLAT_arm_linux */
4283
4284/* ------------------------ arm64-linux ------------------------ */
4285
4286#if defined(PLAT_arm64_linux)
4287
4288/* These regs are trashed by the hidden call. */
4289#define __CALLER_SAVED_REGS \
4290     "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9",   \
4291     "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17",      \
4292     "x18", "x19", "x20", "x30",                                  \
4293     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",  \
4294     "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17",      \
4295     "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25",      \
4296     "v26", "v27", "v28", "v29", "v30", "v31"
4297
4298/* x21 is callee-saved, so we can use it to save and restore SP around
4299   the hidden call. */
4300#define VALGRIND_ALIGN_STACK               \
4301      "mov x21, sp\n\t"                    \
4302      "bic sp, x21, #15\n\t"
4303#define VALGRIND_RESTORE_STACK             \
4304      "mov sp,  x21\n\t"
4305
4306/* These CALL_FN_ macros assume that on arm64-linux,
4307   sizeof(unsigned long) == 8. */
4308
4309#define CALL_FN_W_v(lval, orig)                                   \
4310   do {                                                           \
4311      volatile OrigFn        _orig = (orig);                      \
4312      volatile unsigned long _argvec[1];                          \
4313      volatile unsigned long _res;                                \
4314      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4315      __asm__ volatile(                                           \
4316         VALGRIND_ALIGN_STACK                                     \
4317         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4318         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4319         VALGRIND_RESTORE_STACK                                   \
4320         "mov %0, x0\n"                                           \
4321         : /*out*/   "=r" (_res)                                  \
4322         : /*in*/    "0" (&_argvec[0])                            \
4323         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4324      );                                                          \
4325      lval = (__typeof__(lval)) _res;                             \
4326   } while (0)
4327
4328#define CALL_FN_W_W(lval, orig, arg1)                             \
4329   do {                                                           \
4330      volatile OrigFn        _orig = (orig);                      \
4331      volatile unsigned long _argvec[2];                          \
4332      volatile unsigned long _res;                                \
4333      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4334      _argvec[1] = (unsigned long)(arg1);                         \
4335      __asm__ volatile(                                           \
4336         VALGRIND_ALIGN_STACK                                     \
4337         "ldr x0, [%1, #8] \n\t"                                  \
4338         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4339         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4340         VALGRIND_RESTORE_STACK                                   \
4341         "mov %0, x0\n"                                           \
4342         : /*out*/   "=r" (_res)                                  \
4343         : /*in*/    "0" (&_argvec[0])                            \
4344         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4345      );                                                          \
4346      lval = (__typeof__(lval)) _res;                             \
4347   } while (0)
4348
4349#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
4350   do {                                                           \
4351      volatile OrigFn        _orig = (orig);                      \
4352      volatile unsigned long _argvec[3];                          \
4353      volatile unsigned long _res;                                \
4354      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4355      _argvec[1] = (unsigned long)(arg1);                         \
4356      _argvec[2] = (unsigned long)(arg2);                         \
4357      __asm__ volatile(                                           \
4358         VALGRIND_ALIGN_STACK                                     \
4359         "ldr x0, [%1, #8] \n\t"                                  \
4360         "ldr x1, [%1, #16] \n\t"                                 \
4361         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4362         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4363         VALGRIND_RESTORE_STACK                                   \
4364         "mov %0, x0\n"                                           \
4365         : /*out*/   "=r" (_res)                                  \
4366         : /*in*/    "0" (&_argvec[0])                            \
4367         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4368      );                                                          \
4369      lval = (__typeof__(lval)) _res;                             \
4370   } while (0)
4371
4372#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
4373   do {                                                           \
4374      volatile OrigFn        _orig = (orig);                      \
4375      volatile unsigned long _argvec[4];                          \
4376      volatile unsigned long _res;                                \
4377      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4378      _argvec[1] = (unsigned long)(arg1);                         \
4379      _argvec[2] = (unsigned long)(arg2);                         \
4380      _argvec[3] = (unsigned long)(arg3);                         \
4381      __asm__ volatile(                                           \
4382         VALGRIND_ALIGN_STACK                                     \
4383         "ldr x0, [%1, #8] \n\t"                                  \
4384         "ldr x1, [%1, #16] \n\t"                                 \
4385         "ldr x2, [%1, #24] \n\t"                                 \
4386         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4387         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4388         VALGRIND_RESTORE_STACK                                   \
4389         "mov %0, x0\n"                                           \
4390         : /*out*/   "=r" (_res)                                  \
4391         : /*in*/    "0" (&_argvec[0])                            \
4392         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4393      );                                                          \
4394      lval = (__typeof__(lval)) _res;                             \
4395   } while (0)
4396
4397#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
4398   do {                                                           \
4399      volatile OrigFn        _orig = (orig);                      \
4400      volatile unsigned long _argvec[5];                          \
4401      volatile unsigned long _res;                                \
4402      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4403      _argvec[1] = (unsigned long)(arg1);                         \
4404      _argvec[2] = (unsigned long)(arg2);                         \
4405      _argvec[3] = (unsigned long)(arg3);                         \
4406      _argvec[4] = (unsigned long)(arg4);                         \
4407      __asm__ volatile(                                           \
4408         VALGRIND_ALIGN_STACK                                     \
4409         "ldr x0, [%1, #8] \n\t"                                  \
4410         "ldr x1, [%1, #16] \n\t"                                 \
4411         "ldr x2, [%1, #24] \n\t"                                 \
4412         "ldr x3, [%1, #32] \n\t"                                 \
4413         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4414         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4415         VALGRIND_RESTORE_STACK                                   \
4416         "mov %0, x0"                                             \
4417         : /*out*/   "=r" (_res)                                  \
4418         : /*in*/    "0" (&_argvec[0])                            \
4419         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4420      );                                                          \
4421      lval = (__typeof__(lval)) _res;                             \
4422   } while (0)
4423
4424#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
4425   do {                                                           \
4426      volatile OrigFn        _orig = (orig);                      \
4427      volatile unsigned long _argvec[6];                          \
4428      volatile unsigned long _res;                                \
4429      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4430      _argvec[1] = (unsigned long)(arg1);                         \
4431      _argvec[2] = (unsigned long)(arg2);                         \
4432      _argvec[3] = (unsigned long)(arg3);                         \
4433      _argvec[4] = (unsigned long)(arg4);                         \
4434      _argvec[5] = (unsigned long)(arg5);                         \
4435      __asm__ volatile(                                           \
4436         VALGRIND_ALIGN_STACK                                     \
4437         "ldr x0, [%1, #8] \n\t"                                  \
4438         "ldr x1, [%1, #16] \n\t"                                 \
4439         "ldr x2, [%1, #24] \n\t"                                 \
4440         "ldr x3, [%1, #32] \n\t"                                 \
4441         "ldr x4, [%1, #40] \n\t"                                 \
4442         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4443         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4444         VALGRIND_RESTORE_STACK                                   \
4445         "mov %0, x0"                                             \
4446         : /*out*/   "=r" (_res)                                  \
4447         : /*in*/    "0" (&_argvec[0])                            \
4448         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4449      );                                                          \
4450      lval = (__typeof__(lval)) _res;                             \
4451   } while (0)
4452
4453#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
4454   do {                                                           \
4455      volatile OrigFn        _orig = (orig);                      \
4456      volatile unsigned long _argvec[7];                          \
4457      volatile unsigned long _res;                                \
4458      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4459      _argvec[1] = (unsigned long)(arg1);                         \
4460      _argvec[2] = (unsigned long)(arg2);                         \
4461      _argvec[3] = (unsigned long)(arg3);                         \
4462      _argvec[4] = (unsigned long)(arg4);                         \
4463      _argvec[5] = (unsigned long)(arg5);                         \
4464      _argvec[6] = (unsigned long)(arg6);                         \
4465      __asm__ volatile(                                           \
4466         VALGRIND_ALIGN_STACK                                     \
4467         "ldr x0, [%1, #8] \n\t"                                  \
4468         "ldr x1, [%1, #16] \n\t"                                 \
4469         "ldr x2, [%1, #24] \n\t"                                 \
4470         "ldr x3, [%1, #32] \n\t"                                 \
4471         "ldr x4, [%1, #40] \n\t"                                 \
4472         "ldr x5, [%1, #48] \n\t"                                 \
4473         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4474         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4475         VALGRIND_RESTORE_STACK                                   \
4476         "mov %0, x0"                                             \
4477         : /*out*/   "=r" (_res)                                  \
4478         : /*in*/    "0" (&_argvec[0])                            \
4479         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4480      );                                                          \
4481      lval = (__typeof__(lval)) _res;                             \
4482   } while (0)
4483
4484#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4485                                 arg7)                            \
4486   do {                                                           \
4487      volatile OrigFn        _orig = (orig);                      \
4488      volatile unsigned long _argvec[8];                          \
4489      volatile unsigned long _res;                                \
4490      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4491      _argvec[1] = (unsigned long)(arg1);                         \
4492      _argvec[2] = (unsigned long)(arg2);                         \
4493      _argvec[3] = (unsigned long)(arg3);                         \
4494      _argvec[4] = (unsigned long)(arg4);                         \
4495      _argvec[5] = (unsigned long)(arg5);                         \
4496      _argvec[6] = (unsigned long)(arg6);                         \
4497      _argvec[7] = (unsigned long)(arg7);                         \
4498      __asm__ volatile(                                           \
4499         VALGRIND_ALIGN_STACK                                     \
4500         "ldr x0, [%1, #8] \n\t"                                  \
4501         "ldr x1, [%1, #16] \n\t"                                 \
4502         "ldr x2, [%1, #24] \n\t"                                 \
4503         "ldr x3, [%1, #32] \n\t"                                 \
4504         "ldr x4, [%1, #40] \n\t"                                 \
4505         "ldr x5, [%1, #48] \n\t"                                 \
4506         "ldr x6, [%1, #56] \n\t"                                 \
4507         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4508         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4509         VALGRIND_RESTORE_STACK                                   \
4510         "mov %0, x0"                                             \
4511         : /*out*/   "=r" (_res)                                  \
4512         : /*in*/    "0" (&_argvec[0])                            \
4513         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4514      );                                                          \
4515      lval = (__typeof__(lval)) _res;                             \
4516   } while (0)
4517
4518#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4519                                 arg7,arg8)                       \
4520   do {                                                           \
4521      volatile OrigFn        _orig = (orig);                      \
4522      volatile unsigned long _argvec[9];                          \
4523      volatile unsigned long _res;                                \
4524      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4525      _argvec[1] = (unsigned long)(arg1);                         \
4526      _argvec[2] = (unsigned long)(arg2);                         \
4527      _argvec[3] = (unsigned long)(arg3);                         \
4528      _argvec[4] = (unsigned long)(arg4);                         \
4529      _argvec[5] = (unsigned long)(arg5);                         \
4530      _argvec[6] = (unsigned long)(arg6);                         \
4531      _argvec[7] = (unsigned long)(arg7);                         \
4532      _argvec[8] = (unsigned long)(arg8);                         \
4533      __asm__ volatile(                                           \
4534         VALGRIND_ALIGN_STACK                                     \
4535         "ldr x0, [%1, #8] \n\t"                                  \
4536         "ldr x1, [%1, #16] \n\t"                                 \
4537         "ldr x2, [%1, #24] \n\t"                                 \
4538         "ldr x3, [%1, #32] \n\t"                                 \
4539         "ldr x4, [%1, #40] \n\t"                                 \
4540         "ldr x5, [%1, #48] \n\t"                                 \
4541         "ldr x6, [%1, #56] \n\t"                                 \
4542         "ldr x7, [%1, #64] \n\t"                                 \
4543         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4544         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4545         VALGRIND_RESTORE_STACK                                   \
4546         "mov %0, x0"                                             \
4547         : /*out*/   "=r" (_res)                                  \
4548         : /*in*/    "0" (&_argvec[0])                            \
4549         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4550      );                                                          \
4551      lval = (__typeof__(lval)) _res;                             \
4552   } while (0)
4553
4554#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4555                                 arg7,arg8,arg9)                  \
4556   do {                                                           \
4557      volatile OrigFn        _orig = (orig);                      \
4558      volatile unsigned long _argvec[10];                         \
4559      volatile unsigned long _res;                                \
4560      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4561      _argvec[1] = (unsigned long)(arg1);                         \
4562      _argvec[2] = (unsigned long)(arg2);                         \
4563      _argvec[3] = (unsigned long)(arg3);                         \
4564      _argvec[4] = (unsigned long)(arg4);                         \
4565      _argvec[5] = (unsigned long)(arg5);                         \
4566      _argvec[6] = (unsigned long)(arg6);                         \
4567      _argvec[7] = (unsigned long)(arg7);                         \
4568      _argvec[8] = (unsigned long)(arg8);                         \
4569      _argvec[9] = (unsigned long)(arg9);                         \
4570      __asm__ volatile(                                           \
4571         VALGRIND_ALIGN_STACK                                     \
4572         "sub sp, sp, #0x20 \n\t"                                 \
4573         "ldr x0, [%1, #8] \n\t"                                  \
4574         "ldr x1, [%1, #16] \n\t"                                 \
4575         "ldr x2, [%1, #24] \n\t"                                 \
4576         "ldr x3, [%1, #32] \n\t"                                 \
4577         "ldr x4, [%1, #40] \n\t"                                 \
4578         "ldr x5, [%1, #48] \n\t"                                 \
4579         "ldr x6, [%1, #56] \n\t"                                 \
4580         "ldr x7, [%1, #64] \n\t"                                 \
4581         "ldr x8, [%1, #72] \n\t"                                 \
4582         "str x8, [sp, #0]  \n\t"                                 \
4583         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4584         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4585         VALGRIND_RESTORE_STACK                                   \
4586         "mov %0, x0"                                             \
4587         : /*out*/   "=r" (_res)                                  \
4588         : /*in*/    "0" (&_argvec[0])                            \
4589         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4590      );                                                          \
4591      lval = (__typeof__(lval)) _res;                             \
4592   } while (0)
4593
4594#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4595                                  arg7,arg8,arg9,arg10)           \
4596   do {                                                           \
4597      volatile OrigFn        _orig = (orig);                      \
4598      volatile unsigned long _argvec[11];                         \
4599      volatile unsigned long _res;                                \
4600      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4601      _argvec[1] = (unsigned long)(arg1);                         \
4602      _argvec[2] = (unsigned long)(arg2);                         \
4603      _argvec[3] = (unsigned long)(arg3);                         \
4604      _argvec[4] = (unsigned long)(arg4);                         \
4605      _argvec[5] = (unsigned long)(arg5);                         \
4606      _argvec[6] = (unsigned long)(arg6);                         \
4607      _argvec[7] = (unsigned long)(arg7);                         \
4608      _argvec[8] = (unsigned long)(arg8);                         \
4609      _argvec[9] = (unsigned long)(arg9);                         \
4610      _argvec[10] = (unsigned long)(arg10);                       \
4611      __asm__ volatile(                                           \
4612         VALGRIND_ALIGN_STACK                                     \
4613         "sub sp, sp, #0x20 \n\t"                                 \
4614         "ldr x0, [%1, #8] \n\t"                                  \
4615         "ldr x1, [%1, #16] \n\t"                                 \
4616         "ldr x2, [%1, #24] \n\t"                                 \
4617         "ldr x3, [%1, #32] \n\t"                                 \
4618         "ldr x4, [%1, #40] \n\t"                                 \
4619         "ldr x5, [%1, #48] \n\t"                                 \
4620         "ldr x6, [%1, #56] \n\t"                                 \
4621         "ldr x7, [%1, #64] \n\t"                                 \
4622         "ldr x8, [%1, #72] \n\t"                                 \
4623         "str x8, [sp, #0]  \n\t"                                 \
4624         "ldr x8, [%1, #80] \n\t"                                 \
4625         "str x8, [sp, #8]  \n\t"                                 \
4626         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4627         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4628         VALGRIND_RESTORE_STACK                                   \
4629         "mov %0, x0"                                             \
4630         : /*out*/   "=r" (_res)                                  \
4631         : /*in*/    "0" (&_argvec[0])                            \
4632         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4633      );                                                          \
4634      lval = (__typeof__(lval)) _res;                             \
4635   } while (0)
4636
4637#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4638                                  arg7,arg8,arg9,arg10,arg11)     \
4639   do {                                                           \
4640      volatile OrigFn        _orig = (orig);                      \
4641      volatile unsigned long _argvec[12];                         \
4642      volatile unsigned long _res;                                \
4643      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4644      _argvec[1] = (unsigned long)(arg1);                         \
4645      _argvec[2] = (unsigned long)(arg2);                         \
4646      _argvec[3] = (unsigned long)(arg3);                         \
4647      _argvec[4] = (unsigned long)(arg4);                         \
4648      _argvec[5] = (unsigned long)(arg5);                         \
4649      _argvec[6] = (unsigned long)(arg6);                         \
4650      _argvec[7] = (unsigned long)(arg7);                         \
4651      _argvec[8] = (unsigned long)(arg8);                         \
4652      _argvec[9] = (unsigned long)(arg9);                         \
4653      _argvec[10] = (unsigned long)(arg10);                       \
4654      _argvec[11] = (unsigned long)(arg11);                       \
4655      __asm__ volatile(                                           \
4656         VALGRIND_ALIGN_STACK                                     \
4657         "sub sp, sp, #0x30 \n\t"                                 \
4658         "ldr x0, [%1, #8] \n\t"                                  \
4659         "ldr x1, [%1, #16] \n\t"                                 \
4660         "ldr x2, [%1, #24] \n\t"                                 \
4661         "ldr x3, [%1, #32] \n\t"                                 \
4662         "ldr x4, [%1, #40] \n\t"                                 \
4663         "ldr x5, [%1, #48] \n\t"                                 \
4664         "ldr x6, [%1, #56] \n\t"                                 \
4665         "ldr x7, [%1, #64] \n\t"                                 \
4666         "ldr x8, [%1, #72] \n\t"                                 \
4667         "str x8, [sp, #0]  \n\t"                                 \
4668         "ldr x8, [%1, #80] \n\t"                                 \
4669         "str x8, [sp, #8]  \n\t"                                 \
4670         "ldr x8, [%1, #88] \n\t"                                 \
4671         "str x8, [sp, #16] \n\t"                                 \
4672         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4673         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4674         VALGRIND_RESTORE_STACK                                   \
4675         "mov %0, x0"                                             \
4676         : /*out*/   "=r" (_res)                                  \
4677         : /*in*/    "0" (&_argvec[0])                            \
4678         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4679      );                                                          \
4680      lval = (__typeof__(lval)) _res;                             \
4681   } while (0)
4682
4683#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4684                                  arg7,arg8,arg9,arg10,arg11,     \
4685                                  arg12)                          \
4686   do {                                                           \
4687      volatile OrigFn        _orig = (orig);                      \
4688      volatile unsigned long _argvec[13];                         \
4689      volatile unsigned long _res;                                \
4690      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4691      _argvec[1] = (unsigned long)(arg1);                         \
4692      _argvec[2] = (unsigned long)(arg2);                         \
4693      _argvec[3] = (unsigned long)(arg3);                         \
4694      _argvec[4] = (unsigned long)(arg4);                         \
4695      _argvec[5] = (unsigned long)(arg5);                         \
4696      _argvec[6] = (unsigned long)(arg6);                         \
4697      _argvec[7] = (unsigned long)(arg7);                         \
4698      _argvec[8] = (unsigned long)(arg8);                         \
4699      _argvec[9] = (unsigned long)(arg9);                         \
4700      _argvec[10] = (unsigned long)(arg10);                       \
4701      _argvec[11] = (unsigned long)(arg11);                       \
4702      _argvec[12] = (unsigned long)(arg12);                       \
4703      __asm__ volatile(                                           \
4704         VALGRIND_ALIGN_STACK                                     \
4705         "sub sp, sp, #0x30 \n\t"                                 \
4706         "ldr x0, [%1, #8] \n\t"                                  \
4707         "ldr x1, [%1, #16] \n\t"                                 \
4708         "ldr x2, [%1, #24] \n\t"                                 \
4709         "ldr x3, [%1, #32] \n\t"                                 \
4710         "ldr x4, [%1, #40] \n\t"                                 \
4711         "ldr x5, [%1, #48] \n\t"                                 \
4712         "ldr x6, [%1, #56] \n\t"                                 \
4713         "ldr x7, [%1, #64] \n\t"                                 \
4714         "ldr x8, [%1, #72] \n\t"                                 \
4715         "str x8, [sp, #0]  \n\t"                                 \
4716         "ldr x8, [%1, #80] \n\t"                                 \
4717         "str x8, [sp, #8]  \n\t"                                 \
4718         "ldr x8, [%1, #88] \n\t"                                 \
4719         "str x8, [sp, #16] \n\t"                                 \
4720         "ldr x8, [%1, #96] \n\t"                                 \
4721         "str x8, [sp, #24] \n\t"                                 \
4722         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4723         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4724         VALGRIND_RESTORE_STACK                                   \
4725         "mov %0, x0"                                             \
4726         : /*out*/   "=r" (_res)                                  \
4727         : /*in*/    "0" (&_argvec[0])                            \
4728         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4729      );                                                          \
4730      lval = (__typeof__(lval)) _res;                             \
4731   } while (0)
4732
4733#endif /* PLAT_arm64_linux */
4734
4735/* ------------------------- s390x-linux ------------------------- */
4736
4737#if defined(PLAT_s390x_linux)
4738
4739/* Similar workaround as amd64 (see above), but we use r11 as frame
4740   pointer and save the old r11 in r7. r11 might be used for
4741   argvec, therefore we copy argvec in r1 since r1 is clobbered
4742   after the call anyway.  */
4743#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4744#  define __FRAME_POINTER                                         \
4745      ,"d"(__builtin_dwarf_cfa())
4746#  define VALGRIND_CFI_PROLOGUE                                   \
4747      ".cfi_remember_state\n\t"                                   \
4748      "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */          \
4749      "lgr 7,11\n\t"                                              \
4750      "lgr 11,%2\n\t"                                             \
4751      ".cfi_def_cfa r11, 0\n\t"
4752#  define VALGRIND_CFI_EPILOGUE                                   \
4753      "lgr 11, 7\n\t"                                             \
4754      ".cfi_restore_state\n\t"
4755#else
4756#  define __FRAME_POINTER
4757#  define VALGRIND_CFI_PROLOGUE                                   \
4758      "lgr 1,%1\n\t"
4759#  define VALGRIND_CFI_EPILOGUE
4760#endif
4761
4762/* Nb: On s390 the stack pointer is properly aligned *at all times*
4763   according to the s390 GCC maintainer. (The ABI specification is not
4764   precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4765   VALGRIND_RESTORE_STACK are not defined here. */
4766
4767/* These regs are trashed by the hidden call. Note that we overwrite
4768   r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4769   function a proper return address. All others are ABI defined call
4770   clobbers. */
4771#if defined(__VX__) || defined(__S390_VX__)
4772#define __CALLER_SAVED_REGS "0", "1", "2", "3", "4", "5", "14",   \
4773      "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",             \
4774      "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",       \
4775      "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",     \
4776      "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
4777#else
4778#define __CALLER_SAVED_REGS "0", "1", "2", "3", "4", "5", "14",   \
4779      "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7"
4780#endif
4781
4782/* Nb: Although r11 is modified in the asm snippets below (inside
4783   VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4784   two reasons:
4785   (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4786       modified
4787   (2) GCC will complain that r11 cannot appear inside a clobber section,
4788       when compiled with -O -fno-omit-frame-pointer
4789 */
4790
4791#define CALL_FN_W_v(lval, orig)                                  \
4792   do {                                                          \
4793      volatile OrigFn        _orig = (orig);                     \
4794      volatile unsigned long  _argvec[1];                        \
4795      volatile unsigned long _res;                               \
4796      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4797      __asm__ volatile(                                          \
4798         VALGRIND_CFI_PROLOGUE                                   \
4799         "aghi 15,-160\n\t"                                      \
4800         "lg 1, 0(1)\n\t"  /* target->r1 */                      \
4801         VALGRIND_CALL_NOREDIR_R1                                \
4802         "aghi 15,160\n\t"                                       \
4803         VALGRIND_CFI_EPILOGUE                                   \
4804         "lgr %0, 2\n\t"                                         \
4805         : /*out*/   "=d" (_res)                                 \
4806         : /*in*/    "d" (&_argvec[0]) __FRAME_POINTER           \
4807         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4808      );                                                         \
4809      lval = (__typeof__(lval)) _res;                            \
4810   } while (0)
4811
4812/* The call abi has the arguments in r2-r6 and stack */
4813#define CALL_FN_W_W(lval, orig, arg1)                            \
4814   do {                                                          \
4815      volatile OrigFn        _orig = (orig);                     \
4816      volatile unsigned long _argvec[2];                         \
4817      volatile unsigned long _res;                               \
4818      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4819      _argvec[1] = (unsigned long)arg1;                          \
4820      __asm__ volatile(                                          \
4821         VALGRIND_CFI_PROLOGUE                                   \
4822         "aghi 15,-160\n\t"                                      \
4823         "lg 2, 8(1)\n\t"                                        \
4824         "lg 1, 0(1)\n\t"                                        \
4825         VALGRIND_CALL_NOREDIR_R1                                \
4826         "aghi 15,160\n\t"                                       \
4827         VALGRIND_CFI_EPILOGUE                                   \
4828         "lgr %0, 2\n\t"                                         \
4829         : /*out*/   "=d" (_res)                                 \
4830         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4831         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4832      );                                                         \
4833      lval = (__typeof__(lval)) _res;                            \
4834   } while (0)
4835
4836#define CALL_FN_W_WW(lval, orig, arg1, arg2)                     \
4837   do {                                                          \
4838      volatile OrigFn        _orig = (orig);                     \
4839      volatile unsigned long _argvec[3];                         \
4840      volatile unsigned long _res;                               \
4841      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4842      _argvec[1] = (unsigned long)arg1;                          \
4843      _argvec[2] = (unsigned long)arg2;                          \
4844      __asm__ volatile(                                          \
4845         VALGRIND_CFI_PROLOGUE                                   \
4846         "aghi 15,-160\n\t"                                      \
4847         "lg 2, 8(1)\n\t"                                        \
4848         "lg 3,16(1)\n\t"                                        \
4849         "lg 1, 0(1)\n\t"                                        \
4850         VALGRIND_CALL_NOREDIR_R1                                \
4851         "aghi 15,160\n\t"                                       \
4852         VALGRIND_CFI_EPILOGUE                                   \
4853         "lgr %0, 2\n\t"                                         \
4854         : /*out*/   "=d" (_res)                                 \
4855         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4856         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4857      );                                                         \
4858      lval = (__typeof__(lval)) _res;                            \
4859   } while (0)
4860
4861#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3)              \
4862   do {                                                          \
4863      volatile OrigFn        _orig = (orig);                     \
4864      volatile unsigned long _argvec[4];                         \
4865      volatile unsigned long _res;                               \
4866      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4867      _argvec[1] = (unsigned long)arg1;                          \
4868      _argvec[2] = (unsigned long)arg2;                          \
4869      _argvec[3] = (unsigned long)arg3;                          \
4870      __asm__ volatile(                                          \
4871         VALGRIND_CFI_PROLOGUE                                   \
4872         "aghi 15,-160\n\t"                                      \
4873         "lg 2, 8(1)\n\t"                                        \
4874         "lg 3,16(1)\n\t"                                        \
4875         "lg 4,24(1)\n\t"                                        \
4876         "lg 1, 0(1)\n\t"                                        \
4877         VALGRIND_CALL_NOREDIR_R1                                \
4878         "aghi 15,160\n\t"                                       \
4879         VALGRIND_CFI_EPILOGUE                                   \
4880         "lgr %0, 2\n\t"                                         \
4881         : /*out*/   "=d" (_res)                                 \
4882         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4883         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4884      );                                                         \
4885      lval = (__typeof__(lval)) _res;                            \
4886   } while (0)
4887
4888#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4)       \
4889   do {                                                          \
4890      volatile OrigFn        _orig = (orig);                     \
4891      volatile unsigned long _argvec[5];                         \
4892      volatile unsigned long _res;                               \
4893      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4894      _argvec[1] = (unsigned long)arg1;                          \
4895      _argvec[2] = (unsigned long)arg2;                          \
4896      _argvec[3] = (unsigned long)arg3;                          \
4897      _argvec[4] = (unsigned long)arg4;                          \
4898      __asm__ volatile(                                          \
4899         VALGRIND_CFI_PROLOGUE                                   \
4900         "aghi 15,-160\n\t"                                      \
4901         "lg 2, 8(1)\n\t"                                        \
4902         "lg 3,16(1)\n\t"                                        \
4903         "lg 4,24(1)\n\t"                                        \
4904         "lg 5,32(1)\n\t"                                        \
4905         "lg 1, 0(1)\n\t"                                        \
4906         VALGRIND_CALL_NOREDIR_R1                                \
4907         "aghi 15,160\n\t"                                       \
4908         VALGRIND_CFI_EPILOGUE                                   \
4909         "lgr %0, 2\n\t"                                         \
4910         : /*out*/   "=d" (_res)                                 \
4911         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4912         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4913      );                                                         \
4914      lval = (__typeof__(lval)) _res;                            \
4915   } while (0)
4916
4917#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5)   \
4918   do {                                                          \
4919      volatile OrigFn        _orig = (orig);                     \
4920      volatile unsigned long _argvec[6];                         \
4921      volatile unsigned long _res;                               \
4922      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4923      _argvec[1] = (unsigned long)arg1;                          \
4924      _argvec[2] = (unsigned long)arg2;                          \
4925      _argvec[3] = (unsigned long)arg3;                          \
4926      _argvec[4] = (unsigned long)arg4;                          \
4927      _argvec[5] = (unsigned long)arg5;                          \
4928      __asm__ volatile(                                          \
4929         VALGRIND_CFI_PROLOGUE                                   \
4930         "aghi 15,-160\n\t"                                      \
4931         "lg 2, 8(1)\n\t"                                        \
4932         "lg 3,16(1)\n\t"                                        \
4933         "lg 4,24(1)\n\t"                                        \
4934         "lg 5,32(1)\n\t"                                        \
4935         "lg 6,40(1)\n\t"                                        \
4936         "lg 1, 0(1)\n\t"                                        \
4937         VALGRIND_CALL_NOREDIR_R1                                \
4938         "aghi 15,160\n\t"                                       \
4939         VALGRIND_CFI_EPILOGUE                                   \
4940         "lgr %0, 2\n\t"                                         \
4941         : /*out*/   "=d" (_res)                                 \
4942         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4943         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4944      );                                                         \
4945      lval = (__typeof__(lval)) _res;                            \
4946   } while (0)
4947
4948#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4949                     arg6)                                       \
4950   do {                                                          \
4951      volatile OrigFn        _orig = (orig);                     \
4952      volatile unsigned long _argvec[7];                         \
4953      volatile unsigned long _res;                               \
4954      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4955      _argvec[1] = (unsigned long)arg1;                          \
4956      _argvec[2] = (unsigned long)arg2;                          \
4957      _argvec[3] = (unsigned long)arg3;                          \
4958      _argvec[4] = (unsigned long)arg4;                          \
4959      _argvec[5] = (unsigned long)arg5;                          \
4960      _argvec[6] = (unsigned long)arg6;                          \
4961      __asm__ volatile(                                          \
4962         VALGRIND_CFI_PROLOGUE                                   \
4963         "aghi 15,-168\n\t"                                      \
4964         "lg 2, 8(1)\n\t"                                        \
4965         "lg 3,16(1)\n\t"                                        \
4966         "lg 4,24(1)\n\t"                                        \
4967         "lg 5,32(1)\n\t"                                        \
4968         "lg 6,40(1)\n\t"                                        \
4969         "mvc 160(8,15), 48(1)\n\t"                              \
4970         "lg 1, 0(1)\n\t"                                        \
4971         VALGRIND_CALL_NOREDIR_R1                                \
4972         "aghi 15,168\n\t"                                       \
4973         VALGRIND_CFI_EPILOGUE                                   \
4974         "lgr %0, 2\n\t"                                         \
4975         : /*out*/   "=d" (_res)                                 \
4976         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4977         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4978      );                                                         \
4979      lval = (__typeof__(lval)) _res;                            \
4980   } while (0)
4981
4982#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4983                     arg6, arg7)                                 \
4984   do {                                                          \
4985      volatile OrigFn        _orig = (orig);                     \
4986      volatile unsigned long _argvec[8];                         \
4987      volatile unsigned long _res;                               \
4988      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4989      _argvec[1] = (unsigned long)arg1;                          \
4990      _argvec[2] = (unsigned long)arg2;                          \
4991      _argvec[3] = (unsigned long)arg3;                          \
4992      _argvec[4] = (unsigned long)arg4;                          \
4993      _argvec[5] = (unsigned long)arg5;                          \
4994      _argvec[6] = (unsigned long)arg6;                          \
4995      _argvec[7] = (unsigned long)arg7;                          \
4996      __asm__ volatile(                                          \
4997         VALGRIND_CFI_PROLOGUE                                   \
4998         "aghi 15,-176\n\t"                                      \
4999         "lg 2, 8(1)\n\t"                                        \
5000         "lg 3,16(1)\n\t"                                        \
5001         "lg 4,24(1)\n\t"                                        \
5002         "lg 5,32(1)\n\t"                                        \
5003         "lg 6,40(1)\n\t"                                        \
5004         "mvc 160(8,15), 48(1)\n\t"                              \
5005         "mvc 168(8,15), 56(1)\n\t"                              \
5006         "lg 1, 0(1)\n\t"                                        \
5007         VALGRIND_CALL_NOREDIR_R1                                \
5008         "aghi 15,176\n\t"                                       \
5009         VALGRIND_CFI_EPILOGUE                                   \
5010         "lgr %0, 2\n\t"                                         \
5011         : /*out*/   "=d" (_res)                                 \
5012         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5013         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5014      );                                                         \
5015      lval = (__typeof__(lval)) _res;                            \
5016   } while (0)
5017
5018#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
5019                     arg6, arg7 ,arg8)                           \
5020   do {                                                          \
5021      volatile OrigFn        _orig = (orig);                     \
5022      volatile unsigned long _argvec[9];                         \
5023      volatile unsigned long _res;                               \
5024      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5025      _argvec[1] = (unsigned long)arg1;                          \
5026      _argvec[2] = (unsigned long)arg2;                          \
5027      _argvec[3] = (unsigned long)arg3;                          \
5028      _argvec[4] = (unsigned long)arg4;                          \
5029      _argvec[5] = (unsigned long)arg5;                          \
5030      _argvec[6] = (unsigned long)arg6;                          \
5031      _argvec[7] = (unsigned long)arg7;                          \
5032      _argvec[8] = (unsigned long)arg8;                          \
5033      __asm__ volatile(                                          \
5034         VALGRIND_CFI_PROLOGUE                                   \
5035         "aghi 15,-184\n\t"                                      \
5036         "lg 2, 8(1)\n\t"                                        \
5037         "lg 3,16(1)\n\t"                                        \
5038         "lg 4,24(1)\n\t"                                        \
5039         "lg 5,32(1)\n\t"                                        \
5040         "lg 6,40(1)\n\t"                                        \
5041         "mvc 160(8,15), 48(1)\n\t"                              \
5042         "mvc 168(8,15), 56(1)\n\t"                              \
5043         "mvc 176(8,15), 64(1)\n\t"                              \
5044         "lg 1, 0(1)\n\t"                                        \
5045         VALGRIND_CALL_NOREDIR_R1                                \
5046         "aghi 15,184\n\t"                                       \
5047         VALGRIND_CFI_EPILOGUE                                   \
5048         "lgr %0, 2\n\t"                                         \
5049         : /*out*/   "=d" (_res)                                 \
5050         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5051         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5052      );                                                         \
5053      lval = (__typeof__(lval)) _res;                            \
5054   } while (0)
5055
5056#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
5057                     arg6, arg7 ,arg8, arg9)                     \
5058   do {                                                          \
5059      volatile OrigFn        _orig = (orig);                     \
5060      volatile unsigned long _argvec[10];                        \
5061      volatile unsigned long _res;                               \
5062      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5063      _argvec[1] = (unsigned long)arg1;                          \
5064      _argvec[2] = (unsigned long)arg2;                          \
5065      _argvec[3] = (unsigned long)arg3;                          \
5066      _argvec[4] = (unsigned long)arg4;                          \
5067      _argvec[5] = (unsigned long)arg5;                          \
5068      _argvec[6] = (unsigned long)arg6;                          \
5069      _argvec[7] = (unsigned long)arg7;                          \
5070      _argvec[8] = (unsigned long)arg8;                          \
5071      _argvec[9] = (unsigned long)arg9;                          \
5072      __asm__ volatile(                                          \
5073         VALGRIND_CFI_PROLOGUE                                   \
5074         "aghi 15,-192\n\t"                                      \
5075         "lg 2, 8(1)\n\t"                                        \
5076         "lg 3,16(1)\n\t"                                        \
5077         "lg 4,24(1)\n\t"                                        \
5078         "lg 5,32(1)\n\t"                                        \
5079         "lg 6,40(1)\n\t"                                        \
5080         "mvc 160(8,15), 48(1)\n\t"                              \
5081         "mvc 168(8,15), 56(1)\n\t"                              \
5082         "mvc 176(8,15), 64(1)\n\t"                              \
5083         "mvc 184(8,15), 72(1)\n\t"                              \
5084         "lg 1, 0(1)\n\t"                                        \
5085         VALGRIND_CALL_NOREDIR_R1                                \
5086         "aghi 15,192\n\t"                                       \
5087         VALGRIND_CFI_EPILOGUE                                   \
5088         "lgr %0, 2\n\t"                                         \
5089         : /*out*/   "=d" (_res)                                 \
5090         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5091         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5092      );                                                         \
5093      lval = (__typeof__(lval)) _res;                            \
5094   } while (0)
5095
5096#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5097                     arg6, arg7 ,arg8, arg9, arg10)              \
5098   do {                                                          \
5099      volatile OrigFn        _orig = (orig);                     \
5100      volatile unsigned long _argvec[11];                        \
5101      volatile unsigned long _res;                               \
5102      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5103      _argvec[1] = (unsigned long)arg1;                          \
5104      _argvec[2] = (unsigned long)arg2;                          \
5105      _argvec[3] = (unsigned long)arg3;                          \
5106      _argvec[4] = (unsigned long)arg4;                          \
5107      _argvec[5] = (unsigned long)arg5;                          \
5108      _argvec[6] = (unsigned long)arg6;                          \
5109      _argvec[7] = (unsigned long)arg7;                          \
5110      _argvec[8] = (unsigned long)arg8;                          \
5111      _argvec[9] = (unsigned long)arg9;                          \
5112      _argvec[10] = (unsigned long)arg10;                        \
5113      __asm__ volatile(                                          \
5114         VALGRIND_CFI_PROLOGUE                                   \
5115         "aghi 15,-200\n\t"                                      \
5116         "lg 2, 8(1)\n\t"                                        \
5117         "lg 3,16(1)\n\t"                                        \
5118         "lg 4,24(1)\n\t"                                        \
5119         "lg 5,32(1)\n\t"                                        \
5120         "lg 6,40(1)\n\t"                                        \
5121         "mvc 160(8,15), 48(1)\n\t"                              \
5122         "mvc 168(8,15), 56(1)\n\t"                              \
5123         "mvc 176(8,15), 64(1)\n\t"                              \
5124         "mvc 184(8,15), 72(1)\n\t"                              \
5125         "mvc 192(8,15), 80(1)\n\t"                              \
5126         "lg 1, 0(1)\n\t"                                        \
5127         VALGRIND_CALL_NOREDIR_R1                                \
5128         "aghi 15,200\n\t"                                       \
5129         VALGRIND_CFI_EPILOGUE                                   \
5130         "lgr %0, 2\n\t"                                         \
5131         : /*out*/   "=d" (_res)                                 \
5132         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5133         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5134      );                                                         \
5135      lval = (__typeof__(lval)) _res;                            \
5136   } while (0)
5137
5138#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5139                     arg6, arg7 ,arg8, arg9, arg10, arg11)       \
5140   do {                                                          \
5141      volatile OrigFn        _orig = (orig);                     \
5142      volatile unsigned long _argvec[12];                        \
5143      volatile unsigned long _res;                               \
5144      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5145      _argvec[1] = (unsigned long)arg1;                          \
5146      _argvec[2] = (unsigned long)arg2;                          \
5147      _argvec[3] = (unsigned long)arg3;                          \
5148      _argvec[4] = (unsigned long)arg4;                          \
5149      _argvec[5] = (unsigned long)arg5;                          \
5150      _argvec[6] = (unsigned long)arg6;                          \
5151      _argvec[7] = (unsigned long)arg7;                          \
5152      _argvec[8] = (unsigned long)arg8;                          \
5153      _argvec[9] = (unsigned long)arg9;                          \
5154      _argvec[10] = (unsigned long)arg10;                        \
5155      _argvec[11] = (unsigned long)arg11;                        \
5156      __asm__ volatile(                                          \
5157         VALGRIND_CFI_PROLOGUE                                   \
5158         "aghi 15,-208\n\t"                                      \
5159         "lg 2, 8(1)\n\t"                                        \
5160         "lg 3,16(1)\n\t"                                        \
5161         "lg 4,24(1)\n\t"                                        \
5162         "lg 5,32(1)\n\t"                                        \
5163         "lg 6,40(1)\n\t"                                        \
5164         "mvc 160(8,15), 48(1)\n\t"                              \
5165         "mvc 168(8,15), 56(1)\n\t"                              \
5166         "mvc 176(8,15), 64(1)\n\t"                              \
5167         "mvc 184(8,15), 72(1)\n\t"                              \
5168         "mvc 192(8,15), 80(1)\n\t"                              \
5169         "mvc 200(8,15), 88(1)\n\t"                              \
5170         "lg 1, 0(1)\n\t"                                        \
5171         VALGRIND_CALL_NOREDIR_R1                                \
5172         "aghi 15,208\n\t"                                       \
5173         VALGRIND_CFI_EPILOGUE                                   \
5174         "lgr %0, 2\n\t"                                         \
5175         : /*out*/   "=d" (_res)                                 \
5176         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5177         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5178      );                                                         \
5179      lval = (__typeof__(lval)) _res;                            \
5180   } while (0)
5181
5182#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5183                     arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
5184   do {                                                          \
5185      volatile OrigFn        _orig = (orig);                     \
5186      volatile unsigned long _argvec[13];                        \
5187      volatile unsigned long _res;                               \
5188      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5189      _argvec[1] = (unsigned long)arg1;                          \
5190      _argvec[2] = (unsigned long)arg2;                          \
5191      _argvec[3] = (unsigned long)arg3;                          \
5192      _argvec[4] = (unsigned long)arg4;                          \
5193      _argvec[5] = (unsigned long)arg5;                          \
5194      _argvec[6] = (unsigned long)arg6;                          \
5195      _argvec[7] = (unsigned long)arg7;                          \
5196      _argvec[8] = (unsigned long)arg8;                          \
5197      _argvec[9] = (unsigned long)arg9;                          \
5198      _argvec[10] = (unsigned long)arg10;                        \
5199      _argvec[11] = (unsigned long)arg11;                        \
5200      _argvec[12] = (unsigned long)arg12;                        \
5201      __asm__ volatile(                                          \
5202         VALGRIND_CFI_PROLOGUE                                   \
5203         "aghi 15,-216\n\t"                                      \
5204         "lg 2, 8(1)\n\t"                                        \
5205         "lg 3,16(1)\n\t"                                        \
5206         "lg 4,24(1)\n\t"                                        \
5207         "lg 5,32(1)\n\t"                                        \
5208         "lg 6,40(1)\n\t"                                        \
5209         "mvc 160(8,15), 48(1)\n\t"                              \
5210         "mvc 168(8,15), 56(1)\n\t"                              \
5211         "mvc 176(8,15), 64(1)\n\t"                              \
5212         "mvc 184(8,15), 72(1)\n\t"                              \
5213         "mvc 192(8,15), 80(1)\n\t"                              \
5214         "mvc 200(8,15), 88(1)\n\t"                              \
5215         "mvc 208(8,15), 96(1)\n\t"                              \
5216         "lg 1, 0(1)\n\t"                                        \
5217         VALGRIND_CALL_NOREDIR_R1                                \
5218         "aghi 15,216\n\t"                                       \
5219         VALGRIND_CFI_EPILOGUE                                   \
5220         "lgr %0, 2\n\t"                                         \
5221         : /*out*/   "=d" (_res)                                 \
5222         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5223         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5224      );                                                         \
5225      lval = (__typeof__(lval)) _res;                            \
5226   } while (0)
5227
5228
5229#endif /* PLAT_s390x_linux */
5230
5231/* ------------------------- mips32-linux ----------------------- */
5232
5233#if defined(PLAT_mips32_linux)
5234
5235/* These regs are trashed by the hidden call. */
5236#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6",       \
5237"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5238"$25", "$31"
5239
5240/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5241   long) == 4. */
5242
5243#define CALL_FN_W_v(lval, orig)                                   \
5244   do {                                                           \
5245      volatile OrigFn        _orig = (orig);                      \
5246      volatile unsigned long _argvec[1];                          \
5247      volatile unsigned long _res;                                \
5248      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5249      __asm__ volatile(                                           \
5250         "subu $29, $29, 8 \n\t"                                  \
5251         "sw $28, 0($29) \n\t"                                    \
5252         "sw $31, 4($29) \n\t"                                    \
5253         "subu $29, $29, 16 \n\t"                                 \
5254         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5255         VALGRIND_CALL_NOREDIR_T9                                 \
5256         "addu $29, $29, 16\n\t"                                  \
5257         "lw $28, 0($29) \n\t"                                    \
5258         "lw $31, 4($29) \n\t"                                    \
5259         "addu $29, $29, 8 \n\t"                                  \
5260         "move %0, $2\n"                                          \
5261         : /*out*/   "=r" (_res)                                  \
5262         : /*in*/    "0" (&_argvec[0])                            \
5263         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5264      );                                                          \
5265      lval = (__typeof__(lval)) _res;                             \
5266   } while (0)
5267
5268#define CALL_FN_W_W(lval, orig, arg1)                             \
5269   do {                                                           \
5270      volatile OrigFn        _orig = (orig);                      \
5271     volatile unsigned long _argvec[2];                           \
5272      volatile unsigned long _res;                                \
5273      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5274      _argvec[1] = (unsigned long)(arg1);                         \
5275      __asm__ volatile(                                           \
5276         "subu $29, $29, 8 \n\t"                                  \
5277         "sw $28, 0($29) \n\t"                                    \
5278         "sw $31, 4($29) \n\t"                                    \
5279         "subu $29, $29, 16 \n\t"                                 \
5280         "lw $4, 4(%1) \n\t"   /* arg1*/                          \
5281         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5282         VALGRIND_CALL_NOREDIR_T9                                 \
5283         "addu $29, $29, 16 \n\t"                                 \
5284         "lw $28, 0($29) \n\t"                                    \
5285         "lw $31, 4($29) \n\t"                                    \
5286         "addu $29, $29, 8 \n\t"                                  \
5287         "move %0, $2\n"                                          \
5288         : /*out*/   "=r" (_res)                                  \
5289         : /*in*/    "0" (&_argvec[0])                            \
5290         : /*trash*/ "memory",  __CALLER_SAVED_REGS               \
5291      );                                                          \
5292      lval = (__typeof__(lval)) _res;                             \
5293   } while (0)
5294
5295#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
5296   do {                                                           \
5297      volatile OrigFn        _orig = (orig);                      \
5298      volatile unsigned long _argvec[3];                          \
5299      volatile unsigned long _res;                                \
5300      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5301      _argvec[1] = (unsigned long)(arg1);                         \
5302      _argvec[2] = (unsigned long)(arg2);                         \
5303      __asm__ volatile(                                           \
5304         "subu $29, $29, 8 \n\t"                                  \
5305         "sw $28, 0($29) \n\t"                                    \
5306         "sw $31, 4($29) \n\t"                                    \
5307         "subu $29, $29, 16 \n\t"                                 \
5308         "lw $4, 4(%1) \n\t"                                      \
5309         "lw $5, 8(%1) \n\t"                                      \
5310         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5311         VALGRIND_CALL_NOREDIR_T9                                 \
5312         "addu $29, $29, 16 \n\t"                                 \
5313         "lw $28, 0($29) \n\t"                                    \
5314         "lw $31, 4($29) \n\t"                                    \
5315         "addu $29, $29, 8 \n\t"                                  \
5316         "move %0, $2\n"                                          \
5317         : /*out*/   "=r" (_res)                                  \
5318         : /*in*/    "0" (&_argvec[0])                            \
5319         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5320      );                                                          \
5321      lval = (__typeof__(lval)) _res;                             \
5322   } while (0)
5323
5324#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
5325   do {                                                           \
5326      volatile OrigFn        _orig = (orig);                      \
5327      volatile unsigned long _argvec[4];                          \
5328      volatile unsigned long _res;                                \
5329      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5330      _argvec[1] = (unsigned long)(arg1);                         \
5331      _argvec[2] = (unsigned long)(arg2);                         \
5332      _argvec[3] = (unsigned long)(arg3);                         \
5333      __asm__ volatile(                                           \
5334         "subu $29, $29, 8 \n\t"                                  \
5335         "sw $28, 0($29) \n\t"                                    \
5336         "sw $31, 4($29) \n\t"                                    \
5337         "subu $29, $29, 16 \n\t"                                 \
5338         "lw $4, 4(%1) \n\t"                                      \
5339         "lw $5, 8(%1) \n\t"                                      \
5340         "lw $6, 12(%1) \n\t"                                     \
5341         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5342         VALGRIND_CALL_NOREDIR_T9                                 \
5343         "addu $29, $29, 16 \n\t"                                 \
5344         "lw $28, 0($29) \n\t"                                    \
5345         "lw $31, 4($29) \n\t"                                    \
5346         "addu $29, $29, 8 \n\t"                                  \
5347         "move %0, $2\n"                                          \
5348         : /*out*/   "=r" (_res)                                  \
5349         : /*in*/    "0" (&_argvec[0])                            \
5350         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5351      );                                                          \
5352      lval = (__typeof__(lval)) _res;                             \
5353   } while (0)
5354
5355#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
5356   do {                                                           \
5357      volatile OrigFn        _orig = (orig);                      \
5358      volatile unsigned long _argvec[5];                          \
5359      volatile unsigned long _res;                                \
5360      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5361      _argvec[1] = (unsigned long)(arg1);                         \
5362      _argvec[2] = (unsigned long)(arg2);                         \
5363      _argvec[3] = (unsigned long)(arg3);                         \
5364      _argvec[4] = (unsigned long)(arg4);                         \
5365      __asm__ volatile(                                           \
5366         "subu $29, $29, 8 \n\t"                                  \
5367         "sw $28, 0($29) \n\t"                                    \
5368         "sw $31, 4($29) \n\t"                                    \
5369         "subu $29, $29, 16 \n\t"                                 \
5370         "lw $4, 4(%1) \n\t"                                      \
5371         "lw $5, 8(%1) \n\t"                                      \
5372         "lw $6, 12(%1) \n\t"                                     \
5373         "lw $7, 16(%1) \n\t"                                     \
5374         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5375         VALGRIND_CALL_NOREDIR_T9                                 \
5376         "addu $29, $29, 16 \n\t"                                 \
5377         "lw $28, 0($29) \n\t"                                    \
5378         "lw $31, 4($29) \n\t"                                    \
5379         "addu $29, $29, 8 \n\t"                                  \
5380         "move %0, $2\n"                                          \
5381         : /*out*/   "=r" (_res)                                  \
5382         : /*in*/    "0" (&_argvec[0])                            \
5383         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5384      );                                                          \
5385      lval = (__typeof__(lval)) _res;                             \
5386   } while (0)
5387
5388#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
5389   do {                                                           \
5390      volatile OrigFn        _orig = (orig);                      \
5391      volatile unsigned long _argvec[6];                          \
5392      volatile unsigned long _res;                                \
5393      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5394      _argvec[1] = (unsigned long)(arg1);                         \
5395      _argvec[2] = (unsigned long)(arg2);                         \
5396      _argvec[3] = (unsigned long)(arg3);                         \
5397      _argvec[4] = (unsigned long)(arg4);                         \
5398      _argvec[5] = (unsigned long)(arg5);                         \
5399      __asm__ volatile(                                           \
5400         "subu $29, $29, 8 \n\t"                                  \
5401         "sw $28, 0($29) \n\t"                                    \
5402         "sw $31, 4($29) \n\t"                                    \
5403         "lw $4, 20(%1) \n\t"                                     \
5404         "subu $29, $29, 24\n\t"                                  \
5405         "sw $4, 16($29) \n\t"                                    \
5406         "lw $4, 4(%1) \n\t"                                      \
5407         "lw $5, 8(%1) \n\t"                                      \
5408         "lw $6, 12(%1) \n\t"                                     \
5409         "lw $7, 16(%1) \n\t"                                     \
5410         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5411         VALGRIND_CALL_NOREDIR_T9                                 \
5412         "addu $29, $29, 24 \n\t"                                 \
5413         "lw $28, 0($29) \n\t"                                    \
5414         "lw $31, 4($29) \n\t"                                    \
5415         "addu $29, $29, 8 \n\t"                                  \
5416         "move %0, $2\n"                                          \
5417         : /*out*/   "=r" (_res)                                  \
5418         : /*in*/    "0" (&_argvec[0])                            \
5419         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5420      );                                                          \
5421      lval = (__typeof__(lval)) _res;                             \
5422   } while (0)
5423#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
5424   do {                                                           \
5425      volatile OrigFn        _orig = (orig);                      \
5426      volatile unsigned long _argvec[7];                          \
5427      volatile unsigned long _res;                                \
5428      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5429      _argvec[1] = (unsigned long)(arg1);                         \
5430      _argvec[2] = (unsigned long)(arg2);                         \
5431      _argvec[3] = (unsigned long)(arg3);                         \
5432      _argvec[4] = (unsigned long)(arg4);                         \
5433      _argvec[5] = (unsigned long)(arg5);                         \
5434      _argvec[6] = (unsigned long)(arg6);                         \
5435      __asm__ volatile(                                           \
5436         "subu $29, $29, 8 \n\t"                                  \
5437         "sw $28, 0($29) \n\t"                                    \
5438         "sw $31, 4($29) \n\t"                                    \
5439         "lw $4, 20(%1) \n\t"                                     \
5440         "subu $29, $29, 32\n\t"                                  \
5441         "sw $4, 16($29) \n\t"                                    \
5442         "lw $4, 24(%1) \n\t"                                     \
5443         "nop\n\t"                                                \
5444         "sw $4, 20($29) \n\t"                                    \
5445         "lw $4, 4(%1) \n\t"                                      \
5446         "lw $5, 8(%1) \n\t"                                      \
5447         "lw $6, 12(%1) \n\t"                                     \
5448         "lw $7, 16(%1) \n\t"                                     \
5449         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5450         VALGRIND_CALL_NOREDIR_T9                                 \
5451         "addu $29, $29, 32 \n\t"                                 \
5452         "lw $28, 0($29) \n\t"                                    \
5453         "lw $31, 4($29) \n\t"                                    \
5454         "addu $29, $29, 8 \n\t"                                  \
5455         "move %0, $2\n"                                          \
5456         : /*out*/   "=r" (_res)                                  \
5457         : /*in*/    "0" (&_argvec[0])                            \
5458         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5459      );                                                          \
5460      lval = (__typeof__(lval)) _res;                             \
5461   } while (0)
5462
5463#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5464                                 arg7)                            \
5465   do {                                                           \
5466      volatile OrigFn        _orig = (orig);                      \
5467      volatile unsigned long _argvec[8];                          \
5468      volatile unsigned long _res;                                \
5469      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5470      _argvec[1] = (unsigned long)(arg1);                         \
5471      _argvec[2] = (unsigned long)(arg2);                         \
5472      _argvec[3] = (unsigned long)(arg3);                         \
5473      _argvec[4] = (unsigned long)(arg4);                         \
5474      _argvec[5] = (unsigned long)(arg5);                         \
5475      _argvec[6] = (unsigned long)(arg6);                         \
5476      _argvec[7] = (unsigned long)(arg7);                         \
5477      __asm__ volatile(                                           \
5478         "subu $29, $29, 8 \n\t"                                  \
5479         "sw $28, 0($29) \n\t"                                    \
5480         "sw $31, 4($29) \n\t"                                    \
5481         "lw $4, 20(%1) \n\t"                                     \
5482         "subu $29, $29, 32\n\t"                                  \
5483         "sw $4, 16($29) \n\t"                                    \
5484         "lw $4, 24(%1) \n\t"                                     \
5485         "sw $4, 20($29) \n\t"                                    \
5486         "lw $4, 28(%1) \n\t"                                     \
5487         "sw $4, 24($29) \n\t"                                    \
5488         "lw $4, 4(%1) \n\t"                                      \
5489         "lw $5, 8(%1) \n\t"                                      \
5490         "lw $6, 12(%1) \n\t"                                     \
5491         "lw $7, 16(%1) \n\t"                                     \
5492         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5493         VALGRIND_CALL_NOREDIR_T9                                 \
5494         "addu $29, $29, 32 \n\t"                                 \
5495         "lw $28, 0($29) \n\t"                                    \
5496         "lw $31, 4($29) \n\t"                                    \
5497         "addu $29, $29, 8 \n\t"                                  \
5498         "move %0, $2\n"                                          \
5499         : /*out*/   "=r" (_res)                                  \
5500         : /*in*/    "0" (&_argvec[0])                            \
5501         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5502      );                                                          \
5503      lval = (__typeof__(lval)) _res;                             \
5504   } while (0)
5505
5506#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5507                                 arg7,arg8)                       \
5508   do {                                                           \
5509      volatile OrigFn        _orig = (orig);                      \
5510      volatile unsigned long _argvec[9];                          \
5511      volatile unsigned long _res;                                \
5512      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5513      _argvec[1] = (unsigned long)(arg1);                         \
5514      _argvec[2] = (unsigned long)(arg2);                         \
5515      _argvec[3] = (unsigned long)(arg3);                         \
5516      _argvec[4] = (unsigned long)(arg4);                         \
5517      _argvec[5] = (unsigned long)(arg5);                         \
5518      _argvec[6] = (unsigned long)(arg6);                         \
5519      _argvec[7] = (unsigned long)(arg7);                         \
5520      _argvec[8] = (unsigned long)(arg8);                         \
5521      __asm__ volatile(                                           \
5522         "subu $29, $29, 8 \n\t"                                  \
5523         "sw $28, 0($29) \n\t"                                    \
5524         "sw $31, 4($29) \n\t"                                    \
5525         "lw $4, 20(%1) \n\t"                                     \
5526         "subu $29, $29, 40\n\t"                                  \
5527         "sw $4, 16($29) \n\t"                                    \
5528         "lw $4, 24(%1) \n\t"                                     \
5529         "sw $4, 20($29) \n\t"                                    \
5530         "lw $4, 28(%1) \n\t"                                     \
5531         "sw $4, 24($29) \n\t"                                    \
5532         "lw $4, 32(%1) \n\t"                                     \
5533         "sw $4, 28($29) \n\t"                                    \
5534         "lw $4, 4(%1) \n\t"                                      \
5535         "lw $5, 8(%1) \n\t"                                      \
5536         "lw $6, 12(%1) \n\t"                                     \
5537         "lw $7, 16(%1) \n\t"                                     \
5538         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5539         VALGRIND_CALL_NOREDIR_T9                                 \
5540         "addu $29, $29, 40 \n\t"                                 \
5541         "lw $28, 0($29) \n\t"                                    \
5542         "lw $31, 4($29) \n\t"                                    \
5543         "addu $29, $29, 8 \n\t"                                  \
5544         "move %0, $2\n"                                          \
5545         : /*out*/   "=r" (_res)                                  \
5546         : /*in*/    "0" (&_argvec[0])                            \
5547         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5548      );                                                          \
5549      lval = (__typeof__(lval)) _res;                             \
5550   } while (0)
5551
5552#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5553                                 arg7,arg8,arg9)                  \
5554   do {                                                           \
5555      volatile OrigFn        _orig = (orig);                      \
5556      volatile unsigned long _argvec[10];                         \
5557      volatile unsigned long _res;                                \
5558      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5559      _argvec[1] = (unsigned long)(arg1);                         \
5560      _argvec[2] = (unsigned long)(arg2);                         \
5561      _argvec[3] = (unsigned long)(arg3);                         \
5562      _argvec[4] = (unsigned long)(arg4);                         \
5563      _argvec[5] = (unsigned long)(arg5);                         \
5564      _argvec[6] = (unsigned long)(arg6);                         \
5565      _argvec[7] = (unsigned long)(arg7);                         \
5566      _argvec[8] = (unsigned long)(arg8);                         \
5567      _argvec[9] = (unsigned long)(arg9);                         \
5568      __asm__ volatile(                                           \
5569         "subu $29, $29, 8 \n\t"                                  \
5570         "sw $28, 0($29) \n\t"                                    \
5571         "sw $31, 4($29) \n\t"                                    \
5572         "lw $4, 20(%1) \n\t"                                     \
5573         "subu $29, $29, 40\n\t"                                  \
5574         "sw $4, 16($29) \n\t"                                    \
5575         "lw $4, 24(%1) \n\t"                                     \
5576         "sw $4, 20($29) \n\t"                                    \
5577         "lw $4, 28(%1) \n\t"                                     \
5578         "sw $4, 24($29) \n\t"                                    \
5579         "lw $4, 32(%1) \n\t"                                     \
5580         "sw $4, 28($29) \n\t"                                    \
5581         "lw $4, 36(%1) \n\t"                                     \
5582         "sw $4, 32($29) \n\t"                                    \
5583         "lw $4, 4(%1) \n\t"                                      \
5584         "lw $5, 8(%1) \n\t"                                      \
5585         "lw $6, 12(%1) \n\t"                                     \
5586         "lw $7, 16(%1) \n\t"                                     \
5587         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5588         VALGRIND_CALL_NOREDIR_T9                                 \
5589         "addu $29, $29, 40 \n\t"                                 \
5590         "lw $28, 0($29) \n\t"                                    \
5591         "lw $31, 4($29) \n\t"                                    \
5592         "addu $29, $29, 8 \n\t"                                  \
5593         "move %0, $2\n"                                          \
5594         : /*out*/   "=r" (_res)                                  \
5595         : /*in*/    "0" (&_argvec[0])                            \
5596         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5597      );                                                          \
5598      lval = (__typeof__(lval)) _res;                             \
5599   } while (0)
5600
5601#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
5602                                  arg7,arg8,arg9,arg10)           \
5603   do {                                                           \
5604      volatile OrigFn        _orig = (orig);                      \
5605      volatile unsigned long _argvec[11];                         \
5606      volatile unsigned long _res;                                \
5607      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5608      _argvec[1] = (unsigned long)(arg1);                         \
5609      _argvec[2] = (unsigned long)(arg2);                         \
5610      _argvec[3] = (unsigned long)(arg3);                         \
5611      _argvec[4] = (unsigned long)(arg4);                         \
5612      _argvec[5] = (unsigned long)(arg5);                         \
5613      _argvec[6] = (unsigned long)(arg6);                         \
5614      _argvec[7] = (unsigned long)(arg7);                         \
5615      _argvec[8] = (unsigned long)(arg8);                         \
5616      _argvec[9] = (unsigned long)(arg9);                         \
5617      _argvec[10] = (unsigned long)(arg10);                       \
5618      __asm__ volatile(                                           \
5619         "subu $29, $29, 8 \n\t"                                  \
5620         "sw $28, 0($29) \n\t"                                    \
5621         "sw $31, 4($29) \n\t"                                    \
5622         "lw $4, 20(%1) \n\t"                                     \
5623         "subu $29, $29, 48\n\t"                                  \
5624         "sw $4, 16($29) \n\t"                                    \
5625         "lw $4, 24(%1) \n\t"                                     \
5626         "sw $4, 20($29) \n\t"                                    \
5627         "lw $4, 28(%1) \n\t"                                     \
5628         "sw $4, 24($29) \n\t"                                    \
5629         "lw $4, 32(%1) \n\t"                                     \
5630         "sw $4, 28($29) \n\t"                                    \
5631         "lw $4, 36(%1) \n\t"                                     \
5632         "sw $4, 32($29) \n\t"                                    \
5633         "lw $4, 40(%1) \n\t"                                     \
5634         "sw $4, 36($29) \n\t"                                    \
5635         "lw $4, 4(%1) \n\t"                                      \
5636         "lw $5, 8(%1) \n\t"                                      \
5637         "lw $6, 12(%1) \n\t"                                     \
5638         "lw $7, 16(%1) \n\t"                                     \
5639         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5640         VALGRIND_CALL_NOREDIR_T9                                 \
5641         "addu $29, $29, 48 \n\t"                                 \
5642         "lw $28, 0($29) \n\t"                                    \
5643         "lw $31, 4($29) \n\t"                                    \
5644         "addu $29, $29, 8 \n\t"                                  \
5645         "move %0, $2\n"                                          \
5646         : /*out*/   "=r" (_res)                                  \
5647         : /*in*/    "0" (&_argvec[0])                            \
5648         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5649      );                                                          \
5650      lval = (__typeof__(lval)) _res;                             \
5651   } while (0)
5652
5653#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
5654                                  arg6,arg7,arg8,arg9,arg10,      \
5655                                  arg11)                          \
5656   do {                                                           \
5657      volatile OrigFn        _orig = (orig);                      \
5658      volatile unsigned long _argvec[12];                         \
5659      volatile unsigned long _res;                                \
5660      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5661      _argvec[1] = (unsigned long)(arg1);                         \
5662      _argvec[2] = (unsigned long)(arg2);                         \
5663      _argvec[3] = (unsigned long)(arg3);                         \
5664      _argvec[4] = (unsigned long)(arg4);                         \
5665      _argvec[5] = (unsigned long)(arg5);                         \
5666      _argvec[6] = (unsigned long)(arg6);                         \
5667      _argvec[7] = (unsigned long)(arg7);                         \
5668      _argvec[8] = (unsigned long)(arg8);                         \
5669      _argvec[9] = (unsigned long)(arg9);                         \
5670      _argvec[10] = (unsigned long)(arg10);                       \
5671      _argvec[11] = (unsigned long)(arg11);                       \
5672      __asm__ volatile(                                           \
5673         "subu $29, $29, 8 \n\t"                                  \
5674         "sw $28, 0($29) \n\t"                                    \
5675         "sw $31, 4($29) \n\t"                                    \
5676         "lw $4, 20(%1) \n\t"                                     \
5677         "subu $29, $29, 48\n\t"                                  \
5678         "sw $4, 16($29) \n\t"                                    \
5679         "lw $4, 24(%1) \n\t"                                     \
5680         "sw $4, 20($29) \n\t"                                    \
5681         "lw $4, 28(%1) \n\t"                                     \
5682         "sw $4, 24($29) \n\t"                                    \
5683         "lw $4, 32(%1) \n\t"                                     \
5684         "sw $4, 28($29) \n\t"                                    \
5685         "lw $4, 36(%1) \n\t"                                     \
5686         "sw $4, 32($29) \n\t"                                    \
5687         "lw $4, 40(%1) \n\t"                                     \
5688         "sw $4, 36($29) \n\t"                                    \
5689         "lw $4, 44(%1) \n\t"                                     \
5690         "sw $4, 40($29) \n\t"                                    \
5691         "lw $4, 4(%1) \n\t"                                      \
5692         "lw $5, 8(%1) \n\t"                                      \
5693         "lw $6, 12(%1) \n\t"                                     \
5694         "lw $7, 16(%1) \n\t"                                     \
5695         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5696         VALGRIND_CALL_NOREDIR_T9                                 \
5697         "addu $29, $29, 48 \n\t"                                 \
5698         "lw $28, 0($29) \n\t"                                    \
5699         "lw $31, 4($29) \n\t"                                    \
5700         "addu $29, $29, 8 \n\t"                                  \
5701         "move %0, $2\n"                                          \
5702         : /*out*/   "=r" (_res)                                  \
5703         : /*in*/    "0" (&_argvec[0])                            \
5704         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5705      );                                                          \
5706      lval = (__typeof__(lval)) _res;                             \
5707   } while (0)
5708
5709#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
5710                                  arg6,arg7,arg8,arg9,arg10,      \
5711                                  arg11,arg12)                    \
5712   do {                                                           \
5713      volatile OrigFn        _orig = (orig);                      \
5714      volatile unsigned long _argvec[13];                         \
5715      volatile unsigned long _res;                                \
5716      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5717      _argvec[1] = (unsigned long)(arg1);                         \
5718      _argvec[2] = (unsigned long)(arg2);                         \
5719      _argvec[3] = (unsigned long)(arg3);                         \
5720      _argvec[4] = (unsigned long)(arg4);                         \
5721      _argvec[5] = (unsigned long)(arg5);                         \
5722      _argvec[6] = (unsigned long)(arg6);                         \
5723      _argvec[7] = (unsigned long)(arg7);                         \
5724      _argvec[8] = (unsigned long)(arg8);                         \
5725      _argvec[9] = (unsigned long)(arg9);                         \
5726      _argvec[10] = (unsigned long)(arg10);                       \
5727      _argvec[11] = (unsigned long)(arg11);                       \
5728      _argvec[12] = (unsigned long)(arg12);                       \
5729      __asm__ volatile(                                           \
5730         "subu $29, $29, 8 \n\t"                                  \
5731         "sw $28, 0($29) \n\t"                                    \
5732         "sw $31, 4($29) \n\t"                                    \
5733         "lw $4, 20(%1) \n\t"                                     \
5734         "subu $29, $29, 56\n\t"                                  \
5735         "sw $4, 16($29) \n\t"                                    \
5736         "lw $4, 24(%1) \n\t"                                     \
5737         "sw $4, 20($29) \n\t"                                    \
5738         "lw $4, 28(%1) \n\t"                                     \
5739         "sw $4, 24($29) \n\t"                                    \
5740         "lw $4, 32(%1) \n\t"                                     \
5741         "sw $4, 28($29) \n\t"                                    \
5742         "lw $4, 36(%1) \n\t"                                     \
5743         "sw $4, 32($29) \n\t"                                    \
5744         "lw $4, 40(%1) \n\t"                                     \
5745         "sw $4, 36($29) \n\t"                                    \
5746         "lw $4, 44(%1) \n\t"                                     \
5747         "sw $4, 40($29) \n\t"                                    \
5748         "lw $4, 48(%1) \n\t"                                     \
5749         "sw $4, 44($29) \n\t"                                    \
5750         "lw $4, 4(%1) \n\t"                                      \
5751         "lw $5, 8(%1) \n\t"                                      \
5752         "lw $6, 12(%1) \n\t"                                     \
5753         "lw $7, 16(%1) \n\t"                                     \
5754         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5755         VALGRIND_CALL_NOREDIR_T9                                 \
5756         "addu $29, $29, 56 \n\t"                                 \
5757         "lw $28, 0($29) \n\t"                                    \
5758         "lw $31, 4($29) \n\t"                                    \
5759         "addu $29, $29, 8 \n\t"                                  \
5760         "move %0, $2\n"                                          \
5761         : /*out*/   "=r" (_res)                                  \
5762         : /*in*/    "r" (&_argvec[0])                            \
5763         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5764      );                                                          \
5765      lval = (__typeof__(lval)) _res;                             \
5766   } while (0)
5767
5768#endif /* PLAT_mips32_linux */
5769
5770/* ------------------------- nanomips-linux -------------------- */
5771
5772#if defined(PLAT_nanomips_linux)
5773
5774/* These regs are trashed by the hidden call. */
5775#define __CALLER_SAVED_REGS "$t4", "$t5", "$a0", "$a1", "$a2",     \
5776"$a3", "$a4", "$a5", "$a6", "$a7", "$t0", "$t1", "$t2", "$t3",     \
5777"$t8","$t9", "$at"
5778
5779/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5780   long) == 4. */
5781
5782#define CALL_FN_W_v(lval, orig)                                   \
5783   do {                                                           \
5784      volatile OrigFn        _orig = (orig);                      \
5785      volatile unsigned long _argvec[1];                          \
5786      volatile unsigned long _res;                                \
5787      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5788      __asm__ volatile(                                           \
5789         "lw $t9, 0(%1)\n\t"                                      \
5790         VALGRIND_CALL_NOREDIR_T9                                 \
5791         "move %0, $a0\n"                                         \
5792         : /*out*/   "=r" (_res)                                  \
5793         : /*in*/    "r" (&_argvec[0])                            \
5794         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5795      );                                                          \
5796      lval = (__typeof__(lval)) _res;                             \
5797   } while (0)
5798
5799#define CALL_FN_W_W(lval, orig, arg1)                             \
5800   do {                                                           \
5801      volatile OrigFn        _orig = (orig);                      \
5802      volatile unsigned long _argvec[2];                          \
5803      volatile unsigned long _res;                                \
5804      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5805      _argvec[1] = (unsigned long)(arg1);                         \
5806      __asm__ volatile(                                           \
5807         "lw $t9, 0(%1)\n\t"                                      \
5808         "lw $a0, 4(%1)\n\t"                                      \
5809         VALGRIND_CALL_NOREDIR_T9                                 \
5810         "move %0, $a0\n"                                         \
5811         : /*out*/   "=r" (_res)                                  \
5812         : /*in*/    "r" (&_argvec[0])                            \
5813         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5814      );                                                          \
5815      lval = (__typeof__(lval)) _res;                             \
5816   } while (0)
5817
5818#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
5819   do {                                                           \
5820      volatile OrigFn        _orig = (orig);                      \
5821      volatile unsigned long _argvec[3];                          \
5822      volatile unsigned long _res;                                \
5823      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5824      _argvec[1] = (unsigned long)(arg1);                         \
5825      _argvec[2] = (unsigned long)(arg2);                         \
5826      __asm__ volatile(                                           \
5827         "lw $t9, 0(%1)\n\t"                                      \
5828         "lw $a0, 4(%1)\n\t"                                      \
5829         "lw $a1, 8(%1)\n\t"                                      \
5830         VALGRIND_CALL_NOREDIR_T9                                 \
5831         "move %0, $a0\n"                                         \
5832         : /*out*/   "=r" (_res)                                  \
5833         : /*in*/    "r" (&_argvec[0])                            \
5834         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5835      );                                                          \
5836      lval = (__typeof__(lval)) _res;                             \
5837   } while (0)
5838
5839#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
5840   do {                                                           \
5841      volatile OrigFn        _orig = (orig);                      \
5842      volatile unsigned long _argvec[4];                          \
5843      volatile unsigned long _res;                                \
5844      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5845      _argvec[1] = (unsigned long)(arg1);                         \
5846      _argvec[2] = (unsigned long)(arg2);                         \
5847      _argvec[3] = (unsigned long)(arg3);                         \
5848      __asm__ volatile(                                           \
5849         "lw $t9, 0(%1)\n\t"                                      \
5850         "lw $a0, 4(%1)\n\t"                                      \
5851         "lw $a1, 8(%1)\n\t"                                      \
5852         "lw $a2,12(%1)\n\t"                                      \
5853         VALGRIND_CALL_NOREDIR_T9                                 \
5854         "move %0, $a0\n"                                         \
5855         : /*out*/   "=r" (_res)                                  \
5856         : /*in*/    "r" (&_argvec[0])                            \
5857         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5858      );                                                          \
5859      lval = (__typeof__(lval)) _res;                             \
5860   } while (0)
5861
5862#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
5863   do {                                                           \
5864      volatile OrigFn        _orig = (orig);                      \
5865      volatile unsigned long _argvec[5];                          \
5866      volatile unsigned long _res;                                \
5867      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5868      _argvec[1] = (unsigned long)(arg1);                         \
5869      _argvec[2] = (unsigned long)(arg2);                         \
5870      _argvec[3] = (unsigned long)(arg3);                         \
5871      _argvec[4] = (unsigned long)(arg4);                         \
5872      __asm__ volatile(                                           \
5873         "lw $t9, 0(%1)\n\t"                                      \
5874         "lw $a0, 4(%1)\n\t"                                      \
5875         "lw $a1, 8(%1)\n\t"                                      \
5876         "lw $a2,12(%1)\n\t"                                      \
5877         "lw $a3,16(%1)\n\t"                                      \
5878         VALGRIND_CALL_NOREDIR_T9                                 \
5879         "move %0, $a0\n"                                         \
5880         : /*out*/   "=r" (_res)                                  \
5881         : /*in*/    "r" (&_argvec[0])                            \
5882         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5883      );                                                          \
5884      lval = (__typeof__(lval)) _res;                             \
5885   } while (0)
5886
5887#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
5888   do {                                                           \
5889      volatile OrigFn        _orig = (orig);                      \
5890      volatile unsigned long _argvec[6];                          \
5891      volatile unsigned long _res;                                \
5892      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5893      _argvec[1] = (unsigned long)(arg1);                         \
5894      _argvec[2] = (unsigned long)(arg2);                         \
5895      _argvec[3] = (unsigned long)(arg3);                         \
5896      _argvec[4] = (unsigned long)(arg4);                         \
5897      _argvec[5] = (unsigned long)(arg5);                         \
5898      __asm__ volatile(                                           \
5899         "lw $t9, 0(%1)\n\t"                                      \
5900         "lw $a0, 4(%1)\n\t"                                      \
5901         "lw $a1, 8(%1)\n\t"                                      \
5902         "lw $a2,12(%1)\n\t"                                      \
5903         "lw $a3,16(%1)\n\t"                                      \
5904         "lw $a4,20(%1)\n\t"                                      \
5905         VALGRIND_CALL_NOREDIR_T9                                 \
5906         "move %0, $a0\n"                                         \
5907         : /*out*/   "=r" (_res)                                  \
5908         : /*in*/    "r" (&_argvec[0])                            \
5909         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5910      );                                                          \
5911      lval = (__typeof__(lval)) _res;                             \
5912   } while (0)
5913#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
5914   do {                                                           \
5915      volatile OrigFn        _orig = (orig);                      \
5916      volatile unsigned long _argvec[7];                          \
5917      volatile unsigned long _res;                                \
5918      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5919      _argvec[1] = (unsigned long)(arg1);                         \
5920      _argvec[2] = (unsigned long)(arg2);                         \
5921      _argvec[3] = (unsigned long)(arg3);                         \
5922      _argvec[4] = (unsigned long)(arg4);                         \
5923      _argvec[5] = (unsigned long)(arg5);                         \
5924      _argvec[6] = (unsigned long)(arg6);                         \
5925      __asm__ volatile(                                           \
5926         "lw $t9, 0(%1)\n\t"                                      \
5927         "lw $a0, 4(%1)\n\t"                                      \
5928         "lw $a1, 8(%1)\n\t"                                      \
5929         "lw $a2,12(%1)\n\t"                                      \
5930         "lw $a3,16(%1)\n\t"                                      \
5931         "lw $a4,20(%1)\n\t"                                      \
5932         "lw $a5,24(%1)\n\t"                                      \
5933         VALGRIND_CALL_NOREDIR_T9                                 \
5934         "move %0, $a0\n"                                         \
5935         : /*out*/   "=r" (_res)                                  \
5936         : /*in*/    "r" (&_argvec[0])                            \
5937         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5938      );                                                          \
5939      lval = (__typeof__(lval)) _res;                             \
5940   } while (0)
5941
5942#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5943                                 arg7)                            \
5944   do {                                                           \
5945      volatile OrigFn        _orig = (orig);                      \
5946      volatile unsigned long _argvec[8];                          \
5947      volatile unsigned long _res;                                \
5948      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5949      _argvec[1] = (unsigned long)(arg1);                         \
5950      _argvec[2] = (unsigned long)(arg2);                         \
5951      _argvec[3] = (unsigned long)(arg3);                         \
5952      _argvec[4] = (unsigned long)(arg4);                         \
5953      _argvec[5] = (unsigned long)(arg5);                         \
5954      _argvec[6] = (unsigned long)(arg6);                         \
5955      _argvec[7] = (unsigned long)(arg7);                         \
5956      __asm__ volatile(                                           \
5957         "lw $t9, 0(%1)\n\t"                                      \
5958         "lw $a0, 4(%1)\n\t"                                      \
5959         "lw $a1, 8(%1)\n\t"                                      \
5960         "lw $a2,12(%1)\n\t"                                      \
5961         "lw $a3,16(%1)\n\t"                                      \
5962         "lw $a4,20(%1)\n\t"                                      \
5963         "lw $a5,24(%1)\n\t"                                      \
5964         "lw $a6,28(%1)\n\t"                                      \
5965         VALGRIND_CALL_NOREDIR_T9                                 \
5966         "move %0, $a0\n"                                         \
5967         : /*out*/   "=r" (_res)                                  \
5968         : /*in*/    "r" (&_argvec[0])                            \
5969         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5970      );                                                          \
5971      lval = (__typeof__(lval)) _res;                             \
5972   } while (0)
5973
5974#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5975                                 arg7,arg8)                       \
5976   do {                                                           \
5977      volatile OrigFn        _orig = (orig);                      \
5978      volatile unsigned long _argvec[9];                          \
5979      volatile unsigned long _res;                                \
5980      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5981      _argvec[1] = (unsigned long)(arg1);                         \
5982      _argvec[2] = (unsigned long)(arg2);                         \
5983      _argvec[3] = (unsigned long)(arg3);                         \
5984      _argvec[4] = (unsigned long)(arg4);                         \
5985      _argvec[5] = (unsigned long)(arg5);                         \
5986      _argvec[6] = (unsigned long)(arg6);                         \
5987      _argvec[7] = (unsigned long)(arg7);                         \
5988      _argvec[8] = (unsigned long)(arg8);                         \
5989      __asm__ volatile(                                           \
5990         "lw $t9, 0(%1)\n\t"                                      \
5991         "lw $a0, 4(%1)\n\t"                                      \
5992         "lw $a1, 8(%1)\n\t"                                      \
5993         "lw $a2,12(%1)\n\t"                                      \
5994         "lw $a3,16(%1)\n\t"                                      \
5995         "lw $a4,20(%1)\n\t"                                      \
5996         "lw $a5,24(%1)\n\t"                                      \
5997         "lw $a6,28(%1)\n\t"                                      \
5998         "lw $a7,32(%1)\n\t"                                      \
5999         VALGRIND_CALL_NOREDIR_T9                                 \
6000         "move %0, $a0\n"                                         \
6001         : /*out*/   "=r" (_res)                                  \
6002         : /*in*/    "r" (&_argvec[0])                            \
6003         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6004      );                                                          \
6005      lval = (__typeof__(lval)) _res;                             \
6006   } while (0)
6007
6008#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
6009                                 arg7,arg8,arg9)                  \
6010   do {                                                           \
6011      volatile OrigFn        _orig = (orig);                      \
6012      volatile unsigned long _argvec[10];                         \
6013      volatile unsigned long _res;                                \
6014      _argvec[0] = (unsigned long)_orig.nraddr;                   \
6015      _argvec[1] = (unsigned long)(arg1);                         \
6016      _argvec[2] = (unsigned long)(arg2);                         \
6017      _argvec[3] = (unsigned long)(arg3);                         \
6018      _argvec[4] = (unsigned long)(arg4);                         \
6019      _argvec[5] = (unsigned long)(arg5);                         \
6020      _argvec[6] = (unsigned long)(arg6);                         \
6021      _argvec[7] = (unsigned long)(arg7);                         \
6022      _argvec[8] = (unsigned long)(arg8);                         \
6023      _argvec[9] = (unsigned long)(arg9);                         \
6024      __asm__ volatile(                                           \
6025         "addiu $sp, $sp, -16  \n\t"                              \
6026         "lw $t9,36(%1)        \n\t"                              \
6027         "sw $t9, 0($sp)       \n\t"                              \
6028         "lw $t9, 0(%1)        \n\t"                              \
6029         "lw $a0, 4(%1)        \n\t"                              \
6030         "lw $a1, 8(%1)        \n\t"                              \
6031         "lw $a2,12(%1)        \n\t"                              \
6032         "lw $a3,16(%1)        \n\t"                              \
6033         "lw $a4,20(%1)        \n\t"                              \
6034         "lw $a5,24(%1)        \n\t"                              \
6035         "lw $a6,28(%1)        \n\t"                              \
6036         "lw $a7,32(%1)        \n\t"                              \
6037         VALGRIND_CALL_NOREDIR_T9                                 \
6038         "move %0, $a0         \n\t"                              \
6039         "addiu $sp, $sp, 16   \n\t"                              \
6040         : /*out*/   "=r" (_res)                                  \
6041         : /*in*/    "r" (&_argvec[0])                            \
6042         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6043      );                                                          \
6044      lval = (__typeof__(lval)) _res;                             \
6045   } while (0)
6046
6047#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
6048                                  arg7,arg8,arg9,arg10)           \
6049   do {                                                           \
6050      volatile OrigFn        _orig = (orig);                      \
6051      volatile unsigned long _argvec[11];                         \
6052      volatile unsigned long _res;                                \
6053      _argvec[0] = (unsigned long)_orig.nraddr;                   \
6054      _argvec[1] = (unsigned long)(arg1);                         \
6055      _argvec[2] = (unsigned long)(arg2);                         \
6056      _argvec[3] = (unsigned long)(arg3);                         \
6057      _argvec[4] = (unsigned long)(arg4);                         \
6058      _argvec[5] = (unsigned long)(arg5);                         \
6059      _argvec[6] = (unsigned long)(arg6);                         \
6060      _argvec[7] = (unsigned long)(arg7);                         \
6061      _argvec[8] = (unsigned long)(arg8);                         \
6062      _argvec[9] = (unsigned long)(arg9);                         \
6063      _argvec[10] = (unsigned long)(arg10);                       \
6064      __asm__ volatile(                                           \
6065         "addiu $sp, $sp, -16  \n\t"                              \
6066         "lw $t9,36(%1)        \n\t"                              \
6067         "sw $t9, 0($sp)       \n\t"                              \
6068         "lw $t9,40(%1)        \n\t"                              \
6069         "sw $t9, 4($sp)       \n\t"                              \
6070         "lw $t9, 0(%1)        \n\t"                              \
6071         "lw $a0, 4(%1)        \n\t"                              \
6072         "lw $a1, 8(%1)        \n\t"                              \
6073         "lw $a2,12(%1)        \n\t"                              \
6074         "lw $a3,16(%1)        \n\t"                              \
6075         "lw $a4,20(%1)        \n\t"                              \
6076         "lw $a5,24(%1)        \n\t"                              \
6077         "lw $a6,28(%1)        \n\t"                              \
6078         "lw $a7,32(%1)        \n\t"                              \
6079         VALGRIND_CALL_NOREDIR_T9                                 \
6080         "move %0, $a0         \n\t"                              \
6081         "addiu $sp, $sp, 16   \n\t"                              \
6082         : /*out*/   "=r" (_res)                                  \
6083         : /*in*/    "r" (&_argvec[0])                            \
6084         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6085      );                                                          \
6086      lval = (__typeof__(lval)) _res;                             \
6087   } while (0)
6088
6089#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
6090                                  arg6,arg7,arg8,arg9,arg10,      \
6091                                  arg11)                          \
6092   do {                                                           \
6093      volatile OrigFn        _orig = (orig);                      \
6094      volatile unsigned long _argvec[12];                         \
6095      volatile unsigned long _res;                                \
6096      _argvec[0] = (unsigned long)_orig.nraddr;                   \
6097      _argvec[1] = (unsigned long)(arg1);                         \
6098      _argvec[2] = (unsigned long)(arg2);                         \
6099      _argvec[3] = (unsigned long)(arg3);                         \
6100      _argvec[4] = (unsigned long)(arg4);                         \
6101      _argvec[5] = (unsigned long)(arg5);                         \
6102      _argvec[6] = (unsigned long)(arg6);                         \
6103      _argvec[7] = (unsigned long)(arg7);                         \
6104      _argvec[8] = (unsigned long)(arg8);                         \
6105      _argvec[9] = (unsigned long)(arg9);                         \
6106      _argvec[10] = (unsigned long)(arg10);                       \
6107      _argvec[11] = (unsigned long)(arg11);                       \
6108      __asm__ volatile(                                           \
6109         "addiu $sp, $sp, -16  \n\t"                              \
6110         "lw $t9,36(%1)        \n\t"                              \
6111         "sw $t9, 0($sp)       \n\t"                              \
6112         "lw $t9,40(%1)        \n\t"                              \
6113         "sw $t9, 4($sp)       \n\t"                              \
6114         "lw $t9,44(%1)        \n\t"                              \
6115         "sw $t9, 8($sp)       \n\t"                              \
6116         "lw $t9, 0(%1)        \n\t"                              \
6117         "lw $a0, 4(%1)        \n\t"                              \
6118         "lw $a1, 8(%1)        \n\t"                              \
6119         "lw $a2,12(%1)        \n\t"                              \
6120         "lw $a3,16(%1)        \n\t"                              \
6121         "lw $a4,20(%1)        \n\t"                              \
6122         "lw $a5,24(%1)        \n\t"                              \
6123         "lw $a6,28(%1)        \n\t"                              \
6124         "lw $a7,32(%1)        \n\t"                              \
6125         VALGRIND_CALL_NOREDIR_T9                                 \
6126         "move %0, $a0         \n\t"                              \
6127         "addiu $sp, $sp, 16   \n\t"                              \
6128         : /*out*/   "=r" (_res)                                  \
6129         : /*in*/    "r" (&_argvec[0])                            \
6130         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6131      );                                                          \
6132      lval = (__typeof__(lval)) _res;                             \
6133   } while (0)
6134
6135#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
6136                                  arg6,arg7,arg8,arg9,arg10,      \
6137                                  arg11,arg12)                    \
6138   do {                                                           \
6139      volatile OrigFn        _orig = (orig);                      \
6140      volatile unsigned long _argvec[13];                         \
6141      volatile unsigned long _res;                                \
6142      _argvec[0] = (unsigned long)_orig.nraddr;                   \
6143      _argvec[1] = (unsigned long)(arg1);                         \
6144      _argvec[2] = (unsigned long)(arg2);                         \
6145      _argvec[3] = (unsigned long)(arg3);                         \
6146      _argvec[4] = (unsigned long)(arg4);                         \
6147      _argvec[5] = (unsigned long)(arg5);                         \
6148      _argvec[6] = (unsigned long)(arg6);                         \
6149      _argvec[7] = (unsigned long)(arg7);                         \
6150      _argvec[8] = (unsigned long)(arg8);                         \
6151      _argvec[9] = (unsigned long)(arg9);                         \
6152      _argvec[10] = (unsigned long)(arg10);                       \
6153      _argvec[11] = (unsigned long)(arg11);                       \
6154      _argvec[12] = (unsigned long)(arg12);                       \
6155      __asm__ volatile(                                           \
6156         "addiu $sp, $sp, -16  \n\t"                              \
6157         "lw $t9,36(%1)        \n\t"                              \
6158         "sw $t9, 0($sp)       \n\t"                              \
6159         "lw $t9,40(%1)        \n\t"                              \
6160         "sw $t9, 4($sp)       \n\t"                              \
6161         "lw $t9,44(%1)        \n\t"                              \
6162         "sw $t9, 8($sp)       \n\t"                              \
6163         "lw $t9,48(%1)        \n\t"                              \
6164         "sw $t9,12($sp)       \n\t"                              \
6165         "lw $t9, 0(%1)        \n\t"                              \
6166         "lw $a0, 4(%1)        \n\t"                              \
6167         "lw $a1, 8(%1)        \n\t"                              \
6168         "lw $a2,12(%1)        \n\t"                              \
6169         "lw $a3,16(%1)        \n\t"                              \
6170         "lw $a4,20(%1)        \n\t"                              \
6171         "lw $a5,24(%1)        \n\t"                              \
6172         "lw $a6,28(%1)        \n\t"                              \
6173         "lw $a7,32(%1)        \n\t"                              \
6174         VALGRIND_CALL_NOREDIR_T9                                 \
6175         "move %0, $a0         \n\t"                              \
6176         "addiu $sp, $sp, 16   \n\t"                              \
6177         : /*out*/   "=r" (_res)                                  \
6178         : /*in*/    "r" (&_argvec[0])                            \
6179         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6180      );                                                          \
6181      lval = (__typeof__(lval)) _res;                             \
6182   } while (0)
6183
6184#endif /* PLAT_nanomips_linux */
6185
6186/* ------------------------- mips64-linux ------------------------- */
6187
6188#if defined(PLAT_mips64_linux)
6189
6190/* These regs are trashed by the hidden call. */
6191#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6",       \
6192"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
6193"$25", "$31"
6194
6195/* These CALL_FN_ macros assume that on mips64-linux,
6196   sizeof(long long) == 8. */
6197
6198#define MIPS64_LONG2REG_CAST(x) ((long long)(long)x)
6199
6200#define CALL_FN_W_v(lval, orig)                                   \
6201   do {                                                           \
6202      volatile OrigFn        _orig = (orig);                      \
6203      volatile unsigned long long _argvec[1];                     \
6204      volatile unsigned long long _res;                           \
6205      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6206      __asm__ volatile(                                           \
6207         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6208         VALGRIND_CALL_NOREDIR_T9                                 \
6209         "move %0, $2\n"                                          \
6210         : /*out*/   "=r" (_res)                                  \
6211         : /*in*/    "0" (&_argvec[0])                            \
6212         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6213      );                                                          \
6214      lval = (__typeof__(lval)) (long)_res;                       \
6215   } while (0)
6216
6217#define CALL_FN_W_W(lval, orig, arg1)                             \
6218   do {                                                           \
6219      volatile OrigFn        _orig = (orig);                      \
6220      volatile unsigned long long _argvec[2];                     \
6221      volatile unsigned long long  _res;                          \
6222      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6223      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6224      __asm__ volatile(                                           \
6225         "ld $4, 8(%1)\n\t"   /* arg1*/                           \
6226         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6227         VALGRIND_CALL_NOREDIR_T9                                 \
6228         "move %0, $2\n"                                          \
6229         : /*out*/   "=r" (_res)                                  \
6230         : /*in*/    "r" (&_argvec[0])                            \
6231         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6232      );                                                          \
6233      lval = (__typeof__(lval)) (long)_res;                       \
6234   } while (0)
6235
6236#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
6237   do {                                                           \
6238      volatile OrigFn        _orig = (orig);                      \
6239      volatile unsigned long long _argvec[3];                     \
6240      volatile unsigned long long _res;                           \
6241      _argvec[0] = _orig.nraddr;                                  \
6242      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6243      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6244      __asm__ volatile(                                           \
6245         "ld $4, 8(%1)\n\t"                                       \
6246         "ld $5, 16(%1)\n\t"                                      \
6247         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6248         VALGRIND_CALL_NOREDIR_T9                                 \
6249         "move %0, $2\n"                                          \
6250         : /*out*/   "=r" (_res)                                  \
6251         : /*in*/    "r" (&_argvec[0])                            \
6252         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6253      );                                                          \
6254      lval = (__typeof__(lval)) (long)_res;                       \
6255   } while (0)
6256
6257
6258#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
6259   do {                                                           \
6260      volatile OrigFn        _orig = (orig);                      \
6261      volatile unsigned long long _argvec[4];                     \
6262      volatile unsigned long long _res;                           \
6263      _argvec[0] = _orig.nraddr;                                  \
6264      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6265      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6266      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6267      __asm__ volatile(                                           \
6268         "ld $4, 8(%1)\n\t"                                       \
6269         "ld $5, 16(%1)\n\t"                                      \
6270         "ld $6, 24(%1)\n\t"                                      \
6271         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6272         VALGRIND_CALL_NOREDIR_T9                                 \
6273         "move %0, $2\n"                                          \
6274         : /*out*/   "=r" (_res)                                  \
6275         : /*in*/    "r" (&_argvec[0])                            \
6276         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6277      );                                                          \
6278      lval = (__typeof__(lval)) (long)_res;                       \
6279   } while (0)
6280
6281#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
6282   do {                                                           \
6283      volatile OrigFn        _orig = (orig);                      \
6284      volatile unsigned long long _argvec[5];                     \
6285      volatile unsigned long long _res;                           \
6286      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6287      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6288      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6289      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6290      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6291      __asm__ volatile(                                           \
6292         "ld $4, 8(%1)\n\t"                                       \
6293         "ld $5, 16(%1)\n\t"                                      \
6294         "ld $6, 24(%1)\n\t"                                      \
6295         "ld $7, 32(%1)\n\t"                                      \
6296         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6297         VALGRIND_CALL_NOREDIR_T9                                 \
6298         "move %0, $2\n"                                          \
6299         : /*out*/   "=r" (_res)                                  \
6300         : /*in*/    "r" (&_argvec[0])                            \
6301         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6302      );                                                          \
6303      lval = (__typeof__(lval)) (long)_res;                       \
6304   } while (0)
6305
6306#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
6307   do {                                                           \
6308      volatile OrigFn        _orig = (orig);                      \
6309      volatile unsigned long long _argvec[6];                     \
6310      volatile unsigned long long _res;                           \
6311      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6312      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6313      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6314      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6315      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6316      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6317      __asm__ volatile(                                           \
6318         "ld $4, 8(%1)\n\t"                                       \
6319         "ld $5, 16(%1)\n\t"                                      \
6320         "ld $6, 24(%1)\n\t"                                      \
6321         "ld $7, 32(%1)\n\t"                                      \
6322         "ld $8, 40(%1)\n\t"                                      \
6323         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6324         VALGRIND_CALL_NOREDIR_T9                                 \
6325         "move %0, $2\n"                                          \
6326         : /*out*/   "=r" (_res)                                  \
6327         : /*in*/    "r" (&_argvec[0])                            \
6328         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6329      );                                                          \
6330      lval = (__typeof__(lval)) (long)_res;                       \
6331   } while (0)
6332
6333#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
6334   do {                                                           \
6335      volatile OrigFn        _orig = (orig);                      \
6336      volatile unsigned long long _argvec[7];                     \
6337      volatile unsigned long long _res;                           \
6338      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6339      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6340      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6341      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6342      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6343      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6344      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6345      __asm__ volatile(                                           \
6346         "ld $4, 8(%1)\n\t"                                       \
6347         "ld $5, 16(%1)\n\t"                                      \
6348         "ld $6, 24(%1)\n\t"                                      \
6349         "ld $7, 32(%1)\n\t"                                      \
6350         "ld $8, 40(%1)\n\t"                                      \
6351         "ld $9, 48(%1)\n\t"                                      \
6352         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6353         VALGRIND_CALL_NOREDIR_T9                                 \
6354         "move %0, $2\n"                                          \
6355         : /*out*/   "=r" (_res)                                  \
6356         : /*in*/    "r" (&_argvec[0])                            \
6357         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6358      );                                                          \
6359      lval = (__typeof__(lval)) (long)_res;                       \
6360   } while (0)
6361
6362#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
6363                                 arg7)                            \
6364   do {                                                           \
6365      volatile OrigFn        _orig = (orig);                      \
6366      volatile unsigned long long _argvec[8];                     \
6367      volatile unsigned long long _res;                           \
6368      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6369      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6370      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6371      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6372      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6373      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6374      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6375      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6376      __asm__ volatile(                                           \
6377         "ld $4, 8(%1)\n\t"                                       \
6378         "ld $5, 16(%1)\n\t"                                      \
6379         "ld $6, 24(%1)\n\t"                                      \
6380         "ld $7, 32(%1)\n\t"                                      \
6381         "ld $8, 40(%1)\n\t"                                      \
6382         "ld $9, 48(%1)\n\t"                                      \
6383         "ld $10, 56(%1)\n\t"                                     \
6384         "ld $25, 0(%1) \n\t"  /* target->t9 */                   \
6385         VALGRIND_CALL_NOREDIR_T9                                 \
6386         "move %0, $2\n"                                          \
6387         : /*out*/   "=r" (_res)                                  \
6388         : /*in*/    "r" (&_argvec[0])                            \
6389         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6390      );                                                          \
6391      lval = (__typeof__(lval)) (long)_res;                       \
6392   } while (0)
6393
6394#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
6395                                 arg7,arg8)                       \
6396   do {                                                           \
6397      volatile OrigFn        _orig = (orig);                      \
6398      volatile unsigned long long _argvec[9];                     \
6399      volatile unsigned long long _res;                           \
6400      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6401      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6402      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6403      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6404      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6405      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6406      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6407      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6408      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6409      __asm__ volatile(                                           \
6410         "ld $4, 8(%1)\n\t"                                       \
6411         "ld $5, 16(%1)\n\t"                                      \
6412         "ld $6, 24(%1)\n\t"                                      \
6413         "ld $7, 32(%1)\n\t"                                      \
6414         "ld $8, 40(%1)\n\t"                                      \
6415         "ld $9, 48(%1)\n\t"                                      \
6416         "ld $10, 56(%1)\n\t"                                     \
6417         "ld $11, 64(%1)\n\t"                                     \
6418         "ld $25, 0(%1) \n\t"  /* target->t9 */                   \
6419         VALGRIND_CALL_NOREDIR_T9                                 \
6420         "move %0, $2\n"                                          \
6421         : /*out*/   "=r" (_res)                                  \
6422         : /*in*/    "r" (&_argvec[0])                            \
6423         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6424      );                                                          \
6425      lval = (__typeof__(lval)) (long)_res;                       \
6426   } while (0)
6427
6428#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
6429                                 arg7,arg8,arg9)                  \
6430   do {                                                           \
6431      volatile OrigFn        _orig = (orig);                      \
6432      volatile unsigned long long _argvec[10];                    \
6433      volatile unsigned long long _res;                           \
6434      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6435      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6436      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6437      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6438      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6439      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6440      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6441      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6442      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6443      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
6444      __asm__ volatile(                                           \
6445         "dsubu $29, $29, 8\n\t"                                  \
6446         "ld $4, 72(%1)\n\t"                                      \
6447         "sd $4, 0($29)\n\t"                                      \
6448         "ld $4, 8(%1)\n\t"                                       \
6449         "ld $5, 16(%1)\n\t"                                      \
6450         "ld $6, 24(%1)\n\t"                                      \
6451         "ld $7, 32(%1)\n\t"                                      \
6452         "ld $8, 40(%1)\n\t"                                      \
6453         "ld $9, 48(%1)\n\t"                                      \
6454         "ld $10, 56(%1)\n\t"                                     \
6455         "ld $11, 64(%1)\n\t"                                     \
6456         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6457         VALGRIND_CALL_NOREDIR_T9                                 \
6458         "daddu $29, $29, 8\n\t"                                  \
6459         "move %0, $2\n"                                          \
6460         : /*out*/   "=r" (_res)                                  \
6461         : /*in*/    "r" (&_argvec[0])                            \
6462         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6463      );                                                          \
6464      lval = (__typeof__(lval)) (long)_res;                       \
6465   } while (0)
6466
6467#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
6468                                  arg7,arg8,arg9,arg10)           \
6469   do {                                                           \
6470      volatile OrigFn        _orig = (orig);                      \
6471      volatile unsigned long long _argvec[11];                    \
6472      volatile unsigned long long _res;                           \
6473      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6474      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6475      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6476      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6477      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6478      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6479      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6480      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6481      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6482      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
6483      _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
6484      __asm__ volatile(                                           \
6485         "dsubu $29, $29, 16\n\t"                                 \
6486         "ld $4, 72(%1)\n\t"                                      \
6487         "sd $4, 0($29)\n\t"                                      \
6488         "ld $4, 80(%1)\n\t"                                      \
6489         "sd $4, 8($29)\n\t"                                      \
6490         "ld $4, 8(%1)\n\t"                                       \
6491         "ld $5, 16(%1)\n\t"                                      \
6492         "ld $6, 24(%1)\n\t"                                      \
6493         "ld $7, 32(%1)\n\t"                                      \
6494         "ld $8, 40(%1)\n\t"                                      \
6495         "ld $9, 48(%1)\n\t"                                      \
6496         "ld $10, 56(%1)\n\t"                                     \
6497         "ld $11, 64(%1)\n\t"                                     \
6498         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6499         VALGRIND_CALL_NOREDIR_T9                                 \
6500         "daddu $29, $29, 16\n\t"                                 \
6501         "move %0, $2\n"                                          \
6502         : /*out*/   "=r" (_res)                                  \
6503         : /*in*/    "r" (&_argvec[0])                            \
6504         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6505      );                                                          \
6506      lval = (__typeof__(lval)) (long)_res;                       \
6507   } while (0)
6508
6509#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
6510                                  arg6,arg7,arg8,arg9,arg10,      \
6511                                  arg11)                          \
6512   do {                                                           \
6513      volatile OrigFn        _orig = (orig);                      \
6514      volatile unsigned long long _argvec[12];                    \
6515      volatile unsigned long long _res;                           \
6516      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6517      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6518      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6519      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6520      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6521      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6522      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6523      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6524      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6525      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
6526      _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
6527      _argvec[11] = MIPS64_LONG2REG_CAST(arg11);                  \
6528      __asm__ volatile(                                           \
6529         "dsubu $29, $29, 24\n\t"                                 \
6530         "ld $4, 72(%1)\n\t"                                      \
6531         "sd $4, 0($29)\n\t"                                      \
6532         "ld $4, 80(%1)\n\t"                                      \
6533         "sd $4, 8($29)\n\t"                                      \
6534         "ld $4, 88(%1)\n\t"                                      \
6535         "sd $4, 16($29)\n\t"                                     \
6536         "ld $4, 8(%1)\n\t"                                       \
6537         "ld $5, 16(%1)\n\t"                                      \
6538         "ld $6, 24(%1)\n\t"                                      \
6539         "ld $7, 32(%1)\n\t"                                      \
6540         "ld $8, 40(%1)\n\t"                                      \
6541         "ld $9, 48(%1)\n\t"                                      \
6542         "ld $10, 56(%1)\n\t"                                     \
6543         "ld $11, 64(%1)\n\t"                                     \
6544         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6545         VALGRIND_CALL_NOREDIR_T9                                 \
6546         "daddu $29, $29, 24\n\t"                                 \
6547         "move %0, $2\n"                                          \
6548         : /*out*/   "=r" (_res)                                  \
6549         : /*in*/    "r" (&_argvec[0])                            \
6550         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6551      );                                                          \
6552      lval = (__typeof__(lval)) (long)_res;                       \
6553   } while (0)
6554
6555#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
6556                                  arg6,arg7,arg8,arg9,arg10,      \
6557                                  arg11,arg12)                    \
6558   do {                                                           \
6559      volatile OrigFn        _orig = (orig);                      \
6560      volatile unsigned long long _argvec[13];                    \
6561      volatile unsigned long long _res;                           \
6562      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6563      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6564      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6565      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6566      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6567      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6568      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6569      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6570      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6571      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
6572      _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
6573      _argvec[11] = MIPS64_LONG2REG_CAST(arg11);                  \
6574      _argvec[12] = MIPS64_LONG2REG_CAST(arg12);                  \
6575      __asm__ volatile(                                           \
6576         "dsubu $29, $29, 32\n\t"                                 \
6577         "ld $4, 72(%1)\n\t"                                      \
6578         "sd $4, 0($29)\n\t"                                      \
6579         "ld $4, 80(%1)\n\t"                                      \
6580         "sd $4, 8($29)\n\t"                                      \
6581         "ld $4, 88(%1)\n\t"                                      \
6582         "sd $4, 16($29)\n\t"                                     \
6583         "ld $4, 96(%1)\n\t"                                      \
6584         "sd $4, 24($29)\n\t"                                     \
6585         "ld $4, 8(%1)\n\t"                                       \
6586         "ld $5, 16(%1)\n\t"                                      \
6587         "ld $6, 24(%1)\n\t"                                      \
6588         "ld $7, 32(%1)\n\t"                                      \
6589         "ld $8, 40(%1)\n\t"                                      \
6590         "ld $9, 48(%1)\n\t"                                      \
6591         "ld $10, 56(%1)\n\t"                                     \
6592         "ld $11, 64(%1)\n\t"                                     \
6593         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6594         VALGRIND_CALL_NOREDIR_T9                                 \
6595         "daddu $29, $29, 32\n\t"                                 \
6596         "move %0, $2\n"                                          \
6597         : /*out*/   "=r" (_res)                                  \
6598         : /*in*/    "r" (&_argvec[0])                            \
6599         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6600      );                                                          \
6601      lval = (__typeof__(lval)) (long)_res;                       \
6602   } while (0)
6603
6604#endif /* PLAT_mips64_linux */
6605
6606/* ------------------------------------------------------------------ */
6607/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
6608/*                                                                    */
6609/* ------------------------------------------------------------------ */
6610
6611/* Some request codes.  There are many more of these, but most are not
6612   exposed to end-user view.  These are the public ones, all of the
6613   form 0x1000 + small_number.
6614
6615   Core ones are in the range 0x00000000--0x0000ffff.  The non-public
6616   ones start at 0x2000.
6617*/
6618
6619/* These macros are used by tools -- they must be public, but don't
6620   embed them into other programs. */
6621#define VG_USERREQ_TOOL_BASE(a,b) \
6622   ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
6623#define VG_IS_TOOL_USERREQ(a, b, v) \
6624   (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
6625
6626/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
6627   This enum comprises an ABI exported by Valgrind to programs
6628   which use client requests.  DO NOT CHANGE THE NUMERIC VALUES OF THESE
6629   ENTRIES, NOR DELETE ANY -- add new ones at the end of the most
6630   relevant group. */
6631typedef
6632   enum { VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
6633          VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
6634
6635          /* These allow any function to be called from the simulated
6636             CPU but run on the real CPU.  Nb: the first arg passed to
6637             the function is always the ThreadId of the running
6638             thread!  So CLIENT_CALL0 actually requires a 1 arg
6639             function, etc. */
6640          VG_USERREQ__CLIENT_CALL0 = 0x1101,
6641          VG_USERREQ__CLIENT_CALL1 = 0x1102,
6642          VG_USERREQ__CLIENT_CALL2 = 0x1103,
6643          VG_USERREQ__CLIENT_CALL3 = 0x1104,
6644
6645          /* Can be useful in regression testing suites -- eg. can
6646             send Valgrind's output to /dev/null and still count
6647             errors. */
6648          VG_USERREQ__COUNT_ERRORS = 0x1201,
6649
6650          /* Allows the client program and/or gdbserver to execute a monitor
6651             command. */
6652          VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
6653
6654          /* Allows the client program to change a dynamic command line
6655             option.  */
6656          VG_USERREQ__CLO_CHANGE = 0x1203,
6657
6658          /* These are useful and can be interpreted by any tool that
6659             tracks malloc() et al, by using vg_replace_malloc.c. */
6660          VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
6661          VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
6662          VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
6663          /* Memory pool support. */
6664          VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
6665          VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
6666          VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
6667          VG_USERREQ__MEMPOOL_FREE     = 0x1306,
6668          VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
6669          VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
6670          VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
6671          VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
6672
6673          /* Allow printfs to valgrind log. */
6674          /* The first two pass the va_list argument by value, which
6675             assumes it is the same size as or smaller than a UWord,
6676             which generally isn't the case.  Hence are deprecated.
6677             The second two pass the vargs by reference and so are
6678             immune to this problem. */
6679          /* both :: char* fmt, va_list vargs (DEPRECATED) */
6680          VG_USERREQ__PRINTF           = 0x1401,
6681          VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
6682          /* both :: char* fmt, va_list* vargs */
6683          VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
6684          VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
6685
6686          /* Stack support. */
6687          VG_USERREQ__STACK_REGISTER   = 0x1501,
6688          VG_USERREQ__STACK_DEREGISTER = 0x1502,
6689          VG_USERREQ__STACK_CHANGE     = 0x1503,
6690
6691          /* Wine support */
6692          VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
6693
6694          /* Querying of debug info. */
6695          VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
6696
6697          /* Disable/enable error reporting level.  Takes a single
6698             Word arg which is the delta to this thread's error
6699             disablement indicator.  Hence 1 disables or further
6700             disables errors, and -1 moves back towards enablement.
6701             Other values are not allowed. */
6702          VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
6703
6704          /* Some requests used for Valgrind internal, such as
6705             self-test or self-hosting. */
6706          /* Initialise IR injection */
6707          VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901,
6708          /* Used by Inner Valgrind to inform Outer Valgrind where to
6709             find the list of inner guest threads */
6710          VG_USERREQ__INNER_THREADS    = 0x1902
6711   } Vg_ClientRequest;
6712
6713#if !defined(__GNUC__)
6714#  define __extension__ /* */
6715#endif
6716
6717
6718/* Returns the number of Valgrinds this code is running under.  That
6719   is, 0 if running natively, 1 if running under Valgrind, 2 if
6720   running under Valgrind which is running under another Valgrind,
6721   etc. */
6722#define RUNNING_ON_VALGRIND                                           \
6723    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */,         \
6724                                    VG_USERREQ__RUNNING_ON_VALGRIND,  \
6725                                    0, 0, 0, 0, 0)                    \
6726
6727
6728/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
6729   _qzz_len - 1].  Useful if you are debugging a JITter or some such,
6730   since it provides a way to make sure valgrind will retranslate the
6731   invalidated area.  Returns no value. */
6732#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len)              \
6733    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS,  \
6734                                    _qzz_addr, _qzz_len, 0, 0, 0)
6735
6736#define VALGRIND_INNER_THREADS(_qzz_addr)                               \
6737   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__INNER_THREADS,           \
6738                                   _qzz_addr, 0, 0, 0, 0)
6739
6740
6741/* These requests are for getting Valgrind itself to print something.
6742   Possibly with a backtrace.  This is a really ugly hack.  The return value
6743   is the number of characters printed, excluding the "**<pid>** " part at the
6744   start and the backtrace (if present). */
6745
6746#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6747/* Modern GCC will optimize the static routine out if unused,
6748   and unused attribute will shut down warnings about it.  */
6749static int VALGRIND_PRINTF(const char *format, ...)
6750   __attribute__((format(__printf__, 1, 2), __unused__));
6751#endif
6752static int
6753#if defined(_MSC_VER)
6754__inline
6755#endif
6756VALGRIND_PRINTF(const char *format, ...)
6757{
6758#if defined(NVALGRIND)
6759   (void)format;
6760   return 0;
6761#else /* NVALGRIND */
6762#if defined(_MSC_VER) || defined(__MINGW64__)
6763   uintptr_t _qzz_res;
6764#else
6765   unsigned long _qzz_res;
6766#endif
6767   va_list vargs;
6768   va_start(vargs, format);
6769#if defined(_MSC_VER) || defined(__MINGW64__)
6770   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6771                              VG_USERREQ__PRINTF_VALIST_BY_REF,
6772                              (uintptr_t)format,
6773                              (uintptr_t)&vargs,
6774                              0, 0, 0);
6775#else
6776   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6777                              VG_USERREQ__PRINTF_VALIST_BY_REF,
6778                              (unsigned long)format,
6779                              (unsigned long)&vargs,
6780                              0, 0, 0);
6781#endif
6782   va_end(vargs);
6783   return (int)_qzz_res;
6784#endif /* NVALGRIND */
6785}
6786
6787#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6788static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6789   __attribute__((format(__printf__, 1, 2), __unused__));
6790#endif
6791static int
6792#if defined(_MSC_VER)
6793__inline
6794#endif
6795VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6796{
6797#if defined(NVALGRIND)
6798   (void)format;
6799   return 0;
6800#else /* NVALGRIND */
6801#if defined(_MSC_VER) || defined(__MINGW64__)
6802   uintptr_t _qzz_res;
6803#else
6804   unsigned long _qzz_res;
6805#endif
6806   va_list vargs;
6807   va_start(vargs, format);
6808#if defined(_MSC_VER) || defined(__MINGW64__)
6809   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6810                              VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6811                              (uintptr_t)format,
6812                              (uintptr_t)&vargs,
6813                              0, 0, 0);
6814#else
6815   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6816                              VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6817                              (unsigned long)format,
6818                              (unsigned long)&vargs,
6819                              0, 0, 0);
6820#endif
6821   va_end(vargs);
6822   return (int)_qzz_res;
6823#endif /* NVALGRIND */
6824}
6825
6826
6827/* These requests allow control to move from the simulated CPU to the
6828   real CPU, calling an arbitrary function.
6829
6830   Note that the current ThreadId is inserted as the first argument.
6831   So this call:
6832
6833     VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
6834
6835   requires f to have this signature:
6836
6837     Word f(Word tid, Word arg1, Word arg2)
6838
6839   where "Word" is a word-sized type.
6840
6841   Note that these client requests are not entirely reliable.  For example,
6842   if you call a function with them that subsequently calls printf(),
6843   there's a high chance Valgrind will crash.  Generally, your prospects of
6844   these working are made higher if the called function does not refer to
6845   any global variables, and does not refer to any libc or other functions
6846   (printf et al).  Any kind of entanglement with libc or dynamic linking is
6847   likely to have a bad outcome, for tricky reasons which we've grappled
6848   with a lot in the past.
6849*/
6850#define VALGRIND_NON_SIMD_CALL0(_qyy_fn)                          \
6851    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,       \
6852                                    VG_USERREQ__CLIENT_CALL0,     \
6853                                    _qyy_fn,                      \
6854                                    0, 0, 0, 0)
6855
6856#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1)                    \
6857    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,            \
6858                                    VG_USERREQ__CLIENT_CALL1,          \
6859                                    _qyy_fn,                           \
6860                                    _qyy_arg1, 0, 0, 0)
6861
6862#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2)         \
6863    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,            \
6864                                    VG_USERREQ__CLIENT_CALL2,          \
6865                                    _qyy_fn,                           \
6866                                    _qyy_arg1, _qyy_arg2, 0, 0)
6867
6868#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
6869    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,             \
6870                                    VG_USERREQ__CLIENT_CALL3,           \
6871                                    _qyy_fn,                            \
6872                                    _qyy_arg1, _qyy_arg2,               \
6873                                    _qyy_arg3, 0)
6874
6875
6876/* Counts the number of errors that have been recorded by a tool.  Nb:
6877   the tool must record the errors with VG_(maybe_record_error)() or
6878   VG_(unique_error)() for them to be counted. */
6879#define VALGRIND_COUNT_ERRORS                                     \
6880    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(                    \
6881                               0 /* default return */,            \
6882                               VG_USERREQ__COUNT_ERRORS,          \
6883                               0, 0, 0, 0, 0)
6884
6885/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
6886   when heap blocks are allocated in order to give accurate results.  This
6887   happens automatically for the standard allocator functions such as
6888   malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
6889   delete[], etc.
6890
6891   But if your program uses a custom allocator, this doesn't automatically
6892   happen, and Valgrind will not do as well.  For example, if you allocate
6893   superblocks with mmap() and then allocates chunks of the superblocks, all
6894   Valgrind's observations will be at the mmap() level and it won't know that
6895   the chunks should be considered separate entities.  In Memcheck's case,
6896   that means you probably won't get heap block overrun detection (because
6897   there won't be redzones marked as unaddressable) and you definitely won't
6898   get any leak detection.
6899
6900   The following client requests allow a custom allocator to be annotated so
6901   that it can be handled accurately by Valgrind.
6902
6903   VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
6904   by a malloc()-like function.  For Memcheck (an illustrative case), this
6905   does two things:
6906
6907   - It records that the block has been allocated.  This means any addresses
6908     within the block mentioned in error messages will be
6909     identified as belonging to the block.  It also means that if the block
6910     isn't freed it will be detected by the leak checker.
6911
6912   - It marks the block as being addressable and undefined (if 'is_zeroed' is
6913     not set), or addressable and defined (if 'is_zeroed' is set).  This
6914     controls how accesses to the block by the program are handled.
6915
6916   'addr' is the start of the usable block (ie. after any
6917   redzone), 'sizeB' is its size.  'rzB' is the redzone size if the allocator
6918   can apply redzones -- these are blocks of padding at the start and end of
6919   each block.  Adding redzones is recommended as it makes it much more likely
6920   Valgrind will spot block overruns.  `is_zeroed' indicates if the memory is
6921   zeroed (or filled with another predictable value), as is the case for
6922   calloc().
6923
6924   VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
6925   heap block -- that will be used by the client program -- is allocated.
6926   It's best to put it at the outermost level of the allocator if possible;
6927   for example, if you have a function my_alloc() which calls
6928   internal_alloc(), and the client request is put inside internal_alloc(),
6929   stack traces relating to the heap block will contain entries for both
6930   my_alloc() and internal_alloc(), which is probably not what you want.
6931
6932   For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
6933   custom blocks from within a heap block, B, that has been allocated with
6934   malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
6935   -- the custom blocks will take precedence.
6936
6937   VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK.  For
6938   Memcheck, it does two things:
6939
6940   - It records that the block has been deallocated.  This assumes that the
6941     block was annotated as having been allocated via
6942     VALGRIND_MALLOCLIKE_BLOCK.  Otherwise, an error will be issued.
6943
6944   - It marks the block as being unaddressable.
6945
6946   VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
6947   heap block is deallocated.
6948
6949   VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
6950   Memcheck, it does four things:
6951
6952   - It records that the size of a block has been changed.  This assumes that
6953     the block was annotated as having been allocated via
6954     VALGRIND_MALLOCLIKE_BLOCK.  Otherwise, an error will be issued.
6955
6956   - If the block shrunk, it marks the freed memory as being unaddressable.
6957
6958   - If the block grew, it marks the new area as undefined and defines a red
6959     zone past the end of the new block.
6960
6961   - The V-bits of the overlap between the old and the new block are preserved.
6962
6963   VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
6964   and before deallocation of the old block.
6965
6966   In many cases, these three client requests will not be enough to get your
6967   allocator working well with Memcheck.  More specifically, if your allocator
6968   writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
6969   will be necessary to mark the memory as addressable just before the zeroing
6970   occurs, otherwise you'll get a lot of invalid write errors.  For example,
6971   you'll need to do this if your allocator recycles freed blocks, but it
6972   zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
6973   Alternatively, if your allocator reuses freed blocks for allocator-internal
6974   data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
6975
6976   Really, what's happening is a blurring of the lines between the client
6977   program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
6978   memory should be considered unaddressable to the client program, but the
6979   allocator knows more than the rest of the client program and so may be able
6980   to safely access it.  Extra client requests are necessary for Valgrind to
6981   understand the distinction between the allocator and the rest of the
6982   program.
6983
6984   Ignored if addr == 0.
6985*/
6986#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)          \
6987    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK,       \
6988                                    addr, sizeB, rzB, is_zeroed, 0)
6989
6990/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6991   Ignored if addr == 0.
6992*/
6993#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB)     \
6994    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK,    \
6995                                    addr, oldSizeB, newSizeB, rzB, 0)
6996
6997/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6998   Ignored if addr == 0.
6999*/
7000#define VALGRIND_FREELIKE_BLOCK(addr, rzB)                              \
7001    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK,         \
7002                                    addr, rzB, 0, 0, 0)
7003
7004/* Create a memory pool. */
7005#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)             \
7006    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL,   \
7007                                    pool, rzB, is_zeroed, 0, 0)
7008
7009/* Create a memory pool with some flags specifying extended behaviour.
7010   When flags is zero, the behaviour is identical to VALGRIND_CREATE_MEMPOOL.
7011
7012   The flag VALGRIND_MEMPOOL_METAPOOL specifies that the pieces of memory
7013   associated with the pool using VALGRIND_MEMPOOL_ALLOC  will be used
7014   by the application as superblocks to dole out MALLOC_LIKE blocks using
7015   VALGRIND_MALLOCLIKE_BLOCK. In other words, a meta pool is a "2 levels"
7016   pool : first level is the blocks described by VALGRIND_MEMPOOL_ALLOC.
7017   The second level blocks are described using VALGRIND_MALLOCLIKE_BLOCK.
7018   Note that the association between the pool and the second level blocks
7019   is implicit : second level blocks will be located inside first level
7020   blocks. It is necessary to use the VALGRIND_MEMPOOL_METAPOOL flag
7021   for such 2 levels pools, as otherwise valgrind will detect overlapping
7022   memory blocks, and will abort execution (e.g. during leak search).
7023
7024   Such a meta pool can also be marked as an 'auto free' pool using the flag
7025   VALGRIND_MEMPOOL_AUTO_FREE, which must be OR-ed together with the
7026   VALGRIND_MEMPOOL_METAPOOL. For an 'auto free' pool, VALGRIND_MEMPOOL_FREE
7027   will automatically free the second level blocks that are contained
7028   inside the first level block freed with VALGRIND_MEMPOOL_FREE.
7029   In other words, calling VALGRIND_MEMPOOL_FREE will cause implicit calls
7030   to VALGRIND_FREELIKE_BLOCK for all the second level blocks included
7031   in the first level block.
7032   Note: it is an error to use the VALGRIND_MEMPOOL_AUTO_FREE flag
7033   without the VALGRIND_MEMPOOL_METAPOOL flag.
7034*/
7035#define VALGRIND_MEMPOOL_AUTO_FREE  1
7036#define VALGRIND_MEMPOOL_METAPOOL   2
7037#define VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags)        \
7038   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL,          \
7039                                   pool, rzB, is_zeroed, flags, 0)
7040
7041/* Destroy a memory pool. */
7042#define VALGRIND_DESTROY_MEMPOOL(pool)                            \
7043    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL,  \
7044                                    pool, 0, 0, 0, 0)
7045
7046/* Associate a piece of memory with a memory pool. */
7047#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)                  \
7048    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC,    \
7049                                    pool, addr, size, 0, 0)
7050
7051/* Disassociate a piece of memory from a memory pool. */
7052#define VALGRIND_MEMPOOL_FREE(pool, addr)                         \
7053    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE,     \
7054                                    pool, addr, 0, 0, 0)
7055
7056/* Disassociate any pieces outside a particular range. */
7057#define VALGRIND_MEMPOOL_TRIM(pool, addr, size)                   \
7058    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM,     \
7059                                    pool, addr, size, 0, 0)
7060
7061/* Resize and/or move a piece associated with a memory pool. */
7062#define VALGRIND_MOVE_MEMPOOL(poolA, poolB)                       \
7063    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL,     \
7064                                    poolA, poolB, 0, 0, 0)
7065
7066/* Resize and/or move a piece associated with a memory pool. */
7067#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size)         \
7068    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE,   \
7069                                    pool, addrA, addrB, size, 0)
7070
7071/* Return 1 if a mempool exists, else 0. */
7072#define VALGRIND_MEMPOOL_EXISTS(pool)                             \
7073    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
7074                               VG_USERREQ__MEMPOOL_EXISTS,        \
7075                               pool, 0, 0, 0, 0)
7076
7077/* Mark a piece of memory as being a stack. Returns a stack id.
7078   start is the lowest addressable stack byte, end is the highest
7079   addressable stack byte. */
7080#define VALGRIND_STACK_REGISTER(start, end)                       \
7081    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
7082                               VG_USERREQ__STACK_REGISTER,        \
7083                               start, end, 0, 0, 0)
7084
7085/* Unmark the piece of memory associated with a stack id as being a
7086   stack. */
7087#define VALGRIND_STACK_DEREGISTER(id)                             \
7088    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
7089                                    id, 0, 0, 0, 0)
7090
7091/* Change the start and end address of the stack id.
7092   start is the new lowest addressable stack byte, end is the new highest
7093   addressable stack byte. */
7094#define VALGRIND_STACK_CHANGE(id, start, end)                     \
7095    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE,     \
7096                                    id, start, end, 0, 0)
7097
7098/* Load PDB debug info for Wine PE image_map. */
7099#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta)     \
7100    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
7101                                    fd, ptr, total_size, delta, 0)
7102
7103/* Map a code address to a source file name and line number.  buf64
7104   must point to a 64-byte buffer in the caller's address space.  The
7105   result will be dumped in there and is guaranteed to be zero
7106   terminated.  If no info is found, the first byte is set to zero. */
7107#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64)                    \
7108    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
7109                               VG_USERREQ__MAP_IP_TO_SRCLOC,      \
7110                               addr, buf64, 0, 0, 0)
7111
7112/* Disable error reporting for this thread.  Behaves in a stack like
7113   way, so you can safely call this multiple times provided that
7114   VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
7115   to re-enable reporting.  The first call of this macro disables
7116   reporting.  Subsequent calls have no effect except to increase the
7117   number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
7118   reporting.  Child threads do not inherit this setting from their
7119   parents -- they are always created with reporting enabled. */
7120#define VALGRIND_DISABLE_ERROR_REPORTING                                \
7121    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
7122                                    1, 0, 0, 0, 0)
7123
7124/* Re-enable error reporting, as per comments on
7125   VALGRIND_DISABLE_ERROR_REPORTING. */
7126#define VALGRIND_ENABLE_ERROR_REPORTING                                 \
7127    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
7128                                    -1, 0, 0, 0, 0)
7129
7130/* Execute a monitor command from the client program.
7131   If a connection is opened with GDB, the output will be sent
7132   according to the output mode set for vgdb.
7133   If no connection is opened, output will go to the log output.
7134   Returns 1 if command not recognised, 0 otherwise. */
7135#define VALGRIND_MONITOR_COMMAND(command)                               \
7136   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
7137                                   command, 0, 0, 0, 0)
7138
7139
7140/* Change the value of a dynamic command line option.
7141   Note that unknown or not dynamically changeable options
7142   will cause a warning message to be output.  */
7143#define VALGRIND_CLO_CHANGE(option)                           \
7144   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CLO_CHANGE, \
7145                                   option, 0, 0, 0, 0)
7146
7147
7148#undef PLAT_x86_darwin
7149#undef PLAT_amd64_darwin
7150#undef PLAT_x86_win32
7151#undef PLAT_amd64_win64
7152#undef PLAT_x86_linux
7153#undef PLAT_amd64_linux
7154#undef PLAT_ppc32_linux
7155#undef PLAT_ppc64be_linux
7156#undef PLAT_ppc64le_linux
7157#undef PLAT_arm_linux
7158#undef PLAT_s390x_linux
7159#undef PLAT_mips32_linux
7160#undef PLAT_mips64_linux
7161#undef PLAT_nanomips_linux
7162#undef PLAT_x86_solaris
7163#undef PLAT_amd64_solaris
7164
7165#endif   /* __VALGRIND_H */
7166