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