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