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