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-2008 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
179typedef
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
233typedef
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
287typedef
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
347typedef
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
413typedef
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
485typedef
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. */
3588typedef
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.  */
3672static int VALGRIND_PRINTF(const char *format, ...)
3673   __attribute__((format(__printf__, 1, 2), __unused__));
3674static int
3675VALGRIND_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
3687static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3688   __attribute__((format(__printf__, 1, 2), __unused__));
3689static int
3690VALGRIND_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 arbitary 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