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