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