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