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