2 ----------------------------------------------------------------
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.
10 ----------------------------------------------------------------
12 This file is part of Valgrind, a dynamic binary instrumentation
15 Copyright (C) 2000-2009 Julian Seward. All rights reserved.
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
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.
29 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
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
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.
48 ----------------------------------------------------------------
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.
55 ----------------------------------------------------------------
59 /* This file is for inclusion into client (your!) code.
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
67 consumes very few (eg. 7) instructions, so the resulting performance
68 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
78 /* Nb: this file might be included in a file compiled with -ansi. So
79 we can't use C++ style "//" comments nor the "asm" keyword (instead
82 /* Derive some tags indicating what the target platform is. Note
83 that in this file we're using the compiler's CPP symbols for
84 identifying architectures, which are different to the ones we use
85 within the rest of Valgrind. Note, __powerpc__ is active for both
86 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
87 latter (on Linux, that is). */
89 #undef PLAT_amd64_linux
90 #undef PLAT_ppc32_linux
91 #undef PLAT_ppc64_linux
92 #undef PLAT_ppc32_aix5
93 #undef PLAT_ppc64_aix5
96 #if defined(_AIX) && defined(__64BIT__)
97 # define PLAT_ppc64_aix5 1
98 #elif defined(_AIX) && !defined(__64BIT__)
99 # define PLAT_ppc32_aix5 1
100 #elif defined(__APPLE__) && defined(__i386__)
101 # define PLAT_x86_darwin 1
102 #elif defined(__APPLE__) && defined(__x86_64__)
103 # define PLAT_amd64_darwin 1
104 #elif defined(__i386__)
105 # define PLAT_x86_linux 1
106 #elif defined(__x86_64__)
107 # define PLAT_amd64_linux 1
108 #elif defined(__powerpc__) && !defined(__powerpc64__)
109 # define PLAT_ppc32_linux 1
110 #elif defined(__powerpc__) && defined(__powerpc64__)
111 # define PLAT_ppc64_linux 1
113 /* If we're not compiling for our target platform, don't generate
115 # if !defined(NVALGRIND)
121 /* ------------------------------------------------------------------ */
122 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
123 /* in here of use to end-users -- skip to the next section. */
124 /* ------------------------------------------------------------------ */
126 #if defined(NVALGRIND)
128 /* Define NVALGRIND to completely remove the Valgrind magic sequence
129 from the compiled code (analogous to NDEBUG's effects on
131 #define VALGRIND_DO_CLIENT_REQUEST( \
132 _zzq_rlval, _zzq_default, _zzq_request, \
133 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
135 (_zzq_rlval) = (_zzq_default); \
138 #else /* ! NVALGRIND */
140 /* The following defines the magic code sequences which the JITter
141 spots and handles magically. Don't look too closely at them as
142 they will rot your brain.
144 The assembly code sequences for all architectures is in this one
145 file. This is because this file must be stand-alone, and we don't
146 want to have multiple files.
148 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
149 value gets put in the return slot, so that everything works when
150 this is executed not under Valgrind. Args are passed in a memory
151 block, and so there's no intrinsic limit to the number that could
152 be passed, but it's currently five.
155 _zzq_rlval result lvalue
156 _zzq_default default value (result returned when running on real CPU)
157 _zzq_request request code
158 _zzq_arg1..5 request params
160 The other two macros are used to support function wrapping, and are
161 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
162 guest's NRADDR pseudo-register and whatever other information is
163 needed to safely run the call original from the wrapper: on
164 ppc64-linux, the R2 value at the divert point is also needed. This
165 information is abstracted into a user-visible type, OrigFn.
167 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
168 guest, but guarantees that the branch instruction will not be
169 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
170 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
171 complete inline asm, since it needs to be combined with more magic
172 inline asm stuff to be useful.
175 /* ------------------------- x86-{linux,darwin} ---------------- */
177 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
181 unsigned int nraddr; /* where's the code? */
185 #define __SPECIAL_INSTRUCTION_PREAMBLE \
186 "roll $3, %%edi ; roll $13, %%edi\n\t" \
187 "roll $29, %%edi ; roll $19, %%edi\n\t"
189 #define VALGRIND_DO_CLIENT_REQUEST( \
190 _zzq_rlval, _zzq_default, _zzq_request, \
191 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
192 { volatile unsigned int _zzq_args[6]; \
193 volatile unsigned int _zzq_result; \
194 _zzq_args[0] = (unsigned int)(_zzq_request); \
195 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
196 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
197 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
198 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
199 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
200 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
201 /* %EDX = client_request ( %EAX ) */ \
202 "xchgl %%ebx,%%ebx" \
203 : "=d" (_zzq_result) \
204 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
207 _zzq_rlval = _zzq_result; \
210 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
211 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
212 volatile unsigned int __addr; \
213 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
214 /* %EAX = guest_NRADDR */ \
215 "xchgl %%ecx,%%ecx" \
220 _zzq_orig->nraddr = __addr; \
223 #define VALGRIND_CALL_NOREDIR_EAX \
224 __SPECIAL_INSTRUCTION_PREAMBLE \
225 /* call-noredir *%EAX */ \
226 "xchgl %%edx,%%edx\n\t"
227 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
229 /* ------------------------ amd64-{linux,darwin} --------------- */
231 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
235 unsigned long long int nraddr; /* where's the code? */
239 #define __SPECIAL_INSTRUCTION_PREAMBLE \
240 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
241 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
243 #define VALGRIND_DO_CLIENT_REQUEST( \
244 _zzq_rlval, _zzq_default, _zzq_request, \
245 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
246 { volatile unsigned long long int _zzq_args[6]; \
247 volatile unsigned long long int _zzq_result; \
248 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
249 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
250 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
251 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
252 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
253 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
254 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
255 /* %RDX = client_request ( %RAX ) */ \
256 "xchgq %%rbx,%%rbx" \
257 : "=d" (_zzq_result) \
258 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
261 _zzq_rlval = _zzq_result; \
264 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
265 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
266 volatile unsigned long long int __addr; \
267 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
268 /* %RAX = guest_NRADDR */ \
269 "xchgq %%rcx,%%rcx" \
274 _zzq_orig->nraddr = __addr; \
277 #define VALGRIND_CALL_NOREDIR_RAX \
278 __SPECIAL_INSTRUCTION_PREAMBLE \
279 /* call-noredir *%RAX */ \
280 "xchgq %%rdx,%%rdx\n\t"
281 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
283 /* ------------------------ ppc32-linux ------------------------ */
285 #if defined(PLAT_ppc32_linux)
289 unsigned int nraddr; /* where's the code? */
293 #define __SPECIAL_INSTRUCTION_PREAMBLE \
294 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
295 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
297 #define VALGRIND_DO_CLIENT_REQUEST( \
298 _zzq_rlval, _zzq_default, _zzq_request, \
299 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
301 { unsigned int _zzq_args[6]; \
302 unsigned int _zzq_result; \
303 unsigned int* _zzq_ptr; \
304 _zzq_args[0] = (unsigned int)(_zzq_request); \
305 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
306 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
307 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
308 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
309 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
310 _zzq_ptr = _zzq_args; \
311 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
312 "mr 4,%2\n\t" /*ptr*/ \
313 __SPECIAL_INSTRUCTION_PREAMBLE \
314 /* %R3 = client_request ( %R4 ) */ \
316 "mr %0,3" /*result*/ \
317 : "=b" (_zzq_result) \
318 : "b" (_zzq_default), "b" (_zzq_ptr) \
319 : "cc", "memory", "r3", "r4"); \
320 _zzq_rlval = _zzq_result; \
323 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
324 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
325 unsigned int __addr; \
326 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
327 /* %R3 = guest_NRADDR */ \
332 : "cc", "memory", "r3" \
334 _zzq_orig->nraddr = __addr; \
337 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
338 __SPECIAL_INSTRUCTION_PREAMBLE \
339 /* branch-and-link-to-noredir *%R11 */ \
341 #endif /* PLAT_ppc32_linux */
343 /* ------------------------ ppc64-linux ------------------------ */
345 #if defined(PLAT_ppc64_linux)
349 unsigned long long int nraddr; /* where's the code? */
350 unsigned long long int r2; /* what tocptr do we need? */
354 #define __SPECIAL_INSTRUCTION_PREAMBLE \
355 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
356 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
358 #define VALGRIND_DO_CLIENT_REQUEST( \
359 _zzq_rlval, _zzq_default, _zzq_request, \
360 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
362 { unsigned long long int _zzq_args[6]; \
363 register unsigned long long int _zzq_result __asm__("r3"); \
364 register unsigned long long int* _zzq_ptr __asm__("r4"); \
365 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
366 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
367 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
368 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
369 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
370 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
371 _zzq_ptr = _zzq_args; \
372 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
373 /* %R3 = client_request ( %R4 ) */ \
375 : "=r" (_zzq_result) \
376 : "0" (_zzq_default), "r" (_zzq_ptr) \
378 _zzq_rlval = _zzq_result; \
381 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
382 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
383 register unsigned long long int __addr __asm__("r3"); \
384 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
385 /* %R3 = guest_NRADDR */ \
391 _zzq_orig->nraddr = __addr; \
392 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
393 /* %R3 = guest_NRADDR_GPR2 */ \
399 _zzq_orig->r2 = __addr; \
402 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
403 __SPECIAL_INSTRUCTION_PREAMBLE \
404 /* branch-and-link-to-noredir *%R11 */ \
407 #endif /* PLAT_ppc64_linux */
409 /* ------------------------ ppc32-aix5 ------------------------- */
411 #if defined(PLAT_ppc32_aix5)
415 unsigned int nraddr; /* where's the code? */
416 unsigned int r2; /* what tocptr do we need? */
420 #define __SPECIAL_INSTRUCTION_PREAMBLE \
421 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
422 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
424 #define VALGRIND_DO_CLIENT_REQUEST( \
425 _zzq_rlval, _zzq_default, _zzq_request, \
426 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
428 { unsigned int _zzq_args[7]; \
429 register unsigned int _zzq_result; \
430 register unsigned int* _zzq_ptr; \
431 _zzq_args[0] = (unsigned int)(_zzq_request); \
432 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
433 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
434 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
435 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
436 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
437 _zzq_args[6] = (unsigned int)(_zzq_default); \
438 _zzq_ptr = _zzq_args; \
439 __asm__ volatile("mr 4,%1\n\t" \
441 __SPECIAL_INSTRUCTION_PREAMBLE \
442 /* %R3 = client_request ( %R4 ) */ \
445 : "=b" (_zzq_result) \
447 : "r3", "r4", "cc", "memory"); \
448 _zzq_rlval = _zzq_result; \
451 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
452 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
453 register unsigned int __addr; \
454 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
455 /* %R3 = guest_NRADDR */ \
460 : "r3", "cc", "memory" \
462 _zzq_orig->nraddr = __addr; \
463 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
464 /* %R3 = guest_NRADDR_GPR2 */ \
469 : "r3", "cc", "memory" \
471 _zzq_orig->r2 = __addr; \
474 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
475 __SPECIAL_INSTRUCTION_PREAMBLE \
476 /* branch-and-link-to-noredir *%R11 */ \
479 #endif /* PLAT_ppc32_aix5 */
481 /* ------------------------ ppc64-aix5 ------------------------- */
483 #if defined(PLAT_ppc64_aix5)
487 unsigned long long int nraddr; /* where's the code? */
488 unsigned long long int r2; /* what tocptr do we need? */
492 #define __SPECIAL_INSTRUCTION_PREAMBLE \
493 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
494 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
496 #define VALGRIND_DO_CLIENT_REQUEST( \
497 _zzq_rlval, _zzq_default, _zzq_request, \
498 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
500 { unsigned long long int _zzq_args[7]; \
501 register unsigned long long int _zzq_result; \
502 register unsigned long long int* _zzq_ptr; \
503 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
504 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
505 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
506 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
507 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
508 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
509 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
510 _zzq_ptr = _zzq_args; \
511 __asm__ volatile("mr 4,%1\n\t" \
513 __SPECIAL_INSTRUCTION_PREAMBLE \
514 /* %R3 = client_request ( %R4 ) */ \
517 : "=b" (_zzq_result) \
519 : "r3", "r4", "cc", "memory"); \
520 _zzq_rlval = _zzq_result; \
523 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
524 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
525 register unsigned long long int __addr; \
526 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
527 /* %R3 = guest_NRADDR */ \
532 : "r3", "cc", "memory" \
534 _zzq_orig->nraddr = __addr; \
535 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
536 /* %R3 = guest_NRADDR_GPR2 */ \
541 : "r3", "cc", "memory" \
543 _zzq_orig->r2 = __addr; \
546 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
547 __SPECIAL_INSTRUCTION_PREAMBLE \
548 /* branch-and-link-to-noredir *%R11 */ \
551 #endif /* PLAT_ppc64_aix5 */
553 /* Insert assembly code for other platforms here... */
555 #endif /* NVALGRIND */
558 /* ------------------------------------------------------------------ */
559 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
560 /* ugly. It's the least-worst tradeoff I can think of. */
561 /* ------------------------------------------------------------------ */
563 /* This section defines magic (a.k.a appalling-hack) macros for doing
564 guaranteed-no-redirection macros, so as to get from function
565 wrappers to the functions they are wrapping. The whole point is to
566 construct standard call sequences, but to do the call itself with a
567 special no-redirect call pseudo-instruction that the JIT
568 understands and handles specially. This section is long and
569 repetitious, and I can't see a way to make it shorter.
571 The naming scheme is as follows:
573 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
575 'W' stands for "word" and 'v' for "void". Hence there are
576 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
577 and for each, the possibility of returning a word-typed result, or
581 /* Use these to write the name of your wrapper. NOTE: duplicates
582 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
584 /* Use an extra level of macroisation so as to ensure the soname/fnname
585 args are fully macro-expanded before pasting them together. */
586 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
588 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
589 VG_CONCAT4(_vgwZU_,soname,_,fnname)
591 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
592 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
594 /* Use this macro from within a wrapper function to collect the
595 context (address and possibly other info) of the original function.
596 Once you have that you can then use it in one of the CALL_FN_
597 macros. The type of the argument _lval is OrigFn. */
598 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
600 /* Derivatives of the main macros below, for calling functions
603 #define CALL_FN_v_v(fnptr) \
604 do { volatile unsigned long _junk; \
605 CALL_FN_W_v(_junk,fnptr); } while (0)
607 #define CALL_FN_v_W(fnptr, arg1) \
608 do { volatile unsigned long _junk; \
609 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
611 #define CALL_FN_v_WW(fnptr, arg1,arg2) \
612 do { volatile unsigned long _junk; \
613 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
615 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
616 do { volatile unsigned long _junk; \
617 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
619 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
620 do { volatile unsigned long _junk; \
621 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
623 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
624 do { volatile unsigned long _junk; \
625 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
627 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
628 do { volatile unsigned long _junk; \
629 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
631 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
632 do { volatile unsigned long _junk; \
633 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
635 /* ------------------------- x86-{linux,darwin} ---------------- */
637 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
639 /* These regs are trashed by the hidden call. No need to mention eax
640 as gcc can already see that, plus causes gcc to bomb. */
641 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
643 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
646 #define CALL_FN_W_v(lval, orig) \
648 volatile OrigFn _orig = (orig); \
649 volatile unsigned long _argvec[1]; \
650 volatile unsigned long _res; \
651 _argvec[0] = (unsigned long)_orig.nraddr; \
653 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
654 VALGRIND_CALL_NOREDIR_EAX \
655 : /*out*/ "=a" (_res) \
656 : /*in*/ "a" (&_argvec[0]) \
657 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
659 lval = (__typeof__(lval)) _res; \
662 #define CALL_FN_W_W(lval, orig, arg1) \
664 volatile OrigFn _orig = (orig); \
665 volatile unsigned long _argvec[2]; \
666 volatile unsigned long _res; \
667 _argvec[0] = (unsigned long)_orig.nraddr; \
668 _argvec[1] = (unsigned long)(arg1); \
670 "pushl 4(%%eax)\n\t" \
671 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
672 VALGRIND_CALL_NOREDIR_EAX \
674 : /*out*/ "=a" (_res) \
675 : /*in*/ "a" (&_argvec[0]) \
676 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
678 lval = (__typeof__(lval)) _res; \
681 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
683 volatile OrigFn _orig = (orig); \
684 volatile unsigned long _argvec[3]; \
685 volatile unsigned long _res; \
686 _argvec[0] = (unsigned long)_orig.nraddr; \
687 _argvec[1] = (unsigned long)(arg1); \
688 _argvec[2] = (unsigned long)(arg2); \
690 "pushl 8(%%eax)\n\t" \
691 "pushl 4(%%eax)\n\t" \
692 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
693 VALGRIND_CALL_NOREDIR_EAX \
695 : /*out*/ "=a" (_res) \
696 : /*in*/ "a" (&_argvec[0]) \
697 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
699 lval = (__typeof__(lval)) _res; \
702 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
704 volatile OrigFn _orig = (orig); \
705 volatile unsigned long _argvec[4]; \
706 volatile unsigned long _res; \
707 _argvec[0] = (unsigned long)_orig.nraddr; \
708 _argvec[1] = (unsigned long)(arg1); \
709 _argvec[2] = (unsigned long)(arg2); \
710 _argvec[3] = (unsigned long)(arg3); \
712 "pushl 12(%%eax)\n\t" \
713 "pushl 8(%%eax)\n\t" \
714 "pushl 4(%%eax)\n\t" \
715 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
716 VALGRIND_CALL_NOREDIR_EAX \
717 "addl $12, %%esp\n" \
718 : /*out*/ "=a" (_res) \
719 : /*in*/ "a" (&_argvec[0]) \
720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
722 lval = (__typeof__(lval)) _res; \
725 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
727 volatile OrigFn _orig = (orig); \
728 volatile unsigned long _argvec[5]; \
729 volatile unsigned long _res; \
730 _argvec[0] = (unsigned long)_orig.nraddr; \
731 _argvec[1] = (unsigned long)(arg1); \
732 _argvec[2] = (unsigned long)(arg2); \
733 _argvec[3] = (unsigned long)(arg3); \
734 _argvec[4] = (unsigned long)(arg4); \
736 "pushl 16(%%eax)\n\t" \
737 "pushl 12(%%eax)\n\t" \
738 "pushl 8(%%eax)\n\t" \
739 "pushl 4(%%eax)\n\t" \
740 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
741 VALGRIND_CALL_NOREDIR_EAX \
742 "addl $16, %%esp\n" \
743 : /*out*/ "=a" (_res) \
744 : /*in*/ "a" (&_argvec[0]) \
745 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
747 lval = (__typeof__(lval)) _res; \
750 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
752 volatile OrigFn _orig = (orig); \
753 volatile unsigned long _argvec[6]; \
754 volatile unsigned long _res; \
755 _argvec[0] = (unsigned long)_orig.nraddr; \
756 _argvec[1] = (unsigned long)(arg1); \
757 _argvec[2] = (unsigned long)(arg2); \
758 _argvec[3] = (unsigned long)(arg3); \
759 _argvec[4] = (unsigned long)(arg4); \
760 _argvec[5] = (unsigned long)(arg5); \
762 "pushl 20(%%eax)\n\t" \
763 "pushl 16(%%eax)\n\t" \
764 "pushl 12(%%eax)\n\t" \
765 "pushl 8(%%eax)\n\t" \
766 "pushl 4(%%eax)\n\t" \
767 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
768 VALGRIND_CALL_NOREDIR_EAX \
769 "addl $20, %%esp\n" \
770 : /*out*/ "=a" (_res) \
771 : /*in*/ "a" (&_argvec[0]) \
772 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
774 lval = (__typeof__(lval)) _res; \
777 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
779 volatile OrigFn _orig = (orig); \
780 volatile unsigned long _argvec[7]; \
781 volatile unsigned long _res; \
782 _argvec[0] = (unsigned long)_orig.nraddr; \
783 _argvec[1] = (unsigned long)(arg1); \
784 _argvec[2] = (unsigned long)(arg2); \
785 _argvec[3] = (unsigned long)(arg3); \
786 _argvec[4] = (unsigned long)(arg4); \
787 _argvec[5] = (unsigned long)(arg5); \
788 _argvec[6] = (unsigned long)(arg6); \
790 "pushl 24(%%eax)\n\t" \
791 "pushl 20(%%eax)\n\t" \
792 "pushl 16(%%eax)\n\t" \
793 "pushl 12(%%eax)\n\t" \
794 "pushl 8(%%eax)\n\t" \
795 "pushl 4(%%eax)\n\t" \
796 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
797 VALGRIND_CALL_NOREDIR_EAX \
798 "addl $24, %%esp\n" \
799 : /*out*/ "=a" (_res) \
800 : /*in*/ "a" (&_argvec[0]) \
801 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
803 lval = (__typeof__(lval)) _res; \
806 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
809 volatile OrigFn _orig = (orig); \
810 volatile unsigned long _argvec[8]; \
811 volatile unsigned long _res; \
812 _argvec[0] = (unsigned long)_orig.nraddr; \
813 _argvec[1] = (unsigned long)(arg1); \
814 _argvec[2] = (unsigned long)(arg2); \
815 _argvec[3] = (unsigned long)(arg3); \
816 _argvec[4] = (unsigned long)(arg4); \
817 _argvec[5] = (unsigned long)(arg5); \
818 _argvec[6] = (unsigned long)(arg6); \
819 _argvec[7] = (unsigned long)(arg7); \
821 "pushl 28(%%eax)\n\t" \
822 "pushl 24(%%eax)\n\t" \
823 "pushl 20(%%eax)\n\t" \
824 "pushl 16(%%eax)\n\t" \
825 "pushl 12(%%eax)\n\t" \
826 "pushl 8(%%eax)\n\t" \
827 "pushl 4(%%eax)\n\t" \
828 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
829 VALGRIND_CALL_NOREDIR_EAX \
830 "addl $28, %%esp\n" \
831 : /*out*/ "=a" (_res) \
832 : /*in*/ "a" (&_argvec[0]) \
833 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
835 lval = (__typeof__(lval)) _res; \
838 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
841 volatile OrigFn _orig = (orig); \
842 volatile unsigned long _argvec[9]; \
843 volatile unsigned long _res; \
844 _argvec[0] = (unsigned long)_orig.nraddr; \
845 _argvec[1] = (unsigned long)(arg1); \
846 _argvec[2] = (unsigned long)(arg2); \
847 _argvec[3] = (unsigned long)(arg3); \
848 _argvec[4] = (unsigned long)(arg4); \
849 _argvec[5] = (unsigned long)(arg5); \
850 _argvec[6] = (unsigned long)(arg6); \
851 _argvec[7] = (unsigned long)(arg7); \
852 _argvec[8] = (unsigned long)(arg8); \
854 "pushl 32(%%eax)\n\t" \
855 "pushl 28(%%eax)\n\t" \
856 "pushl 24(%%eax)\n\t" \
857 "pushl 20(%%eax)\n\t" \
858 "pushl 16(%%eax)\n\t" \
859 "pushl 12(%%eax)\n\t" \
860 "pushl 8(%%eax)\n\t" \
861 "pushl 4(%%eax)\n\t" \
862 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
863 VALGRIND_CALL_NOREDIR_EAX \
864 "addl $32, %%esp\n" \
865 : /*out*/ "=a" (_res) \
866 : /*in*/ "a" (&_argvec[0]) \
867 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
869 lval = (__typeof__(lval)) _res; \
872 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
875 volatile OrigFn _orig = (orig); \
876 volatile unsigned long _argvec[10]; \
877 volatile unsigned long _res; \
878 _argvec[0] = (unsigned long)_orig.nraddr; \
879 _argvec[1] = (unsigned long)(arg1); \
880 _argvec[2] = (unsigned long)(arg2); \
881 _argvec[3] = (unsigned long)(arg3); \
882 _argvec[4] = (unsigned long)(arg4); \
883 _argvec[5] = (unsigned long)(arg5); \
884 _argvec[6] = (unsigned long)(arg6); \
885 _argvec[7] = (unsigned long)(arg7); \
886 _argvec[8] = (unsigned long)(arg8); \
887 _argvec[9] = (unsigned long)(arg9); \
889 "pushl 36(%%eax)\n\t" \
890 "pushl 32(%%eax)\n\t" \
891 "pushl 28(%%eax)\n\t" \
892 "pushl 24(%%eax)\n\t" \
893 "pushl 20(%%eax)\n\t" \
894 "pushl 16(%%eax)\n\t" \
895 "pushl 12(%%eax)\n\t" \
896 "pushl 8(%%eax)\n\t" \
897 "pushl 4(%%eax)\n\t" \
898 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
899 VALGRIND_CALL_NOREDIR_EAX \
900 "addl $36, %%esp\n" \
901 : /*out*/ "=a" (_res) \
902 : /*in*/ "a" (&_argvec[0]) \
903 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
905 lval = (__typeof__(lval)) _res; \
908 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
909 arg7,arg8,arg9,arg10) \
911 volatile OrigFn _orig = (orig); \
912 volatile unsigned long _argvec[11]; \
913 volatile unsigned long _res; \
914 _argvec[0] = (unsigned long)_orig.nraddr; \
915 _argvec[1] = (unsigned long)(arg1); \
916 _argvec[2] = (unsigned long)(arg2); \
917 _argvec[3] = (unsigned long)(arg3); \
918 _argvec[4] = (unsigned long)(arg4); \
919 _argvec[5] = (unsigned long)(arg5); \
920 _argvec[6] = (unsigned long)(arg6); \
921 _argvec[7] = (unsigned long)(arg7); \
922 _argvec[8] = (unsigned long)(arg8); \
923 _argvec[9] = (unsigned long)(arg9); \
924 _argvec[10] = (unsigned long)(arg10); \
926 "pushl 40(%%eax)\n\t" \
927 "pushl 36(%%eax)\n\t" \
928 "pushl 32(%%eax)\n\t" \
929 "pushl 28(%%eax)\n\t" \
930 "pushl 24(%%eax)\n\t" \
931 "pushl 20(%%eax)\n\t" \
932 "pushl 16(%%eax)\n\t" \
933 "pushl 12(%%eax)\n\t" \
934 "pushl 8(%%eax)\n\t" \
935 "pushl 4(%%eax)\n\t" \
936 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
937 VALGRIND_CALL_NOREDIR_EAX \
938 "addl $40, %%esp\n" \
939 : /*out*/ "=a" (_res) \
940 : /*in*/ "a" (&_argvec[0]) \
941 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
943 lval = (__typeof__(lval)) _res; \
946 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
947 arg6,arg7,arg8,arg9,arg10, \
950 volatile OrigFn _orig = (orig); \
951 volatile unsigned long _argvec[12]; \
952 volatile unsigned long _res; \
953 _argvec[0] = (unsigned long)_orig.nraddr; \
954 _argvec[1] = (unsigned long)(arg1); \
955 _argvec[2] = (unsigned long)(arg2); \
956 _argvec[3] = (unsigned long)(arg3); \
957 _argvec[4] = (unsigned long)(arg4); \
958 _argvec[5] = (unsigned long)(arg5); \
959 _argvec[6] = (unsigned long)(arg6); \
960 _argvec[7] = (unsigned long)(arg7); \
961 _argvec[8] = (unsigned long)(arg8); \
962 _argvec[9] = (unsigned long)(arg9); \
963 _argvec[10] = (unsigned long)(arg10); \
964 _argvec[11] = (unsigned long)(arg11); \
966 "pushl 44(%%eax)\n\t" \
967 "pushl 40(%%eax)\n\t" \
968 "pushl 36(%%eax)\n\t" \
969 "pushl 32(%%eax)\n\t" \
970 "pushl 28(%%eax)\n\t" \
971 "pushl 24(%%eax)\n\t" \
972 "pushl 20(%%eax)\n\t" \
973 "pushl 16(%%eax)\n\t" \
974 "pushl 12(%%eax)\n\t" \
975 "pushl 8(%%eax)\n\t" \
976 "pushl 4(%%eax)\n\t" \
977 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
978 VALGRIND_CALL_NOREDIR_EAX \
979 "addl $44, %%esp\n" \
980 : /*out*/ "=a" (_res) \
981 : /*in*/ "a" (&_argvec[0]) \
982 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
984 lval = (__typeof__(lval)) _res; \
987 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
988 arg6,arg7,arg8,arg9,arg10, \
991 volatile OrigFn _orig = (orig); \
992 volatile unsigned long _argvec[13]; \
993 volatile unsigned long _res; \
994 _argvec[0] = (unsigned long)_orig.nraddr; \
995 _argvec[1] = (unsigned long)(arg1); \
996 _argvec[2] = (unsigned long)(arg2); \
997 _argvec[3] = (unsigned long)(arg3); \
998 _argvec[4] = (unsigned long)(arg4); \
999 _argvec[5] = (unsigned long)(arg5); \
1000 _argvec[6] = (unsigned long)(arg6); \
1001 _argvec[7] = (unsigned long)(arg7); \
1002 _argvec[8] = (unsigned long)(arg8); \
1003 _argvec[9] = (unsigned long)(arg9); \
1004 _argvec[10] = (unsigned long)(arg10); \
1005 _argvec[11] = (unsigned long)(arg11); \
1006 _argvec[12] = (unsigned long)(arg12); \
1008 "pushl 48(%%eax)\n\t" \
1009 "pushl 44(%%eax)\n\t" \
1010 "pushl 40(%%eax)\n\t" \
1011 "pushl 36(%%eax)\n\t" \
1012 "pushl 32(%%eax)\n\t" \
1013 "pushl 28(%%eax)\n\t" \
1014 "pushl 24(%%eax)\n\t" \
1015 "pushl 20(%%eax)\n\t" \
1016 "pushl 16(%%eax)\n\t" \
1017 "pushl 12(%%eax)\n\t" \
1018 "pushl 8(%%eax)\n\t" \
1019 "pushl 4(%%eax)\n\t" \
1020 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1021 VALGRIND_CALL_NOREDIR_EAX \
1022 "addl $48, %%esp\n" \
1023 : /*out*/ "=a" (_res) \
1024 : /*in*/ "a" (&_argvec[0]) \
1025 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1027 lval = (__typeof__(lval)) _res; \
1030 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
1032 /* ------------------------ amd64-{linux,darwin} --------------- */
1034 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
1036 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1038 /* These regs are trashed by the hidden call. */
1039 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1040 "rdi", "r8", "r9", "r10", "r11"
1042 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1045 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1046 macros. In order not to trash the stack redzone, we need to drop
1047 %rsp by 128 before the hidden call, and restore afterwards. The
1048 nastyness is that it is only by luck that the stack still appears
1049 to be unwindable during the hidden call - since then the behaviour
1050 of any routine using this macro does not match what the CFI data
1053 Why is this important? Imagine that a wrapper has a stack
1054 allocated local, and passes to the hidden call, a pointer to it.
1055 Because gcc does not know about the hidden call, it may allocate
1056 that local in the redzone. Unfortunately the hidden call may then
1057 trash it before it comes to use it. So we must step clear of the
1058 redzone, for the duration of the hidden call, to make it safe.
1060 Probably the same problem afflicts the other redzone-style ABIs too
1061 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1062 self describing (none of this CFI nonsense) so at least messing
1063 with the stack pointer doesn't give a danger of non-unwindable
1066 #define CALL_FN_W_v(lval, orig) \
1068 volatile OrigFn _orig = (orig); \
1069 volatile unsigned long _argvec[1]; \
1070 volatile unsigned long _res; \
1071 _argvec[0] = (unsigned long)_orig.nraddr; \
1073 "subq $128,%%rsp\n\t" \
1074 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1075 VALGRIND_CALL_NOREDIR_RAX \
1076 "addq $128,%%rsp\n\t" \
1077 : /*out*/ "=a" (_res) \
1078 : /*in*/ "a" (&_argvec[0]) \
1079 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1081 lval = (__typeof__(lval)) _res; \
1084 #define CALL_FN_W_W(lval, orig, arg1) \
1086 volatile OrigFn _orig = (orig); \
1087 volatile unsigned long _argvec[2]; \
1088 volatile unsigned long _res; \
1089 _argvec[0] = (unsigned long)_orig.nraddr; \
1090 _argvec[1] = (unsigned long)(arg1); \
1092 "subq $128,%%rsp\n\t" \
1093 "movq 8(%%rax), %%rdi\n\t" \
1094 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1095 VALGRIND_CALL_NOREDIR_RAX \
1096 "addq $128,%%rsp\n\t" \
1097 : /*out*/ "=a" (_res) \
1098 : /*in*/ "a" (&_argvec[0]) \
1099 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1101 lval = (__typeof__(lval)) _res; \
1104 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1106 volatile OrigFn _orig = (orig); \
1107 volatile unsigned long _argvec[3]; \
1108 volatile unsigned long _res; \
1109 _argvec[0] = (unsigned long)_orig.nraddr; \
1110 _argvec[1] = (unsigned long)(arg1); \
1111 _argvec[2] = (unsigned long)(arg2); \
1113 "subq $128,%%rsp\n\t" \
1114 "movq 16(%%rax), %%rsi\n\t" \
1115 "movq 8(%%rax), %%rdi\n\t" \
1116 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1117 VALGRIND_CALL_NOREDIR_RAX \
1118 "addq $128,%%rsp\n\t" \
1119 : /*out*/ "=a" (_res) \
1120 : /*in*/ "a" (&_argvec[0]) \
1121 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1123 lval = (__typeof__(lval)) _res; \
1126 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1128 volatile OrigFn _orig = (orig); \
1129 volatile unsigned long _argvec[4]; \
1130 volatile unsigned long _res; \
1131 _argvec[0] = (unsigned long)_orig.nraddr; \
1132 _argvec[1] = (unsigned long)(arg1); \
1133 _argvec[2] = (unsigned long)(arg2); \
1134 _argvec[3] = (unsigned long)(arg3); \
1136 "subq $128,%%rsp\n\t" \
1137 "movq 24(%%rax), %%rdx\n\t" \
1138 "movq 16(%%rax), %%rsi\n\t" \
1139 "movq 8(%%rax), %%rdi\n\t" \
1140 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1141 VALGRIND_CALL_NOREDIR_RAX \
1142 "addq $128,%%rsp\n\t" \
1143 : /*out*/ "=a" (_res) \
1144 : /*in*/ "a" (&_argvec[0]) \
1145 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1147 lval = (__typeof__(lval)) _res; \
1150 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1152 volatile OrigFn _orig = (orig); \
1153 volatile unsigned long _argvec[5]; \
1154 volatile unsigned long _res; \
1155 _argvec[0] = (unsigned long)_orig.nraddr; \
1156 _argvec[1] = (unsigned long)(arg1); \
1157 _argvec[2] = (unsigned long)(arg2); \
1158 _argvec[3] = (unsigned long)(arg3); \
1159 _argvec[4] = (unsigned long)(arg4); \
1161 "subq $128,%%rsp\n\t" \
1162 "movq 32(%%rax), %%rcx\n\t" \
1163 "movq 24(%%rax), %%rdx\n\t" \
1164 "movq 16(%%rax), %%rsi\n\t" \
1165 "movq 8(%%rax), %%rdi\n\t" \
1166 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1167 VALGRIND_CALL_NOREDIR_RAX \
1168 "addq $128,%%rsp\n\t" \
1169 : /*out*/ "=a" (_res) \
1170 : /*in*/ "a" (&_argvec[0]) \
1171 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1173 lval = (__typeof__(lval)) _res; \
1176 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1178 volatile OrigFn _orig = (orig); \
1179 volatile unsigned long _argvec[6]; \
1180 volatile unsigned long _res; \
1181 _argvec[0] = (unsigned long)_orig.nraddr; \
1182 _argvec[1] = (unsigned long)(arg1); \
1183 _argvec[2] = (unsigned long)(arg2); \
1184 _argvec[3] = (unsigned long)(arg3); \
1185 _argvec[4] = (unsigned long)(arg4); \
1186 _argvec[5] = (unsigned long)(arg5); \
1188 "subq $128,%%rsp\n\t" \
1189 "movq 40(%%rax), %%r8\n\t" \
1190 "movq 32(%%rax), %%rcx\n\t" \
1191 "movq 24(%%rax), %%rdx\n\t" \
1192 "movq 16(%%rax), %%rsi\n\t" \
1193 "movq 8(%%rax), %%rdi\n\t" \
1194 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1195 VALGRIND_CALL_NOREDIR_RAX \
1196 "addq $128,%%rsp\n\t" \
1197 : /*out*/ "=a" (_res) \
1198 : /*in*/ "a" (&_argvec[0]) \
1199 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1201 lval = (__typeof__(lval)) _res; \
1204 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1206 volatile OrigFn _orig = (orig); \
1207 volatile unsigned long _argvec[7]; \
1208 volatile unsigned long _res; \
1209 _argvec[0] = (unsigned long)_orig.nraddr; \
1210 _argvec[1] = (unsigned long)(arg1); \
1211 _argvec[2] = (unsigned long)(arg2); \
1212 _argvec[3] = (unsigned long)(arg3); \
1213 _argvec[4] = (unsigned long)(arg4); \
1214 _argvec[5] = (unsigned long)(arg5); \
1215 _argvec[6] = (unsigned long)(arg6); \
1217 "subq $128,%%rsp\n\t" \
1218 "movq 48(%%rax), %%r9\n\t" \
1219 "movq 40(%%rax), %%r8\n\t" \
1220 "movq 32(%%rax), %%rcx\n\t" \
1221 "movq 24(%%rax), %%rdx\n\t" \
1222 "movq 16(%%rax), %%rsi\n\t" \
1223 "movq 8(%%rax), %%rdi\n\t" \
1224 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1225 "addq $128,%%rsp\n\t" \
1226 VALGRIND_CALL_NOREDIR_RAX \
1227 : /*out*/ "=a" (_res) \
1228 : /*in*/ "a" (&_argvec[0]) \
1229 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1231 lval = (__typeof__(lval)) _res; \
1234 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1237 volatile OrigFn _orig = (orig); \
1238 volatile unsigned long _argvec[8]; \
1239 volatile unsigned long _res; \
1240 _argvec[0] = (unsigned long)_orig.nraddr; \
1241 _argvec[1] = (unsigned long)(arg1); \
1242 _argvec[2] = (unsigned long)(arg2); \
1243 _argvec[3] = (unsigned long)(arg3); \
1244 _argvec[4] = (unsigned long)(arg4); \
1245 _argvec[5] = (unsigned long)(arg5); \
1246 _argvec[6] = (unsigned long)(arg6); \
1247 _argvec[7] = (unsigned long)(arg7); \
1249 "subq $128,%%rsp\n\t" \
1250 "pushq 56(%%rax)\n\t" \
1251 "movq 48(%%rax), %%r9\n\t" \
1252 "movq 40(%%rax), %%r8\n\t" \
1253 "movq 32(%%rax), %%rcx\n\t" \
1254 "movq 24(%%rax), %%rdx\n\t" \
1255 "movq 16(%%rax), %%rsi\n\t" \
1256 "movq 8(%%rax), %%rdi\n\t" \
1257 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1258 VALGRIND_CALL_NOREDIR_RAX \
1259 "addq $8, %%rsp\n" \
1260 "addq $128,%%rsp\n\t" \
1261 : /*out*/ "=a" (_res) \
1262 : /*in*/ "a" (&_argvec[0]) \
1263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1265 lval = (__typeof__(lval)) _res; \
1268 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1271 volatile OrigFn _orig = (orig); \
1272 volatile unsigned long _argvec[9]; \
1273 volatile unsigned long _res; \
1274 _argvec[0] = (unsigned long)_orig.nraddr; \
1275 _argvec[1] = (unsigned long)(arg1); \
1276 _argvec[2] = (unsigned long)(arg2); \
1277 _argvec[3] = (unsigned long)(arg3); \
1278 _argvec[4] = (unsigned long)(arg4); \
1279 _argvec[5] = (unsigned long)(arg5); \
1280 _argvec[6] = (unsigned long)(arg6); \
1281 _argvec[7] = (unsigned long)(arg7); \
1282 _argvec[8] = (unsigned long)(arg8); \
1284 "subq $128,%%rsp\n\t" \
1285 "pushq 64(%%rax)\n\t" \
1286 "pushq 56(%%rax)\n\t" \
1287 "movq 48(%%rax), %%r9\n\t" \
1288 "movq 40(%%rax), %%r8\n\t" \
1289 "movq 32(%%rax), %%rcx\n\t" \
1290 "movq 24(%%rax), %%rdx\n\t" \
1291 "movq 16(%%rax), %%rsi\n\t" \
1292 "movq 8(%%rax), %%rdi\n\t" \
1293 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1294 VALGRIND_CALL_NOREDIR_RAX \
1295 "addq $16, %%rsp\n" \
1296 "addq $128,%%rsp\n\t" \
1297 : /*out*/ "=a" (_res) \
1298 : /*in*/ "a" (&_argvec[0]) \
1299 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1301 lval = (__typeof__(lval)) _res; \
1304 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1307 volatile OrigFn _orig = (orig); \
1308 volatile unsigned long _argvec[10]; \
1309 volatile unsigned long _res; \
1310 _argvec[0] = (unsigned long)_orig.nraddr; \
1311 _argvec[1] = (unsigned long)(arg1); \
1312 _argvec[2] = (unsigned long)(arg2); \
1313 _argvec[3] = (unsigned long)(arg3); \
1314 _argvec[4] = (unsigned long)(arg4); \
1315 _argvec[5] = (unsigned long)(arg5); \
1316 _argvec[6] = (unsigned long)(arg6); \
1317 _argvec[7] = (unsigned long)(arg7); \
1318 _argvec[8] = (unsigned long)(arg8); \
1319 _argvec[9] = (unsigned long)(arg9); \
1321 "subq $128,%%rsp\n\t" \
1322 "pushq 72(%%rax)\n\t" \
1323 "pushq 64(%%rax)\n\t" \
1324 "pushq 56(%%rax)\n\t" \
1325 "movq 48(%%rax), %%r9\n\t" \
1326 "movq 40(%%rax), %%r8\n\t" \
1327 "movq 32(%%rax), %%rcx\n\t" \
1328 "movq 24(%%rax), %%rdx\n\t" \
1329 "movq 16(%%rax), %%rsi\n\t" \
1330 "movq 8(%%rax), %%rdi\n\t" \
1331 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1332 VALGRIND_CALL_NOREDIR_RAX \
1333 "addq $24, %%rsp\n" \
1334 "addq $128,%%rsp\n\t" \
1335 : /*out*/ "=a" (_res) \
1336 : /*in*/ "a" (&_argvec[0]) \
1337 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1339 lval = (__typeof__(lval)) _res; \
1342 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1343 arg7,arg8,arg9,arg10) \
1345 volatile OrigFn _orig = (orig); \
1346 volatile unsigned long _argvec[11]; \
1347 volatile unsigned long _res; \
1348 _argvec[0] = (unsigned long)_orig.nraddr; \
1349 _argvec[1] = (unsigned long)(arg1); \
1350 _argvec[2] = (unsigned long)(arg2); \
1351 _argvec[3] = (unsigned long)(arg3); \
1352 _argvec[4] = (unsigned long)(arg4); \
1353 _argvec[5] = (unsigned long)(arg5); \
1354 _argvec[6] = (unsigned long)(arg6); \
1355 _argvec[7] = (unsigned long)(arg7); \
1356 _argvec[8] = (unsigned long)(arg8); \
1357 _argvec[9] = (unsigned long)(arg9); \
1358 _argvec[10] = (unsigned long)(arg10); \
1360 "subq $128,%%rsp\n\t" \
1361 "pushq 80(%%rax)\n\t" \
1362 "pushq 72(%%rax)\n\t" \
1363 "pushq 64(%%rax)\n\t" \
1364 "pushq 56(%%rax)\n\t" \
1365 "movq 48(%%rax), %%r9\n\t" \
1366 "movq 40(%%rax), %%r8\n\t" \
1367 "movq 32(%%rax), %%rcx\n\t" \
1368 "movq 24(%%rax), %%rdx\n\t" \
1369 "movq 16(%%rax), %%rsi\n\t" \
1370 "movq 8(%%rax), %%rdi\n\t" \
1371 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1372 VALGRIND_CALL_NOREDIR_RAX \
1373 "addq $32, %%rsp\n" \
1374 "addq $128,%%rsp\n\t" \
1375 : /*out*/ "=a" (_res) \
1376 : /*in*/ "a" (&_argvec[0]) \
1377 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1379 lval = (__typeof__(lval)) _res; \
1382 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1383 arg7,arg8,arg9,arg10,arg11) \
1385 volatile OrigFn _orig = (orig); \
1386 volatile unsigned long _argvec[12]; \
1387 volatile unsigned long _res; \
1388 _argvec[0] = (unsigned long)_orig.nraddr; \
1389 _argvec[1] = (unsigned long)(arg1); \
1390 _argvec[2] = (unsigned long)(arg2); \
1391 _argvec[3] = (unsigned long)(arg3); \
1392 _argvec[4] = (unsigned long)(arg4); \
1393 _argvec[5] = (unsigned long)(arg5); \
1394 _argvec[6] = (unsigned long)(arg6); \
1395 _argvec[7] = (unsigned long)(arg7); \
1396 _argvec[8] = (unsigned long)(arg8); \
1397 _argvec[9] = (unsigned long)(arg9); \
1398 _argvec[10] = (unsigned long)(arg10); \
1399 _argvec[11] = (unsigned long)(arg11); \
1401 "subq $128,%%rsp\n\t" \
1402 "pushq 88(%%rax)\n\t" \
1403 "pushq 80(%%rax)\n\t" \
1404 "pushq 72(%%rax)\n\t" \
1405 "pushq 64(%%rax)\n\t" \
1406 "pushq 56(%%rax)\n\t" \
1407 "movq 48(%%rax), %%r9\n\t" \
1408 "movq 40(%%rax), %%r8\n\t" \
1409 "movq 32(%%rax), %%rcx\n\t" \
1410 "movq 24(%%rax), %%rdx\n\t" \
1411 "movq 16(%%rax), %%rsi\n\t" \
1412 "movq 8(%%rax), %%rdi\n\t" \
1413 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1414 VALGRIND_CALL_NOREDIR_RAX \
1415 "addq $40, %%rsp\n" \
1416 "addq $128,%%rsp\n\t" \
1417 : /*out*/ "=a" (_res) \
1418 : /*in*/ "a" (&_argvec[0]) \
1419 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1421 lval = (__typeof__(lval)) _res; \
1424 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1425 arg7,arg8,arg9,arg10,arg11,arg12) \
1427 volatile OrigFn _orig = (orig); \
1428 volatile unsigned long _argvec[13]; \
1429 volatile unsigned long _res; \
1430 _argvec[0] = (unsigned long)_orig.nraddr; \
1431 _argvec[1] = (unsigned long)(arg1); \
1432 _argvec[2] = (unsigned long)(arg2); \
1433 _argvec[3] = (unsigned long)(arg3); \
1434 _argvec[4] = (unsigned long)(arg4); \
1435 _argvec[5] = (unsigned long)(arg5); \
1436 _argvec[6] = (unsigned long)(arg6); \
1437 _argvec[7] = (unsigned long)(arg7); \
1438 _argvec[8] = (unsigned long)(arg8); \
1439 _argvec[9] = (unsigned long)(arg9); \
1440 _argvec[10] = (unsigned long)(arg10); \
1441 _argvec[11] = (unsigned long)(arg11); \
1442 _argvec[12] = (unsigned long)(arg12); \
1444 "subq $128,%%rsp\n\t" \
1445 "pushq 96(%%rax)\n\t" \
1446 "pushq 88(%%rax)\n\t" \
1447 "pushq 80(%%rax)\n\t" \
1448 "pushq 72(%%rax)\n\t" \
1449 "pushq 64(%%rax)\n\t" \
1450 "pushq 56(%%rax)\n\t" \
1451 "movq 48(%%rax), %%r9\n\t" \
1452 "movq 40(%%rax), %%r8\n\t" \
1453 "movq 32(%%rax), %%rcx\n\t" \
1454 "movq 24(%%rax), %%rdx\n\t" \
1455 "movq 16(%%rax), %%rsi\n\t" \
1456 "movq 8(%%rax), %%rdi\n\t" \
1457 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1458 VALGRIND_CALL_NOREDIR_RAX \
1459 "addq $48, %%rsp\n" \
1460 "addq $128,%%rsp\n\t" \
1461 : /*out*/ "=a" (_res) \
1462 : /*in*/ "a" (&_argvec[0]) \
1463 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1465 lval = (__typeof__(lval)) _res; \
1468 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
1470 /* ------------------------ ppc32-linux ------------------------ */
1472 #if defined(PLAT_ppc32_linux)
1474 /* This is useful for finding out about the on-stack stuff:
1476 extern int f9 ( int,int,int,int,int,int,int,int,int );
1477 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1478 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1479 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1482 return f9(11,22,33,44,55,66,77,88,99);
1485 return f10(11,22,33,44,55,66,77,88,99,110);
1488 return f11(11,22,33,44,55,66,77,88,99,110,121);
1491 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1495 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1497 /* These regs are trashed by the hidden call. */
1498 #define __CALLER_SAVED_REGS \
1499 "lr", "ctr", "xer", \
1500 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1501 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1504 /* These CALL_FN_ macros assume that on ppc32-linux,
1505 sizeof(unsigned long) == 4. */
1507 #define CALL_FN_W_v(lval, orig) \
1509 volatile OrigFn _orig = (orig); \
1510 volatile unsigned long _argvec[1]; \
1511 volatile unsigned long _res; \
1512 _argvec[0] = (unsigned long)_orig.nraddr; \
1515 "lwz 11,0(11)\n\t" /* target->r11 */ \
1516 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1518 : /*out*/ "=r" (_res) \
1519 : /*in*/ "r" (&_argvec[0]) \
1520 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1522 lval = (__typeof__(lval)) _res; \
1525 #define CALL_FN_W_W(lval, orig, arg1) \
1527 volatile OrigFn _orig = (orig); \
1528 volatile unsigned long _argvec[2]; \
1529 volatile unsigned long _res; \
1530 _argvec[0] = (unsigned long)_orig.nraddr; \
1531 _argvec[1] = (unsigned long)arg1; \
1534 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1535 "lwz 11,0(11)\n\t" /* target->r11 */ \
1536 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1538 : /*out*/ "=r" (_res) \
1539 : /*in*/ "r" (&_argvec[0]) \
1540 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1542 lval = (__typeof__(lval)) _res; \
1545 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1547 volatile OrigFn _orig = (orig); \
1548 volatile unsigned long _argvec[3]; \
1549 volatile unsigned long _res; \
1550 _argvec[0] = (unsigned long)_orig.nraddr; \
1551 _argvec[1] = (unsigned long)arg1; \
1552 _argvec[2] = (unsigned long)arg2; \
1555 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1557 "lwz 11,0(11)\n\t" /* target->r11 */ \
1558 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1560 : /*out*/ "=r" (_res) \
1561 : /*in*/ "r" (&_argvec[0]) \
1562 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1564 lval = (__typeof__(lval)) _res; \
1567 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1569 volatile OrigFn _orig = (orig); \
1570 volatile unsigned long _argvec[4]; \
1571 volatile unsigned long _res; \
1572 _argvec[0] = (unsigned long)_orig.nraddr; \
1573 _argvec[1] = (unsigned long)arg1; \
1574 _argvec[2] = (unsigned long)arg2; \
1575 _argvec[3] = (unsigned long)arg3; \
1578 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1580 "lwz 5,12(11)\n\t" \
1581 "lwz 11,0(11)\n\t" /* target->r11 */ \
1582 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1584 : /*out*/ "=r" (_res) \
1585 : /*in*/ "r" (&_argvec[0]) \
1586 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1588 lval = (__typeof__(lval)) _res; \
1591 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1593 volatile OrigFn _orig = (orig); \
1594 volatile unsigned long _argvec[5]; \
1595 volatile unsigned long _res; \
1596 _argvec[0] = (unsigned long)_orig.nraddr; \
1597 _argvec[1] = (unsigned long)arg1; \
1598 _argvec[2] = (unsigned long)arg2; \
1599 _argvec[3] = (unsigned long)arg3; \
1600 _argvec[4] = (unsigned long)arg4; \
1603 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1605 "lwz 5,12(11)\n\t" \
1606 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1607 "lwz 11,0(11)\n\t" /* target->r11 */ \
1608 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1610 : /*out*/ "=r" (_res) \
1611 : /*in*/ "r" (&_argvec[0]) \
1612 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1614 lval = (__typeof__(lval)) _res; \
1617 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1619 volatile OrigFn _orig = (orig); \
1620 volatile unsigned long _argvec[6]; \
1621 volatile unsigned long _res; \
1622 _argvec[0] = (unsigned long)_orig.nraddr; \
1623 _argvec[1] = (unsigned long)arg1; \
1624 _argvec[2] = (unsigned long)arg2; \
1625 _argvec[3] = (unsigned long)arg3; \
1626 _argvec[4] = (unsigned long)arg4; \
1627 _argvec[5] = (unsigned long)arg5; \
1630 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1632 "lwz 5,12(11)\n\t" \
1633 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1634 "lwz 7,20(11)\n\t" \
1635 "lwz 11,0(11)\n\t" /* target->r11 */ \
1636 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1638 : /*out*/ "=r" (_res) \
1639 : /*in*/ "r" (&_argvec[0]) \
1640 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1642 lval = (__typeof__(lval)) _res; \
1645 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1647 volatile OrigFn _orig = (orig); \
1648 volatile unsigned long _argvec[7]; \
1649 volatile unsigned long _res; \
1650 _argvec[0] = (unsigned long)_orig.nraddr; \
1651 _argvec[1] = (unsigned long)arg1; \
1652 _argvec[2] = (unsigned long)arg2; \
1653 _argvec[3] = (unsigned long)arg3; \
1654 _argvec[4] = (unsigned long)arg4; \
1655 _argvec[5] = (unsigned long)arg5; \
1656 _argvec[6] = (unsigned long)arg6; \
1659 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1661 "lwz 5,12(11)\n\t" \
1662 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1663 "lwz 7,20(11)\n\t" \
1664 "lwz 8,24(11)\n\t" \
1665 "lwz 11,0(11)\n\t" /* target->r11 */ \
1666 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1668 : /*out*/ "=r" (_res) \
1669 : /*in*/ "r" (&_argvec[0]) \
1670 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1672 lval = (__typeof__(lval)) _res; \
1675 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1678 volatile OrigFn _orig = (orig); \
1679 volatile unsigned long _argvec[8]; \
1680 volatile unsigned long _res; \
1681 _argvec[0] = (unsigned long)_orig.nraddr; \
1682 _argvec[1] = (unsigned long)arg1; \
1683 _argvec[2] = (unsigned long)arg2; \
1684 _argvec[3] = (unsigned long)arg3; \
1685 _argvec[4] = (unsigned long)arg4; \
1686 _argvec[5] = (unsigned long)arg5; \
1687 _argvec[6] = (unsigned long)arg6; \
1688 _argvec[7] = (unsigned long)arg7; \
1691 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1693 "lwz 5,12(11)\n\t" \
1694 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1695 "lwz 7,20(11)\n\t" \
1696 "lwz 8,24(11)\n\t" \
1697 "lwz 9,28(11)\n\t" \
1698 "lwz 11,0(11)\n\t" /* target->r11 */ \
1699 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1701 : /*out*/ "=r" (_res) \
1702 : /*in*/ "r" (&_argvec[0]) \
1703 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1705 lval = (__typeof__(lval)) _res; \
1708 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1711 volatile OrigFn _orig = (orig); \
1712 volatile unsigned long _argvec[9]; \
1713 volatile unsigned long _res; \
1714 _argvec[0] = (unsigned long)_orig.nraddr; \
1715 _argvec[1] = (unsigned long)arg1; \
1716 _argvec[2] = (unsigned long)arg2; \
1717 _argvec[3] = (unsigned long)arg3; \
1718 _argvec[4] = (unsigned long)arg4; \
1719 _argvec[5] = (unsigned long)arg5; \
1720 _argvec[6] = (unsigned long)arg6; \
1721 _argvec[7] = (unsigned long)arg7; \
1722 _argvec[8] = (unsigned long)arg8; \
1725 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1727 "lwz 5,12(11)\n\t" \
1728 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1729 "lwz 7,20(11)\n\t" \
1730 "lwz 8,24(11)\n\t" \
1731 "lwz 9,28(11)\n\t" \
1732 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1733 "lwz 11,0(11)\n\t" /* target->r11 */ \
1734 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1736 : /*out*/ "=r" (_res) \
1737 : /*in*/ "r" (&_argvec[0]) \
1738 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1740 lval = (__typeof__(lval)) _res; \
1743 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1746 volatile OrigFn _orig = (orig); \
1747 volatile unsigned long _argvec[10]; \
1748 volatile unsigned long _res; \
1749 _argvec[0] = (unsigned long)_orig.nraddr; \
1750 _argvec[1] = (unsigned long)arg1; \
1751 _argvec[2] = (unsigned long)arg2; \
1752 _argvec[3] = (unsigned long)arg3; \
1753 _argvec[4] = (unsigned long)arg4; \
1754 _argvec[5] = (unsigned long)arg5; \
1755 _argvec[6] = (unsigned long)arg6; \
1756 _argvec[7] = (unsigned long)arg7; \
1757 _argvec[8] = (unsigned long)arg8; \
1758 _argvec[9] = (unsigned long)arg9; \
1761 "addi 1,1,-16\n\t" \
1763 "lwz 3,36(11)\n\t" \
1766 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1768 "lwz 5,12(11)\n\t" \
1769 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1770 "lwz 7,20(11)\n\t" \
1771 "lwz 8,24(11)\n\t" \
1772 "lwz 9,28(11)\n\t" \
1773 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1774 "lwz 11,0(11)\n\t" /* target->r11 */ \
1775 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1778 : /*out*/ "=r" (_res) \
1779 : /*in*/ "r" (&_argvec[0]) \
1780 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1782 lval = (__typeof__(lval)) _res; \
1785 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1786 arg7,arg8,arg9,arg10) \
1788 volatile OrigFn _orig = (orig); \
1789 volatile unsigned long _argvec[11]; \
1790 volatile unsigned long _res; \
1791 _argvec[0] = (unsigned long)_orig.nraddr; \
1792 _argvec[1] = (unsigned long)arg1; \
1793 _argvec[2] = (unsigned long)arg2; \
1794 _argvec[3] = (unsigned long)arg3; \
1795 _argvec[4] = (unsigned long)arg4; \
1796 _argvec[5] = (unsigned long)arg5; \
1797 _argvec[6] = (unsigned long)arg6; \
1798 _argvec[7] = (unsigned long)arg7; \
1799 _argvec[8] = (unsigned long)arg8; \
1800 _argvec[9] = (unsigned long)arg9; \
1801 _argvec[10] = (unsigned long)arg10; \
1804 "addi 1,1,-16\n\t" \
1806 "lwz 3,40(11)\n\t" \
1809 "lwz 3,36(11)\n\t" \
1812 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1814 "lwz 5,12(11)\n\t" \
1815 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1816 "lwz 7,20(11)\n\t" \
1817 "lwz 8,24(11)\n\t" \
1818 "lwz 9,28(11)\n\t" \
1819 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1820 "lwz 11,0(11)\n\t" /* target->r11 */ \
1821 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1824 : /*out*/ "=r" (_res) \
1825 : /*in*/ "r" (&_argvec[0]) \
1826 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1828 lval = (__typeof__(lval)) _res; \
1831 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1832 arg7,arg8,arg9,arg10,arg11) \
1834 volatile OrigFn _orig = (orig); \
1835 volatile unsigned long _argvec[12]; \
1836 volatile unsigned long _res; \
1837 _argvec[0] = (unsigned long)_orig.nraddr; \
1838 _argvec[1] = (unsigned long)arg1; \
1839 _argvec[2] = (unsigned long)arg2; \
1840 _argvec[3] = (unsigned long)arg3; \
1841 _argvec[4] = (unsigned long)arg4; \
1842 _argvec[5] = (unsigned long)arg5; \
1843 _argvec[6] = (unsigned long)arg6; \
1844 _argvec[7] = (unsigned long)arg7; \
1845 _argvec[8] = (unsigned long)arg8; \
1846 _argvec[9] = (unsigned long)arg9; \
1847 _argvec[10] = (unsigned long)arg10; \
1848 _argvec[11] = (unsigned long)arg11; \
1851 "addi 1,1,-32\n\t" \
1853 "lwz 3,44(11)\n\t" \
1856 "lwz 3,40(11)\n\t" \
1859 "lwz 3,36(11)\n\t" \
1862 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1864 "lwz 5,12(11)\n\t" \
1865 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1866 "lwz 7,20(11)\n\t" \
1867 "lwz 8,24(11)\n\t" \
1868 "lwz 9,28(11)\n\t" \
1869 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1870 "lwz 11,0(11)\n\t" /* target->r11 */ \
1871 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1874 : /*out*/ "=r" (_res) \
1875 : /*in*/ "r" (&_argvec[0]) \
1876 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1878 lval = (__typeof__(lval)) _res; \
1881 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1882 arg7,arg8,arg9,arg10,arg11,arg12) \
1884 volatile OrigFn _orig = (orig); \
1885 volatile unsigned long _argvec[13]; \
1886 volatile unsigned long _res; \
1887 _argvec[0] = (unsigned long)_orig.nraddr; \
1888 _argvec[1] = (unsigned long)arg1; \
1889 _argvec[2] = (unsigned long)arg2; \
1890 _argvec[3] = (unsigned long)arg3; \
1891 _argvec[4] = (unsigned long)arg4; \
1892 _argvec[5] = (unsigned long)arg5; \
1893 _argvec[6] = (unsigned long)arg6; \
1894 _argvec[7] = (unsigned long)arg7; \
1895 _argvec[8] = (unsigned long)arg8; \
1896 _argvec[9] = (unsigned long)arg9; \
1897 _argvec[10] = (unsigned long)arg10; \
1898 _argvec[11] = (unsigned long)arg11; \
1899 _argvec[12] = (unsigned long)arg12; \
1902 "addi 1,1,-32\n\t" \
1904 "lwz 3,48(11)\n\t" \
1907 "lwz 3,44(11)\n\t" \
1910 "lwz 3,40(11)\n\t" \
1913 "lwz 3,36(11)\n\t" \
1916 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1918 "lwz 5,12(11)\n\t" \
1919 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1920 "lwz 7,20(11)\n\t" \
1921 "lwz 8,24(11)\n\t" \
1922 "lwz 9,28(11)\n\t" \
1923 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1924 "lwz 11,0(11)\n\t" /* target->r11 */ \
1925 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1928 : /*out*/ "=r" (_res) \
1929 : /*in*/ "r" (&_argvec[0]) \
1930 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1932 lval = (__typeof__(lval)) _res; \
1935 #endif /* PLAT_ppc32_linux */
1937 /* ------------------------ ppc64-linux ------------------------ */
1939 #if defined(PLAT_ppc64_linux)
1941 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1943 /* These regs are trashed by the hidden call. */
1944 #define __CALLER_SAVED_REGS \
1945 "lr", "ctr", "xer", \
1946 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1947 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1950 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1953 #define CALL_FN_W_v(lval, orig) \
1955 volatile OrigFn _orig = (orig); \
1956 volatile unsigned long _argvec[3+0]; \
1957 volatile unsigned long _res; \
1958 /* _argvec[0] holds current r2 across the call */ \
1959 _argvec[1] = (unsigned long)_orig.r2; \
1960 _argvec[2] = (unsigned long)_orig.nraddr; \
1963 "std 2,-16(11)\n\t" /* save tocptr */ \
1964 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1965 "ld 11, 0(11)\n\t" /* target->r11 */ \
1966 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1969 "ld 2,-16(11)" /* restore tocptr */ \
1970 : /*out*/ "=r" (_res) \
1971 : /*in*/ "r" (&_argvec[2]) \
1972 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1974 lval = (__typeof__(lval)) _res; \
1977 #define CALL_FN_W_W(lval, orig, arg1) \
1979 volatile OrigFn _orig = (orig); \
1980 volatile unsigned long _argvec[3+1]; \
1981 volatile unsigned long _res; \
1982 /* _argvec[0] holds current r2 across the call */ \
1983 _argvec[1] = (unsigned long)_orig.r2; \
1984 _argvec[2] = (unsigned long)_orig.nraddr; \
1985 _argvec[2+1] = (unsigned long)arg1; \
1988 "std 2,-16(11)\n\t" /* save tocptr */ \
1989 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1990 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1991 "ld 11, 0(11)\n\t" /* target->r11 */ \
1992 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1995 "ld 2,-16(11)" /* restore tocptr */ \
1996 : /*out*/ "=r" (_res) \
1997 : /*in*/ "r" (&_argvec[2]) \
1998 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2000 lval = (__typeof__(lval)) _res; \
2003 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2005 volatile OrigFn _orig = (orig); \
2006 volatile unsigned long _argvec[3+2]; \
2007 volatile unsigned long _res; \
2008 /* _argvec[0] holds current r2 across the call */ \
2009 _argvec[1] = (unsigned long)_orig.r2; \
2010 _argvec[2] = (unsigned long)_orig.nraddr; \
2011 _argvec[2+1] = (unsigned long)arg1; \
2012 _argvec[2+2] = (unsigned long)arg2; \
2015 "std 2,-16(11)\n\t" /* save tocptr */ \
2016 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2017 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2018 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2019 "ld 11, 0(11)\n\t" /* target->r11 */ \
2020 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2023 "ld 2,-16(11)" /* restore tocptr */ \
2024 : /*out*/ "=r" (_res) \
2025 : /*in*/ "r" (&_argvec[2]) \
2026 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2028 lval = (__typeof__(lval)) _res; \
2031 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2033 volatile OrigFn _orig = (orig); \
2034 volatile unsigned long _argvec[3+3]; \
2035 volatile unsigned long _res; \
2036 /* _argvec[0] holds current r2 across the call */ \
2037 _argvec[1] = (unsigned long)_orig.r2; \
2038 _argvec[2] = (unsigned long)_orig.nraddr; \
2039 _argvec[2+1] = (unsigned long)arg1; \
2040 _argvec[2+2] = (unsigned long)arg2; \
2041 _argvec[2+3] = (unsigned long)arg3; \
2044 "std 2,-16(11)\n\t" /* save tocptr */ \
2045 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2046 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2047 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2048 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2049 "ld 11, 0(11)\n\t" /* target->r11 */ \
2050 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2053 "ld 2,-16(11)" /* restore tocptr */ \
2054 : /*out*/ "=r" (_res) \
2055 : /*in*/ "r" (&_argvec[2]) \
2056 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2058 lval = (__typeof__(lval)) _res; \
2061 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2063 volatile OrigFn _orig = (orig); \
2064 volatile unsigned long _argvec[3+4]; \
2065 volatile unsigned long _res; \
2066 /* _argvec[0] holds current r2 across the call */ \
2067 _argvec[1] = (unsigned long)_orig.r2; \
2068 _argvec[2] = (unsigned long)_orig.nraddr; \
2069 _argvec[2+1] = (unsigned long)arg1; \
2070 _argvec[2+2] = (unsigned long)arg2; \
2071 _argvec[2+3] = (unsigned long)arg3; \
2072 _argvec[2+4] = (unsigned long)arg4; \
2075 "std 2,-16(11)\n\t" /* save tocptr */ \
2076 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2077 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2078 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2079 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2080 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2081 "ld 11, 0(11)\n\t" /* target->r11 */ \
2082 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2085 "ld 2,-16(11)" /* restore tocptr */ \
2086 : /*out*/ "=r" (_res) \
2087 : /*in*/ "r" (&_argvec[2]) \
2088 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2090 lval = (__typeof__(lval)) _res; \
2093 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2095 volatile OrigFn _orig = (orig); \
2096 volatile unsigned long _argvec[3+5]; \
2097 volatile unsigned long _res; \
2098 /* _argvec[0] holds current r2 across the call */ \
2099 _argvec[1] = (unsigned long)_orig.r2; \
2100 _argvec[2] = (unsigned long)_orig.nraddr; \
2101 _argvec[2+1] = (unsigned long)arg1; \
2102 _argvec[2+2] = (unsigned long)arg2; \
2103 _argvec[2+3] = (unsigned long)arg3; \
2104 _argvec[2+4] = (unsigned long)arg4; \
2105 _argvec[2+5] = (unsigned long)arg5; \
2108 "std 2,-16(11)\n\t" /* save tocptr */ \
2109 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2110 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2111 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2112 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2113 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2114 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2115 "ld 11, 0(11)\n\t" /* target->r11 */ \
2116 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2119 "ld 2,-16(11)" /* restore tocptr */ \
2120 : /*out*/ "=r" (_res) \
2121 : /*in*/ "r" (&_argvec[2]) \
2122 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2124 lval = (__typeof__(lval)) _res; \
2127 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2129 volatile OrigFn _orig = (orig); \
2130 volatile unsigned long _argvec[3+6]; \
2131 volatile unsigned long _res; \
2132 /* _argvec[0] holds current r2 across the call */ \
2133 _argvec[1] = (unsigned long)_orig.r2; \
2134 _argvec[2] = (unsigned long)_orig.nraddr; \
2135 _argvec[2+1] = (unsigned long)arg1; \
2136 _argvec[2+2] = (unsigned long)arg2; \
2137 _argvec[2+3] = (unsigned long)arg3; \
2138 _argvec[2+4] = (unsigned long)arg4; \
2139 _argvec[2+5] = (unsigned long)arg5; \
2140 _argvec[2+6] = (unsigned long)arg6; \
2143 "std 2,-16(11)\n\t" /* save tocptr */ \
2144 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2145 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2146 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2147 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2148 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2149 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2150 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2151 "ld 11, 0(11)\n\t" /* target->r11 */ \
2152 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2155 "ld 2,-16(11)" /* restore tocptr */ \
2156 : /*out*/ "=r" (_res) \
2157 : /*in*/ "r" (&_argvec[2]) \
2158 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2160 lval = (__typeof__(lval)) _res; \
2163 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2166 volatile OrigFn _orig = (orig); \
2167 volatile unsigned long _argvec[3+7]; \
2168 volatile unsigned long _res; \
2169 /* _argvec[0] holds current r2 across the call */ \
2170 _argvec[1] = (unsigned long)_orig.r2; \
2171 _argvec[2] = (unsigned long)_orig.nraddr; \
2172 _argvec[2+1] = (unsigned long)arg1; \
2173 _argvec[2+2] = (unsigned long)arg2; \
2174 _argvec[2+3] = (unsigned long)arg3; \
2175 _argvec[2+4] = (unsigned long)arg4; \
2176 _argvec[2+5] = (unsigned long)arg5; \
2177 _argvec[2+6] = (unsigned long)arg6; \
2178 _argvec[2+7] = (unsigned long)arg7; \
2181 "std 2,-16(11)\n\t" /* save tocptr */ \
2182 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2183 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2184 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2185 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2186 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2187 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2188 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2189 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2190 "ld 11, 0(11)\n\t" /* target->r11 */ \
2191 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2194 "ld 2,-16(11)" /* restore tocptr */ \
2195 : /*out*/ "=r" (_res) \
2196 : /*in*/ "r" (&_argvec[2]) \
2197 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2199 lval = (__typeof__(lval)) _res; \
2202 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2205 volatile OrigFn _orig = (orig); \
2206 volatile unsigned long _argvec[3+8]; \
2207 volatile unsigned long _res; \
2208 /* _argvec[0] holds current r2 across the call */ \
2209 _argvec[1] = (unsigned long)_orig.r2; \
2210 _argvec[2] = (unsigned long)_orig.nraddr; \
2211 _argvec[2+1] = (unsigned long)arg1; \
2212 _argvec[2+2] = (unsigned long)arg2; \
2213 _argvec[2+3] = (unsigned long)arg3; \
2214 _argvec[2+4] = (unsigned long)arg4; \
2215 _argvec[2+5] = (unsigned long)arg5; \
2216 _argvec[2+6] = (unsigned long)arg6; \
2217 _argvec[2+7] = (unsigned long)arg7; \
2218 _argvec[2+8] = (unsigned long)arg8; \
2221 "std 2,-16(11)\n\t" /* save tocptr */ \
2222 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2223 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2224 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2225 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2226 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2227 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2228 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2229 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2230 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2231 "ld 11, 0(11)\n\t" /* target->r11 */ \
2232 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2235 "ld 2,-16(11)" /* restore tocptr */ \
2236 : /*out*/ "=r" (_res) \
2237 : /*in*/ "r" (&_argvec[2]) \
2238 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2240 lval = (__typeof__(lval)) _res; \
2243 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2246 volatile OrigFn _orig = (orig); \
2247 volatile unsigned long _argvec[3+9]; \
2248 volatile unsigned long _res; \
2249 /* _argvec[0] holds current r2 across the call */ \
2250 _argvec[1] = (unsigned long)_orig.r2; \
2251 _argvec[2] = (unsigned long)_orig.nraddr; \
2252 _argvec[2+1] = (unsigned long)arg1; \
2253 _argvec[2+2] = (unsigned long)arg2; \
2254 _argvec[2+3] = (unsigned long)arg3; \
2255 _argvec[2+4] = (unsigned long)arg4; \
2256 _argvec[2+5] = (unsigned long)arg5; \
2257 _argvec[2+6] = (unsigned long)arg6; \
2258 _argvec[2+7] = (unsigned long)arg7; \
2259 _argvec[2+8] = (unsigned long)arg8; \
2260 _argvec[2+9] = (unsigned long)arg9; \
2263 "std 2,-16(11)\n\t" /* save tocptr */ \
2264 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2265 "addi 1,1,-128\n\t" /* expand stack frame */ \
2268 "std 3,112(1)\n\t" \
2270 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2271 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2272 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2273 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2274 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2275 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2276 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2277 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2278 "ld 11, 0(11)\n\t" /* target->r11 */ \
2279 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2282 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2283 "addi 1,1,128" /* restore frame */ \
2284 : /*out*/ "=r" (_res) \
2285 : /*in*/ "r" (&_argvec[2]) \
2286 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2288 lval = (__typeof__(lval)) _res; \
2291 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2292 arg7,arg8,arg9,arg10) \
2294 volatile OrigFn _orig = (orig); \
2295 volatile unsigned long _argvec[3+10]; \
2296 volatile unsigned long _res; \
2297 /* _argvec[0] holds current r2 across the call */ \
2298 _argvec[1] = (unsigned long)_orig.r2; \
2299 _argvec[2] = (unsigned long)_orig.nraddr; \
2300 _argvec[2+1] = (unsigned long)arg1; \
2301 _argvec[2+2] = (unsigned long)arg2; \
2302 _argvec[2+3] = (unsigned long)arg3; \
2303 _argvec[2+4] = (unsigned long)arg4; \
2304 _argvec[2+5] = (unsigned long)arg5; \
2305 _argvec[2+6] = (unsigned long)arg6; \
2306 _argvec[2+7] = (unsigned long)arg7; \
2307 _argvec[2+8] = (unsigned long)arg8; \
2308 _argvec[2+9] = (unsigned long)arg9; \
2309 _argvec[2+10] = (unsigned long)arg10; \
2312 "std 2,-16(11)\n\t" /* save tocptr */ \
2313 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2314 "addi 1,1,-128\n\t" /* expand stack frame */ \
2317 "std 3,120(1)\n\t" \
2320 "std 3,112(1)\n\t" \
2322 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2323 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2324 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2325 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2326 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2327 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2328 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2329 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2330 "ld 11, 0(11)\n\t" /* target->r11 */ \
2331 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2334 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2335 "addi 1,1,128" /* restore frame */ \
2336 : /*out*/ "=r" (_res) \
2337 : /*in*/ "r" (&_argvec[2]) \
2338 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2340 lval = (__typeof__(lval)) _res; \
2343 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2344 arg7,arg8,arg9,arg10,arg11) \
2346 volatile OrigFn _orig = (orig); \
2347 volatile unsigned long _argvec[3+11]; \
2348 volatile unsigned long _res; \
2349 /* _argvec[0] holds current r2 across the call */ \
2350 _argvec[1] = (unsigned long)_orig.r2; \
2351 _argvec[2] = (unsigned long)_orig.nraddr; \
2352 _argvec[2+1] = (unsigned long)arg1; \
2353 _argvec[2+2] = (unsigned long)arg2; \
2354 _argvec[2+3] = (unsigned long)arg3; \
2355 _argvec[2+4] = (unsigned long)arg4; \
2356 _argvec[2+5] = (unsigned long)arg5; \
2357 _argvec[2+6] = (unsigned long)arg6; \
2358 _argvec[2+7] = (unsigned long)arg7; \
2359 _argvec[2+8] = (unsigned long)arg8; \
2360 _argvec[2+9] = (unsigned long)arg9; \
2361 _argvec[2+10] = (unsigned long)arg10; \
2362 _argvec[2+11] = (unsigned long)arg11; \
2365 "std 2,-16(11)\n\t" /* save tocptr */ \
2366 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2367 "addi 1,1,-144\n\t" /* expand stack frame */ \
2370 "std 3,128(1)\n\t" \
2373 "std 3,120(1)\n\t" \
2376 "std 3,112(1)\n\t" \
2378 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2379 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2380 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2381 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2382 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2383 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2384 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2385 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2386 "ld 11, 0(11)\n\t" /* target->r11 */ \
2387 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2390 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2391 "addi 1,1,144" /* restore frame */ \
2392 : /*out*/ "=r" (_res) \
2393 : /*in*/ "r" (&_argvec[2]) \
2394 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2396 lval = (__typeof__(lval)) _res; \
2399 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2400 arg7,arg8,arg9,arg10,arg11,arg12) \
2402 volatile OrigFn _orig = (orig); \
2403 volatile unsigned long _argvec[3+12]; \
2404 volatile unsigned long _res; \
2405 /* _argvec[0] holds current r2 across the call */ \
2406 _argvec[1] = (unsigned long)_orig.r2; \
2407 _argvec[2] = (unsigned long)_orig.nraddr; \
2408 _argvec[2+1] = (unsigned long)arg1; \
2409 _argvec[2+2] = (unsigned long)arg2; \
2410 _argvec[2+3] = (unsigned long)arg3; \
2411 _argvec[2+4] = (unsigned long)arg4; \
2412 _argvec[2+5] = (unsigned long)arg5; \
2413 _argvec[2+6] = (unsigned long)arg6; \
2414 _argvec[2+7] = (unsigned long)arg7; \
2415 _argvec[2+8] = (unsigned long)arg8; \
2416 _argvec[2+9] = (unsigned long)arg9; \
2417 _argvec[2+10] = (unsigned long)arg10; \
2418 _argvec[2+11] = (unsigned long)arg11; \
2419 _argvec[2+12] = (unsigned long)arg12; \
2422 "std 2,-16(11)\n\t" /* save tocptr */ \
2423 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2424 "addi 1,1,-144\n\t" /* expand stack frame */ \
2427 "std 3,136(1)\n\t" \
2430 "std 3,128(1)\n\t" \
2433 "std 3,120(1)\n\t" \
2436 "std 3,112(1)\n\t" \
2438 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2439 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2440 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2441 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2442 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2443 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2444 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2445 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2446 "ld 11, 0(11)\n\t" /* target->r11 */ \
2447 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2450 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2451 "addi 1,1,144" /* restore frame */ \
2452 : /*out*/ "=r" (_res) \
2453 : /*in*/ "r" (&_argvec[2]) \
2454 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2456 lval = (__typeof__(lval)) _res; \
2459 #endif /* PLAT_ppc64_linux */
2461 /* ------------------------ ppc32-aix5 ------------------------- */
2463 #if defined(PLAT_ppc32_aix5)
2465 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2467 /* These regs are trashed by the hidden call. */
2468 #define __CALLER_SAVED_REGS \
2469 "lr", "ctr", "xer", \
2470 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2471 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2474 /* Expand the stack frame, copying enough info that unwinding
2475 still works. Trashes r3. */
2477 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2478 "addi 1,1,-" #_n_fr "\n\t" \
2479 "lwz 3," #_n_fr "(1)\n\t" \
2482 #define VG_CONTRACT_FRAME_BY(_n_fr) \
2483 "addi 1,1," #_n_fr "\n\t"
2485 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2488 #define CALL_FN_W_v(lval, orig) \
2490 volatile OrigFn _orig = (orig); \
2491 volatile unsigned long _argvec[3+0]; \
2492 volatile unsigned long _res; \
2493 /* _argvec[0] holds current r2 across the call */ \
2494 _argvec[1] = (unsigned long)_orig.r2; \
2495 _argvec[2] = (unsigned long)_orig.nraddr; \
2498 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2499 "stw 2,-8(11)\n\t" /* save tocptr */ \
2500 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2501 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2502 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2505 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2506 VG_CONTRACT_FRAME_BY(512) \
2507 : /*out*/ "=r" (_res) \
2508 : /*in*/ "r" (&_argvec[2]) \
2509 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2511 lval = (__typeof__(lval)) _res; \
2514 #define CALL_FN_W_W(lval, orig, arg1) \
2516 volatile OrigFn _orig = (orig); \
2517 volatile unsigned long _argvec[3+1]; \
2518 volatile unsigned long _res; \
2519 /* _argvec[0] holds current r2 across the call */ \
2520 _argvec[1] = (unsigned long)_orig.r2; \
2521 _argvec[2] = (unsigned long)_orig.nraddr; \
2522 _argvec[2+1] = (unsigned long)arg1; \
2525 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2526 "stw 2,-8(11)\n\t" /* save tocptr */ \
2527 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2528 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2529 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2530 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2533 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2534 VG_CONTRACT_FRAME_BY(512) \
2535 : /*out*/ "=r" (_res) \
2536 : /*in*/ "r" (&_argvec[2]) \
2537 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2539 lval = (__typeof__(lval)) _res; \
2542 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2544 volatile OrigFn _orig = (orig); \
2545 volatile unsigned long _argvec[3+2]; \
2546 volatile unsigned long _res; \
2547 /* _argvec[0] holds current r2 across the call */ \
2548 _argvec[1] = (unsigned long)_orig.r2; \
2549 _argvec[2] = (unsigned long)_orig.nraddr; \
2550 _argvec[2+1] = (unsigned long)arg1; \
2551 _argvec[2+2] = (unsigned long)arg2; \
2554 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2555 "stw 2,-8(11)\n\t" /* save tocptr */ \
2556 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2557 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2558 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2559 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2560 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2563 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2564 VG_CONTRACT_FRAME_BY(512) \
2565 : /*out*/ "=r" (_res) \
2566 : /*in*/ "r" (&_argvec[2]) \
2567 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2569 lval = (__typeof__(lval)) _res; \
2572 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2574 volatile OrigFn _orig = (orig); \
2575 volatile unsigned long _argvec[3+3]; \
2576 volatile unsigned long _res; \
2577 /* _argvec[0] holds current r2 across the call */ \
2578 _argvec[1] = (unsigned long)_orig.r2; \
2579 _argvec[2] = (unsigned long)_orig.nraddr; \
2580 _argvec[2+1] = (unsigned long)arg1; \
2581 _argvec[2+2] = (unsigned long)arg2; \
2582 _argvec[2+3] = (unsigned long)arg3; \
2585 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2586 "stw 2,-8(11)\n\t" /* save tocptr */ \
2587 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2588 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2589 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2590 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2591 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2592 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2595 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2596 VG_CONTRACT_FRAME_BY(512) \
2597 : /*out*/ "=r" (_res) \
2598 : /*in*/ "r" (&_argvec[2]) \
2599 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2601 lval = (__typeof__(lval)) _res; \
2604 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2606 volatile OrigFn _orig = (orig); \
2607 volatile unsigned long _argvec[3+4]; \
2608 volatile unsigned long _res; \
2609 /* _argvec[0] holds current r2 across the call */ \
2610 _argvec[1] = (unsigned long)_orig.r2; \
2611 _argvec[2] = (unsigned long)_orig.nraddr; \
2612 _argvec[2+1] = (unsigned long)arg1; \
2613 _argvec[2+2] = (unsigned long)arg2; \
2614 _argvec[2+3] = (unsigned long)arg3; \
2615 _argvec[2+4] = (unsigned long)arg4; \
2618 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2619 "stw 2,-8(11)\n\t" /* save tocptr */ \
2620 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2621 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2622 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2623 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2624 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2625 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2626 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2629 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2630 VG_CONTRACT_FRAME_BY(512) \
2631 : /*out*/ "=r" (_res) \
2632 : /*in*/ "r" (&_argvec[2]) \
2633 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2635 lval = (__typeof__(lval)) _res; \
2638 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2640 volatile OrigFn _orig = (orig); \
2641 volatile unsigned long _argvec[3+5]; \
2642 volatile unsigned long _res; \
2643 /* _argvec[0] holds current r2 across the call */ \
2644 _argvec[1] = (unsigned long)_orig.r2; \
2645 _argvec[2] = (unsigned long)_orig.nraddr; \
2646 _argvec[2+1] = (unsigned long)arg1; \
2647 _argvec[2+2] = (unsigned long)arg2; \
2648 _argvec[2+3] = (unsigned long)arg3; \
2649 _argvec[2+4] = (unsigned long)arg4; \
2650 _argvec[2+5] = (unsigned long)arg5; \
2653 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2654 "stw 2,-8(11)\n\t" /* save tocptr */ \
2655 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2656 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2657 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2658 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2659 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2660 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2661 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2662 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2665 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2666 VG_CONTRACT_FRAME_BY(512) \
2667 : /*out*/ "=r" (_res) \
2668 : /*in*/ "r" (&_argvec[2]) \
2669 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2671 lval = (__typeof__(lval)) _res; \
2674 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2676 volatile OrigFn _orig = (orig); \
2677 volatile unsigned long _argvec[3+6]; \
2678 volatile unsigned long _res; \
2679 /* _argvec[0] holds current r2 across the call */ \
2680 _argvec[1] = (unsigned long)_orig.r2; \
2681 _argvec[2] = (unsigned long)_orig.nraddr; \
2682 _argvec[2+1] = (unsigned long)arg1; \
2683 _argvec[2+2] = (unsigned long)arg2; \
2684 _argvec[2+3] = (unsigned long)arg3; \
2685 _argvec[2+4] = (unsigned long)arg4; \
2686 _argvec[2+5] = (unsigned long)arg5; \
2687 _argvec[2+6] = (unsigned long)arg6; \
2690 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2691 "stw 2,-8(11)\n\t" /* save tocptr */ \
2692 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2693 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2694 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2695 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2696 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2697 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2698 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2699 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2700 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2703 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2704 VG_CONTRACT_FRAME_BY(512) \
2705 : /*out*/ "=r" (_res) \
2706 : /*in*/ "r" (&_argvec[2]) \
2707 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2709 lval = (__typeof__(lval)) _res; \
2712 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2715 volatile OrigFn _orig = (orig); \
2716 volatile unsigned long _argvec[3+7]; \
2717 volatile unsigned long _res; \
2718 /* _argvec[0] holds current r2 across the call */ \
2719 _argvec[1] = (unsigned long)_orig.r2; \
2720 _argvec[2] = (unsigned long)_orig.nraddr; \
2721 _argvec[2+1] = (unsigned long)arg1; \
2722 _argvec[2+2] = (unsigned long)arg2; \
2723 _argvec[2+3] = (unsigned long)arg3; \
2724 _argvec[2+4] = (unsigned long)arg4; \
2725 _argvec[2+5] = (unsigned long)arg5; \
2726 _argvec[2+6] = (unsigned long)arg6; \
2727 _argvec[2+7] = (unsigned long)arg7; \
2730 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2731 "stw 2,-8(11)\n\t" /* save tocptr */ \
2732 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2733 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2734 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2735 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2736 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2737 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2738 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2739 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2740 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2741 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2744 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2745 VG_CONTRACT_FRAME_BY(512) \
2746 : /*out*/ "=r" (_res) \
2747 : /*in*/ "r" (&_argvec[2]) \
2748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2750 lval = (__typeof__(lval)) _res; \
2753 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2756 volatile OrigFn _orig = (orig); \
2757 volatile unsigned long _argvec[3+8]; \
2758 volatile unsigned long _res; \
2759 /* _argvec[0] holds current r2 across the call */ \
2760 _argvec[1] = (unsigned long)_orig.r2; \
2761 _argvec[2] = (unsigned long)_orig.nraddr; \
2762 _argvec[2+1] = (unsigned long)arg1; \
2763 _argvec[2+2] = (unsigned long)arg2; \
2764 _argvec[2+3] = (unsigned long)arg3; \
2765 _argvec[2+4] = (unsigned long)arg4; \
2766 _argvec[2+5] = (unsigned long)arg5; \
2767 _argvec[2+6] = (unsigned long)arg6; \
2768 _argvec[2+7] = (unsigned long)arg7; \
2769 _argvec[2+8] = (unsigned long)arg8; \
2772 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2773 "stw 2,-8(11)\n\t" /* save tocptr */ \
2774 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2775 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2776 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2777 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2778 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2779 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2780 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2781 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2782 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2783 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2784 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2787 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2788 VG_CONTRACT_FRAME_BY(512) \
2789 : /*out*/ "=r" (_res) \
2790 : /*in*/ "r" (&_argvec[2]) \
2791 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2793 lval = (__typeof__(lval)) _res; \
2796 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2799 volatile OrigFn _orig = (orig); \
2800 volatile unsigned long _argvec[3+9]; \
2801 volatile unsigned long _res; \
2802 /* _argvec[0] holds current r2 across the call */ \
2803 _argvec[1] = (unsigned long)_orig.r2; \
2804 _argvec[2] = (unsigned long)_orig.nraddr; \
2805 _argvec[2+1] = (unsigned long)arg1; \
2806 _argvec[2+2] = (unsigned long)arg2; \
2807 _argvec[2+3] = (unsigned long)arg3; \
2808 _argvec[2+4] = (unsigned long)arg4; \
2809 _argvec[2+5] = (unsigned long)arg5; \
2810 _argvec[2+6] = (unsigned long)arg6; \
2811 _argvec[2+7] = (unsigned long)arg7; \
2812 _argvec[2+8] = (unsigned long)arg8; \
2813 _argvec[2+9] = (unsigned long)arg9; \
2816 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2817 "stw 2,-8(11)\n\t" /* save tocptr */ \
2818 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2819 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2821 "lwz 3,36(11)\n\t" \
2824 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2825 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2826 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2827 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2828 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2829 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2830 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2831 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2832 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2833 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2836 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2837 VG_CONTRACT_FRAME_BY(64) \
2838 VG_CONTRACT_FRAME_BY(512) \
2839 : /*out*/ "=r" (_res) \
2840 : /*in*/ "r" (&_argvec[2]) \
2841 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2843 lval = (__typeof__(lval)) _res; \
2846 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2847 arg7,arg8,arg9,arg10) \
2849 volatile OrigFn _orig = (orig); \
2850 volatile unsigned long _argvec[3+10]; \
2851 volatile unsigned long _res; \
2852 /* _argvec[0] holds current r2 across the call */ \
2853 _argvec[1] = (unsigned long)_orig.r2; \
2854 _argvec[2] = (unsigned long)_orig.nraddr; \
2855 _argvec[2+1] = (unsigned long)arg1; \
2856 _argvec[2+2] = (unsigned long)arg2; \
2857 _argvec[2+3] = (unsigned long)arg3; \
2858 _argvec[2+4] = (unsigned long)arg4; \
2859 _argvec[2+5] = (unsigned long)arg5; \
2860 _argvec[2+6] = (unsigned long)arg6; \
2861 _argvec[2+7] = (unsigned long)arg7; \
2862 _argvec[2+8] = (unsigned long)arg8; \
2863 _argvec[2+9] = (unsigned long)arg9; \
2864 _argvec[2+10] = (unsigned long)arg10; \
2867 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2868 "stw 2,-8(11)\n\t" /* save tocptr */ \
2869 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2870 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2872 "lwz 3,40(11)\n\t" \
2875 "lwz 3,36(11)\n\t" \
2878 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2879 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2880 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2881 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2882 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2883 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2884 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2885 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2886 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2887 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2890 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2891 VG_CONTRACT_FRAME_BY(64) \
2892 VG_CONTRACT_FRAME_BY(512) \
2893 : /*out*/ "=r" (_res) \
2894 : /*in*/ "r" (&_argvec[2]) \
2895 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2897 lval = (__typeof__(lval)) _res; \
2900 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2901 arg7,arg8,arg9,arg10,arg11) \
2903 volatile OrigFn _orig = (orig); \
2904 volatile unsigned long _argvec[3+11]; \
2905 volatile unsigned long _res; \
2906 /* _argvec[0] holds current r2 across the call */ \
2907 _argvec[1] = (unsigned long)_orig.r2; \
2908 _argvec[2] = (unsigned long)_orig.nraddr; \
2909 _argvec[2+1] = (unsigned long)arg1; \
2910 _argvec[2+2] = (unsigned long)arg2; \
2911 _argvec[2+3] = (unsigned long)arg3; \
2912 _argvec[2+4] = (unsigned long)arg4; \
2913 _argvec[2+5] = (unsigned long)arg5; \
2914 _argvec[2+6] = (unsigned long)arg6; \
2915 _argvec[2+7] = (unsigned long)arg7; \
2916 _argvec[2+8] = (unsigned long)arg8; \
2917 _argvec[2+9] = (unsigned long)arg9; \
2918 _argvec[2+10] = (unsigned long)arg10; \
2919 _argvec[2+11] = (unsigned long)arg11; \
2922 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2923 "stw 2,-8(11)\n\t" /* save tocptr */ \
2924 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2925 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2927 "lwz 3,44(11)\n\t" \
2930 "lwz 3,40(11)\n\t" \
2933 "lwz 3,36(11)\n\t" \
2936 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2937 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2938 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2939 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2940 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2941 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2942 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2943 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2944 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2945 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2948 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2949 VG_CONTRACT_FRAME_BY(72) \
2950 VG_CONTRACT_FRAME_BY(512) \
2951 : /*out*/ "=r" (_res) \
2952 : /*in*/ "r" (&_argvec[2]) \
2953 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2955 lval = (__typeof__(lval)) _res; \
2958 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2959 arg7,arg8,arg9,arg10,arg11,arg12) \
2961 volatile OrigFn _orig = (orig); \
2962 volatile unsigned long _argvec[3+12]; \
2963 volatile unsigned long _res; \
2964 /* _argvec[0] holds current r2 across the call */ \
2965 _argvec[1] = (unsigned long)_orig.r2; \
2966 _argvec[2] = (unsigned long)_orig.nraddr; \
2967 _argvec[2+1] = (unsigned long)arg1; \
2968 _argvec[2+2] = (unsigned long)arg2; \
2969 _argvec[2+3] = (unsigned long)arg3; \
2970 _argvec[2+4] = (unsigned long)arg4; \
2971 _argvec[2+5] = (unsigned long)arg5; \
2972 _argvec[2+6] = (unsigned long)arg6; \
2973 _argvec[2+7] = (unsigned long)arg7; \
2974 _argvec[2+8] = (unsigned long)arg8; \
2975 _argvec[2+9] = (unsigned long)arg9; \
2976 _argvec[2+10] = (unsigned long)arg10; \
2977 _argvec[2+11] = (unsigned long)arg11; \
2978 _argvec[2+12] = (unsigned long)arg12; \
2981 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2982 "stw 2,-8(11)\n\t" /* save tocptr */ \
2983 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2984 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2986 "lwz 3,48(11)\n\t" \
2989 "lwz 3,44(11)\n\t" \
2992 "lwz 3,40(11)\n\t" \
2995 "lwz 3,36(11)\n\t" \
2998 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2999 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3000 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3001 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3002 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3003 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3004 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3005 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3006 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3007 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3010 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3011 VG_CONTRACT_FRAME_BY(72) \
3012 VG_CONTRACT_FRAME_BY(512) \
3013 : /*out*/ "=r" (_res) \
3014 : /*in*/ "r" (&_argvec[2]) \
3015 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3017 lval = (__typeof__(lval)) _res; \
3020 #endif /* PLAT_ppc32_aix5 */
3022 /* ------------------------ ppc64-aix5 ------------------------- */
3024 #if defined(PLAT_ppc64_aix5)
3026 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3028 /* These regs are trashed by the hidden call. */
3029 #define __CALLER_SAVED_REGS \
3030 "lr", "ctr", "xer", \
3031 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3032 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3035 /* Expand the stack frame, copying enough info that unwinding
3036 still works. Trashes r3. */
3038 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3039 "addi 1,1,-" #_n_fr "\n\t" \
3040 "ld 3," #_n_fr "(1)\n\t" \
3043 #define VG_CONTRACT_FRAME_BY(_n_fr) \
3044 "addi 1,1," #_n_fr "\n\t"
3046 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3049 #define CALL_FN_W_v(lval, orig) \
3051 volatile OrigFn _orig = (orig); \
3052 volatile unsigned long _argvec[3+0]; \
3053 volatile unsigned long _res; \
3054 /* _argvec[0] holds current r2 across the call */ \
3055 _argvec[1] = (unsigned long)_orig.r2; \
3056 _argvec[2] = (unsigned long)_orig.nraddr; \
3059 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3060 "std 2,-16(11)\n\t" /* save tocptr */ \
3061 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3062 "ld 11, 0(11)\n\t" /* target->r11 */ \
3063 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3066 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3067 VG_CONTRACT_FRAME_BY(512) \
3068 : /*out*/ "=r" (_res) \
3069 : /*in*/ "r" (&_argvec[2]) \
3070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3072 lval = (__typeof__(lval)) _res; \
3075 #define CALL_FN_W_W(lval, orig, arg1) \
3077 volatile OrigFn _orig = (orig); \
3078 volatile unsigned long _argvec[3+1]; \
3079 volatile unsigned long _res; \
3080 /* _argvec[0] holds current r2 across the call */ \
3081 _argvec[1] = (unsigned long)_orig.r2; \
3082 _argvec[2] = (unsigned long)_orig.nraddr; \
3083 _argvec[2+1] = (unsigned long)arg1; \
3086 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3087 "std 2,-16(11)\n\t" /* save tocptr */ \
3088 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3089 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3090 "ld 11, 0(11)\n\t" /* target->r11 */ \
3091 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3094 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3095 VG_CONTRACT_FRAME_BY(512) \
3096 : /*out*/ "=r" (_res) \
3097 : /*in*/ "r" (&_argvec[2]) \
3098 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3100 lval = (__typeof__(lval)) _res; \
3103 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3105 volatile OrigFn _orig = (orig); \
3106 volatile unsigned long _argvec[3+2]; \
3107 volatile unsigned long _res; \
3108 /* _argvec[0] holds current r2 across the call */ \
3109 _argvec[1] = (unsigned long)_orig.r2; \
3110 _argvec[2] = (unsigned long)_orig.nraddr; \
3111 _argvec[2+1] = (unsigned long)arg1; \
3112 _argvec[2+2] = (unsigned long)arg2; \
3115 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3116 "std 2,-16(11)\n\t" /* save tocptr */ \
3117 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3118 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3119 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3120 "ld 11, 0(11)\n\t" /* target->r11 */ \
3121 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3124 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3125 VG_CONTRACT_FRAME_BY(512) \
3126 : /*out*/ "=r" (_res) \
3127 : /*in*/ "r" (&_argvec[2]) \
3128 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3130 lval = (__typeof__(lval)) _res; \
3133 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3135 volatile OrigFn _orig = (orig); \
3136 volatile unsigned long _argvec[3+3]; \
3137 volatile unsigned long _res; \
3138 /* _argvec[0] holds current r2 across the call */ \
3139 _argvec[1] = (unsigned long)_orig.r2; \
3140 _argvec[2] = (unsigned long)_orig.nraddr; \
3141 _argvec[2+1] = (unsigned long)arg1; \
3142 _argvec[2+2] = (unsigned long)arg2; \
3143 _argvec[2+3] = (unsigned long)arg3; \
3146 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3147 "std 2,-16(11)\n\t" /* save tocptr */ \
3148 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3149 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3150 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3151 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3152 "ld 11, 0(11)\n\t" /* target->r11 */ \
3153 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3156 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3157 VG_CONTRACT_FRAME_BY(512) \
3158 : /*out*/ "=r" (_res) \
3159 : /*in*/ "r" (&_argvec[2]) \
3160 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3162 lval = (__typeof__(lval)) _res; \
3165 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3167 volatile OrigFn _orig = (orig); \
3168 volatile unsigned long _argvec[3+4]; \
3169 volatile unsigned long _res; \
3170 /* _argvec[0] holds current r2 across the call */ \
3171 _argvec[1] = (unsigned long)_orig.r2; \
3172 _argvec[2] = (unsigned long)_orig.nraddr; \
3173 _argvec[2+1] = (unsigned long)arg1; \
3174 _argvec[2+2] = (unsigned long)arg2; \
3175 _argvec[2+3] = (unsigned long)arg3; \
3176 _argvec[2+4] = (unsigned long)arg4; \
3179 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3180 "std 2,-16(11)\n\t" /* save tocptr */ \
3181 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3182 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3183 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3184 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3185 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3186 "ld 11, 0(11)\n\t" /* target->r11 */ \
3187 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3190 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3191 VG_CONTRACT_FRAME_BY(512) \
3192 : /*out*/ "=r" (_res) \
3193 : /*in*/ "r" (&_argvec[2]) \
3194 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3196 lval = (__typeof__(lval)) _res; \
3199 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3201 volatile OrigFn _orig = (orig); \
3202 volatile unsigned long _argvec[3+5]; \
3203 volatile unsigned long _res; \
3204 /* _argvec[0] holds current r2 across the call */ \
3205 _argvec[1] = (unsigned long)_orig.r2; \
3206 _argvec[2] = (unsigned long)_orig.nraddr; \
3207 _argvec[2+1] = (unsigned long)arg1; \
3208 _argvec[2+2] = (unsigned long)arg2; \
3209 _argvec[2+3] = (unsigned long)arg3; \
3210 _argvec[2+4] = (unsigned long)arg4; \
3211 _argvec[2+5] = (unsigned long)arg5; \
3214 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3215 "std 2,-16(11)\n\t" /* save tocptr */ \
3216 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3217 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3218 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3219 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3220 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3221 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3222 "ld 11, 0(11)\n\t" /* target->r11 */ \
3223 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3226 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3227 VG_CONTRACT_FRAME_BY(512) \
3228 : /*out*/ "=r" (_res) \
3229 : /*in*/ "r" (&_argvec[2]) \
3230 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3232 lval = (__typeof__(lval)) _res; \
3235 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3237 volatile OrigFn _orig = (orig); \
3238 volatile unsigned long _argvec[3+6]; \
3239 volatile unsigned long _res; \
3240 /* _argvec[0] holds current r2 across the call */ \
3241 _argvec[1] = (unsigned long)_orig.r2; \
3242 _argvec[2] = (unsigned long)_orig.nraddr; \
3243 _argvec[2+1] = (unsigned long)arg1; \
3244 _argvec[2+2] = (unsigned long)arg2; \
3245 _argvec[2+3] = (unsigned long)arg3; \
3246 _argvec[2+4] = (unsigned long)arg4; \
3247 _argvec[2+5] = (unsigned long)arg5; \
3248 _argvec[2+6] = (unsigned long)arg6; \
3251 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3252 "std 2,-16(11)\n\t" /* save tocptr */ \
3253 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3254 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3255 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3256 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3257 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3258 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3259 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3260 "ld 11, 0(11)\n\t" /* target->r11 */ \
3261 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3264 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3265 VG_CONTRACT_FRAME_BY(512) \
3266 : /*out*/ "=r" (_res) \
3267 : /*in*/ "r" (&_argvec[2]) \
3268 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3270 lval = (__typeof__(lval)) _res; \
3273 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3276 volatile OrigFn _orig = (orig); \
3277 volatile unsigned long _argvec[3+7]; \
3278 volatile unsigned long _res; \
3279 /* _argvec[0] holds current r2 across the call */ \
3280 _argvec[1] = (unsigned long)_orig.r2; \
3281 _argvec[2] = (unsigned long)_orig.nraddr; \
3282 _argvec[2+1] = (unsigned long)arg1; \
3283 _argvec[2+2] = (unsigned long)arg2; \
3284 _argvec[2+3] = (unsigned long)arg3; \
3285 _argvec[2+4] = (unsigned long)arg4; \
3286 _argvec[2+5] = (unsigned long)arg5; \
3287 _argvec[2+6] = (unsigned long)arg6; \
3288 _argvec[2+7] = (unsigned long)arg7; \
3291 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3292 "std 2,-16(11)\n\t" /* save tocptr */ \
3293 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3294 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3295 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3296 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3297 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3298 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3299 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3300 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3301 "ld 11, 0(11)\n\t" /* target->r11 */ \
3302 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3305 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3306 VG_CONTRACT_FRAME_BY(512) \
3307 : /*out*/ "=r" (_res) \
3308 : /*in*/ "r" (&_argvec[2]) \
3309 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3311 lval = (__typeof__(lval)) _res; \
3314 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3317 volatile OrigFn _orig = (orig); \
3318 volatile unsigned long _argvec[3+8]; \
3319 volatile unsigned long _res; \
3320 /* _argvec[0] holds current r2 across the call */ \
3321 _argvec[1] = (unsigned long)_orig.r2; \
3322 _argvec[2] = (unsigned long)_orig.nraddr; \
3323 _argvec[2+1] = (unsigned long)arg1; \
3324 _argvec[2+2] = (unsigned long)arg2; \
3325 _argvec[2+3] = (unsigned long)arg3; \
3326 _argvec[2+4] = (unsigned long)arg4; \
3327 _argvec[2+5] = (unsigned long)arg5; \
3328 _argvec[2+6] = (unsigned long)arg6; \
3329 _argvec[2+7] = (unsigned long)arg7; \
3330 _argvec[2+8] = (unsigned long)arg8; \
3333 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3334 "std 2,-16(11)\n\t" /* save tocptr */ \
3335 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3336 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3337 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3338 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3339 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3340 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3341 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3342 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3343 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3344 "ld 11, 0(11)\n\t" /* target->r11 */ \
3345 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3348 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3349 VG_CONTRACT_FRAME_BY(512) \
3350 : /*out*/ "=r" (_res) \
3351 : /*in*/ "r" (&_argvec[2]) \
3352 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3354 lval = (__typeof__(lval)) _res; \
3357 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3360 volatile OrigFn _orig = (orig); \
3361 volatile unsigned long _argvec[3+9]; \
3362 volatile unsigned long _res; \
3363 /* _argvec[0] holds current r2 across the call */ \
3364 _argvec[1] = (unsigned long)_orig.r2; \
3365 _argvec[2] = (unsigned long)_orig.nraddr; \
3366 _argvec[2+1] = (unsigned long)arg1; \
3367 _argvec[2+2] = (unsigned long)arg2; \
3368 _argvec[2+3] = (unsigned long)arg3; \
3369 _argvec[2+4] = (unsigned long)arg4; \
3370 _argvec[2+5] = (unsigned long)arg5; \
3371 _argvec[2+6] = (unsigned long)arg6; \
3372 _argvec[2+7] = (unsigned long)arg7; \
3373 _argvec[2+8] = (unsigned long)arg8; \
3374 _argvec[2+9] = (unsigned long)arg9; \
3377 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3378 "std 2,-16(11)\n\t" /* save tocptr */ \
3379 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3380 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3383 "std 3,112(1)\n\t" \
3385 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3386 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3387 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3388 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3389 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3390 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3391 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3392 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3393 "ld 11, 0(11)\n\t" /* target->r11 */ \
3394 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3397 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3398 VG_CONTRACT_FRAME_BY(128) \
3399 VG_CONTRACT_FRAME_BY(512) \
3400 : /*out*/ "=r" (_res) \
3401 : /*in*/ "r" (&_argvec[2]) \
3402 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3404 lval = (__typeof__(lval)) _res; \
3407 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3408 arg7,arg8,arg9,arg10) \
3410 volatile OrigFn _orig = (orig); \
3411 volatile unsigned long _argvec[3+10]; \
3412 volatile unsigned long _res; \
3413 /* _argvec[0] holds current r2 across the call */ \
3414 _argvec[1] = (unsigned long)_orig.r2; \
3415 _argvec[2] = (unsigned long)_orig.nraddr; \
3416 _argvec[2+1] = (unsigned long)arg1; \
3417 _argvec[2+2] = (unsigned long)arg2; \
3418 _argvec[2+3] = (unsigned long)arg3; \
3419 _argvec[2+4] = (unsigned long)arg4; \
3420 _argvec[2+5] = (unsigned long)arg5; \
3421 _argvec[2+6] = (unsigned long)arg6; \
3422 _argvec[2+7] = (unsigned long)arg7; \
3423 _argvec[2+8] = (unsigned long)arg8; \
3424 _argvec[2+9] = (unsigned long)arg9; \
3425 _argvec[2+10] = (unsigned long)arg10; \
3428 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3429 "std 2,-16(11)\n\t" /* save tocptr */ \
3430 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3431 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3434 "std 3,120(1)\n\t" \
3437 "std 3,112(1)\n\t" \
3439 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3440 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3441 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3442 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3443 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3444 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3445 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3446 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3447 "ld 11, 0(11)\n\t" /* target->r11 */ \
3448 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3451 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3452 VG_CONTRACT_FRAME_BY(128) \
3453 VG_CONTRACT_FRAME_BY(512) \
3454 : /*out*/ "=r" (_res) \
3455 : /*in*/ "r" (&_argvec[2]) \
3456 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3458 lval = (__typeof__(lval)) _res; \
3461 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3462 arg7,arg8,arg9,arg10,arg11) \
3464 volatile OrigFn _orig = (orig); \
3465 volatile unsigned long _argvec[3+11]; \
3466 volatile unsigned long _res; \
3467 /* _argvec[0] holds current r2 across the call */ \
3468 _argvec[1] = (unsigned long)_orig.r2; \
3469 _argvec[2] = (unsigned long)_orig.nraddr; \
3470 _argvec[2+1] = (unsigned long)arg1; \
3471 _argvec[2+2] = (unsigned long)arg2; \
3472 _argvec[2+3] = (unsigned long)arg3; \
3473 _argvec[2+4] = (unsigned long)arg4; \
3474 _argvec[2+5] = (unsigned long)arg5; \
3475 _argvec[2+6] = (unsigned long)arg6; \
3476 _argvec[2+7] = (unsigned long)arg7; \
3477 _argvec[2+8] = (unsigned long)arg8; \
3478 _argvec[2+9] = (unsigned long)arg9; \
3479 _argvec[2+10] = (unsigned long)arg10; \
3480 _argvec[2+11] = (unsigned long)arg11; \
3483 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3484 "std 2,-16(11)\n\t" /* save tocptr */ \
3485 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3486 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3489 "std 3,128(1)\n\t" \
3492 "std 3,120(1)\n\t" \
3495 "std 3,112(1)\n\t" \
3497 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3498 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3499 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3500 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3501 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3502 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3503 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3504 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3505 "ld 11, 0(11)\n\t" /* target->r11 */ \
3506 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3509 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3510 VG_CONTRACT_FRAME_BY(144) \
3511 VG_CONTRACT_FRAME_BY(512) \
3512 : /*out*/ "=r" (_res) \
3513 : /*in*/ "r" (&_argvec[2]) \
3514 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3516 lval = (__typeof__(lval)) _res; \
3519 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3520 arg7,arg8,arg9,arg10,arg11,arg12) \
3522 volatile OrigFn _orig = (orig); \
3523 volatile unsigned long _argvec[3+12]; \
3524 volatile unsigned long _res; \
3525 /* _argvec[0] holds current r2 across the call */ \
3526 _argvec[1] = (unsigned long)_orig.r2; \
3527 _argvec[2] = (unsigned long)_orig.nraddr; \
3528 _argvec[2+1] = (unsigned long)arg1; \
3529 _argvec[2+2] = (unsigned long)arg2; \
3530 _argvec[2+3] = (unsigned long)arg3; \
3531 _argvec[2+4] = (unsigned long)arg4; \
3532 _argvec[2+5] = (unsigned long)arg5; \
3533 _argvec[2+6] = (unsigned long)arg6; \
3534 _argvec[2+7] = (unsigned long)arg7; \
3535 _argvec[2+8] = (unsigned long)arg8; \
3536 _argvec[2+9] = (unsigned long)arg9; \
3537 _argvec[2+10] = (unsigned long)arg10; \
3538 _argvec[2+11] = (unsigned long)arg11; \
3539 _argvec[2+12] = (unsigned long)arg12; \
3542 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3543 "std 2,-16(11)\n\t" /* save tocptr */ \
3544 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3545 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3548 "std 3,136(1)\n\t" \
3551 "std 3,128(1)\n\t" \
3554 "std 3,120(1)\n\t" \
3557 "std 3,112(1)\n\t" \
3559 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3560 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3561 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3562 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3563 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3564 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3565 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3566 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3567 "ld 11, 0(11)\n\t" /* target->r11 */ \
3568 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3571 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3572 VG_CONTRACT_FRAME_BY(144) \
3573 VG_CONTRACT_FRAME_BY(512) \
3574 : /*out*/ "=r" (_res) \
3575 : /*in*/ "r" (&_argvec[2]) \
3576 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3578 lval = (__typeof__(lval)) _res; \
3581 #endif /* PLAT_ppc64_aix5 */
3584 /* ------------------------------------------------------------------ */
3585 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
3587 /* ------------------------------------------------------------------ */
3589 /* Some request codes. There are many more of these, but most are not
3590 exposed to end-user view. These are the public ones, all of the
3591 form 0x1000 + small_number.
3593 Core ones are in the range 0x00000000--0x0000ffff. The non-public
3594 ones start at 0x2000.
3597 /* These macros are used by tools -- they must be public, but don't
3598 embed them into other programs. */
3599 #define VG_USERREQ_TOOL_BASE(a,b) \
3600 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
3601 #define VG_IS_TOOL_USERREQ(a, b, v) \
3602 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
3604 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3605 This enum comprises an ABI exported by Valgrind to programs
3606 which use client requests. DO NOT CHANGE THE ORDER OF THESE
3607 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
3609 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
3610 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
3612 /* These allow any function to be called from the simulated
3613 CPU but run on the real CPU. Nb: the first arg passed to
3614 the function is always the ThreadId of the running
3615 thread! So CLIENT_CALL0 actually requires a 1 arg
3617 VG_USERREQ__CLIENT_CALL0 = 0x1101,
3618 VG_USERREQ__CLIENT_CALL1 = 0x1102,
3619 VG_USERREQ__CLIENT_CALL2 = 0x1103,
3620 VG_USERREQ__CLIENT_CALL3 = 0x1104,
3622 /* Can be useful in regression testing suites -- eg. can
3623 send Valgrind's output to /dev/null and still count
3625 VG_USERREQ__COUNT_ERRORS = 0x1201,
3627 /* These are useful and can be interpreted by any tool that
3628 tracks malloc() et al, by using vg_replace_malloc.c. */
3629 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
3630 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
3631 /* Memory pool support. */
3632 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
3633 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
3634 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
3635 VG_USERREQ__MEMPOOL_FREE = 0x1306,
3636 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
3637 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
3638 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
3639 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
3641 /* Allow printfs to valgrind log. */
3642 VG_USERREQ__PRINTF = 0x1401,
3643 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
3645 /* Stack support. */
3646 VG_USERREQ__STACK_REGISTER = 0x1501,
3647 VG_USERREQ__STACK_DEREGISTER = 0x1502,
3648 VG_USERREQ__STACK_CHANGE = 0x1503,
3651 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
3654 #if !defined(__GNUC__)
3655 # define __extension__ /* */
3658 /* Returns the number of Valgrinds this code is running under. That
3659 is, 0 if running natively, 1 if running under Valgrind, 2 if
3660 running under Valgrind which is running under another Valgrind,
3662 #define RUNNING_ON_VALGRIND __extension__ \
3663 ({unsigned int _qzz_res; \
3664 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
3665 VG_USERREQ__RUNNING_ON_VALGRIND, \
3671 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3672 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
3673 since it provides a way to make sure valgrind will retranslate the
3674 invalidated area. Returns no value. */
3675 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
3676 {unsigned int _qzz_res; \
3677 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3678 VG_USERREQ__DISCARD_TRANSLATIONS, \
3679 _qzz_addr, _qzz_len, 0, 0, 0); \
3683 /* These requests are for getting Valgrind itself to print something.
3684 Possibly with a backtrace. This is a really ugly hack. The return value
3685 is the number of characters printed, excluding the "**<pid>** " part at the
3686 start and the backtrace (if present). */
3688 #if defined(NVALGRIND)
3690 # define VALGRIND_PRINTF(...)
3691 # define VALGRIND_PRINTF_BACKTRACE(...)
3693 #else /* NVALGRIND */
3695 /* Modern GCC will optimize the static routine out if unused,
3696 and unused attribute will shut down warnings about it. */
3697 static int VALGRIND_PRINTF(const char *format, ...)
3698 __attribute__((format(__printf__, 1, 2), __unused__));
3700 VALGRIND_PRINTF(const char *format, ...)
3702 unsigned long _qzz_res;
3704 va_start(vargs, format);
3705 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
3706 (unsigned long)format, (unsigned long)vargs,
3709 return (int)_qzz_res;
3712 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3713 __attribute__((format(__printf__, 1, 2), __unused__));
3715 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3717 unsigned long _qzz_res;
3719 va_start(vargs, format);
3720 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
3721 (unsigned long)format, (unsigned long)vargs,
3724 return (int)_qzz_res;
3727 #endif /* NVALGRIND */
3730 /* These requests allow control to move from the simulated CPU to the
3731 real CPU, calling an arbitary function.
3733 Note that the current ThreadId is inserted as the first argument.
3736 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3738 requires f to have this signature:
3740 Word f(Word tid, Word arg1, Word arg2)
3742 where "Word" is a word-sized type.
3744 Note that these client requests are not entirely reliable. For example,
3745 if you call a function with them that subsequently calls printf(),
3746 there's a high chance Valgrind will crash. Generally, your prospects of
3747 these working are made higher if the called function does not refer to
3748 any global variables, and does not refer to any libc or other functions
3749 (printf et al). Any kind of entanglement with libc or dynamic linking is
3750 likely to have a bad outcome, for tricky reasons which we've grappled
3751 with a lot in the past.
3753 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
3755 ({unsigned long _qyy_res; \
3756 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3757 VG_USERREQ__CLIENT_CALL0, \
3763 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
3765 ({unsigned long _qyy_res; \
3766 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3767 VG_USERREQ__CLIENT_CALL1, \
3769 _qyy_arg1, 0, 0, 0); \
3773 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
3775 ({unsigned long _qyy_res; \
3776 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3777 VG_USERREQ__CLIENT_CALL2, \
3779 _qyy_arg1, _qyy_arg2, 0, 0); \
3783 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
3785 ({unsigned long _qyy_res; \
3786 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3787 VG_USERREQ__CLIENT_CALL3, \
3789 _qyy_arg1, _qyy_arg2, \
3795 /* Counts the number of errors that have been recorded by a tool. Nb:
3796 the tool must record the errors with VG_(maybe_record_error)() or
3797 VG_(unique_error)() for them to be counted. */
3798 #define VALGRIND_COUNT_ERRORS \
3800 ({unsigned int _qyy_res; \
3801 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3802 VG_USERREQ__COUNT_ERRORS, \
3807 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
3808 when heap blocks are allocated in order to give accurate results. This
3809 happens automatically for the standard allocator functions such as
3810 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
3813 But if your program uses a custom allocator, this doesn't automatically
3814 happen, and Valgrind will not do as well. For example, if you allocate
3815 superblocks with mmap() and then allocates chunks of the superblocks, all
3816 Valgrind's observations will be at the mmap() level and it won't know that
3817 the chunks should be considered separate entities. In Memcheck's case,
3818 that means you probably won't get heap block overrun detection (because
3819 there won't be redzones marked as unaddressable) and you definitely won't
3820 get any leak detection.
3822 The following client requests allow a custom allocator to be annotated so
3823 that it can be handled accurately by Valgrind.
3825 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
3826 by a malloc()-like function. For Memcheck (an illustrative case), this
3829 - It records that the block has been allocated. This means any addresses
3830 within the block mentioned in error messages will be
3831 identified as belonging to the block. It also means that if the block
3832 isn't freed it will be detected by the leak checker.
3834 - It marks the block as being addressable and undefined (if 'is_zeroed' is
3835 not set), or addressable and defined (if 'is_zeroed' is set). This
3836 controls how accesses to the block by the program are handled.
3838 'addr' is the start of the usable block (ie. after any
3839 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
3840 can apply redzones -- these are blocks of padding at the start and end of
3841 each block. Adding redzones is recommended as it makes it much more likely
3842 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
3843 zeroed (or filled with another predictable value), as is the case for
3846 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
3847 heap block -- that will be used by the client program -- is allocated.
3848 It's best to put it at the outermost level of the allocator if possible;
3849 for example, if you have a function my_alloc() which calls
3850 internal_alloc(), and the client request is put inside internal_alloc(),
3851 stack traces relating to the heap block will contain entries for both
3852 my_alloc() and internal_alloc(), which is probably not what you want.
3854 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
3855 custom blocks from within a heap block, B, that has been allocated with
3856 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
3857 -- the custom blocks will take precedence.
3859 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
3860 Memcheck, it does two things:
3862 - It records that the block has been deallocated. This assumes that the
3863 block was annotated as having been allocated via
3864 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3866 - It marks the block as being unaddressable.
3868 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
3869 heap block is deallocated.
3871 In many cases, these two client requests will not be enough to get your
3872 allocator working well with Memcheck. More specifically, if your allocator
3873 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
3874 will be necessary to mark the memory as addressable just before the zeroing
3875 occurs, otherwise you'll get a lot of invalid write errors. For example,
3876 you'll need to do this if your allocator recycles freed blocks, but it
3877 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
3878 Alternatively, if your allocator reuses freed blocks for allocator-internal
3879 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
3881 Really, what's happening is a blurring of the lines between the client
3882 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
3883 memory should be considered unaddressable to the client program, but the
3884 allocator knows more than the rest of the client program and so may be able
3885 to safely access it. Extra client requests are necessary for Valgrind to
3886 understand the distinction between the allocator and the rest of the
3889 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
3890 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
3892 Ignored if addr == 0.
3894 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
3895 {unsigned int _qzz_res; \
3896 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3897 VG_USERREQ__MALLOCLIKE_BLOCK, \
3898 addr, sizeB, rzB, is_zeroed, 0); \
3901 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3902 Ignored if addr == 0.
3904 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
3905 {unsigned int _qzz_res; \
3906 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3907 VG_USERREQ__FREELIKE_BLOCK, \
3908 addr, rzB, 0, 0, 0); \
3911 /* Create a memory pool. */
3912 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
3913 {unsigned int _qzz_res; \
3914 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3915 VG_USERREQ__CREATE_MEMPOOL, \
3916 pool, rzB, is_zeroed, 0, 0); \
3919 /* Destroy a memory pool. */
3920 #define VALGRIND_DESTROY_MEMPOOL(pool) \
3921 {unsigned int _qzz_res; \
3922 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3923 VG_USERREQ__DESTROY_MEMPOOL, \
3924 pool, 0, 0, 0, 0); \
3927 /* Associate a piece of memory with a memory pool. */
3928 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
3929 {unsigned int _qzz_res; \
3930 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3931 VG_USERREQ__MEMPOOL_ALLOC, \
3932 pool, addr, size, 0, 0); \
3935 /* Disassociate a piece of memory from a memory pool. */
3936 #define VALGRIND_MEMPOOL_FREE(pool, addr) \
3937 {unsigned int _qzz_res; \
3938 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3939 VG_USERREQ__MEMPOOL_FREE, \
3940 pool, addr, 0, 0, 0); \
3943 /* Disassociate any pieces outside a particular range. */
3944 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
3945 {unsigned int _qzz_res; \
3946 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3947 VG_USERREQ__MEMPOOL_TRIM, \
3948 pool, addr, size, 0, 0); \
3951 /* Resize and/or move a piece associated with a memory pool. */
3952 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
3953 {unsigned int _qzz_res; \
3954 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3955 VG_USERREQ__MOVE_MEMPOOL, \
3956 poolA, poolB, 0, 0, 0); \
3959 /* Resize and/or move a piece associated with a memory pool. */
3960 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
3961 {unsigned int _qzz_res; \
3962 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3963 VG_USERREQ__MEMPOOL_CHANGE, \
3964 pool, addrA, addrB, size, 0); \
3967 /* Return 1 if a mempool exists, else 0. */
3968 #define VALGRIND_MEMPOOL_EXISTS(pool) \
3970 ({unsigned int _qzz_res; \
3971 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3972 VG_USERREQ__MEMPOOL_EXISTS, \
3973 pool, 0, 0, 0, 0); \
3977 /* Mark a piece of memory as being a stack. Returns a stack id. */
3978 #define VALGRIND_STACK_REGISTER(start, end) \
3980 ({unsigned int _qzz_res; \
3981 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3982 VG_USERREQ__STACK_REGISTER, \
3983 start, end, 0, 0, 0); \
3987 /* Unmark the piece of memory associated with a stack id as being a
3989 #define VALGRIND_STACK_DEREGISTER(id) \
3990 {unsigned int _qzz_res; \
3991 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3992 VG_USERREQ__STACK_DEREGISTER, \
3996 /* Change the start and end address of the stack id. */
3997 #define VALGRIND_STACK_CHANGE(id, start, end) \
3998 {unsigned int _qzz_res; \
3999 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4000 VG_USERREQ__STACK_CHANGE, \
4001 id, start, end, 0, 0); \
4004 /* Load PDB debug info for Wine PE image_map. */
4005 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4006 {unsigned int _qzz_res; \
4007 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4008 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4009 fd, ptr, total_size, delta, 0); \
4013 #undef PLAT_x86_linux
4014 #undef PLAT_amd64_linux
4015 #undef PLAT_ppc32_linux
4016 #undef PLAT_ppc64_linux
4017 #undef PLAT_ppc32_aix5
4018 #undef PLAT_ppc64_aix5
4020 #endif /* __VALGRIND_H */