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. */
80 /* Nb: this file might be included in a file compiled with -ansi. So
81 we can't use C++ style "//" comments nor the "asm" keyword (instead
84 /* Derive some tags indicating what the target platform is. Note
85 that in this file we're using the compiler's CPP symbols for
86 identifying architectures, which are different to the ones we use
87 within the rest of Valgrind. Note, __powerpc__ is active for both
88 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
89 latter (on Linux, that is). */
91 #undef PLAT_amd64_linux
92 #undef PLAT_ppc32_linux
93 #undef PLAT_ppc64_linux
94 #undef PLAT_ppc32_aix5
95 #undef PLAT_ppc64_aix5
98 #if defined(_AIX) && defined(__64BIT__)
99 # define PLAT_ppc64_aix5 1
100 #elif defined(_AIX) && !defined(__64BIT__)
101 # define PLAT_ppc32_aix5 1
102 #elif defined(__APPLE__) && defined(__i386__)
103 # define PLAT_x86_darwin 1
104 #elif defined(__APPLE__) && defined(__x86_64__)
105 # define PLAT_amd64_darwin 1
106 #elif defined(__i386__)
107 # define PLAT_x86_linux 1
108 #elif defined(__x86_64__)
109 # define PLAT_amd64_linux 1
110 #elif defined(__powerpc__) && !defined(__powerpc64__)
111 # define PLAT_ppc32_linux 1
112 #elif defined(__powerpc__) && defined(__powerpc64__)
113 # define PLAT_ppc64_linux 1
115 /* If we're not compiling for our target platform, don't generate
117 # if !defined(NVALGRIND)
123 /* ------------------------------------------------------------------ */
124 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
125 /* in here of use to end-users -- skip to the next section. */
126 /* ------------------------------------------------------------------ */
128 #if defined(NVALGRIND)
130 /* Define NVALGRIND to completely remove the Valgrind magic sequence
131 from the compiled code (analogous to NDEBUG's effects on
133 #define VALGRIND_DO_CLIENT_REQUEST( \
134 _zzq_rlval, _zzq_default, _zzq_request, \
135 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
137 (_zzq_rlval) = (_zzq_default); \
140 #else /* ! NVALGRIND */
142 /* The following defines the magic code sequences which the JITter
143 spots and handles magically. Don't look too closely at them as
144 they will rot your brain.
146 The assembly code sequences for all architectures is in this one
147 file. This is because this file must be stand-alone, and we don't
148 want to have multiple files.
150 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
151 value gets put in the return slot, so that everything works when
152 this is executed not under Valgrind. Args are passed in a memory
153 block, and so there's no intrinsic limit to the number that could
154 be passed, but it's currently five.
157 _zzq_rlval result lvalue
158 _zzq_default default value (result returned when running on real CPU)
159 _zzq_request request code
160 _zzq_arg1..5 request params
162 The other two macros are used to support function wrapping, and are
163 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
164 guest's NRADDR pseudo-register and whatever other information is
165 needed to safely run the call original from the wrapper: on
166 ppc64-linux, the R2 value at the divert point is also needed. This
167 information is abstracted into a user-visible type, OrigFn.
169 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
170 guest, but guarantees that the branch instruction will not be
171 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
172 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
173 complete inline asm, since it needs to be combined with more magic
174 inline asm stuff to be useful.
177 /* ------------------------- x86-{linux,darwin} ---------------- */
179 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
183 unsigned int nraddr; /* where's the code? */
187 #define __SPECIAL_INSTRUCTION_PREAMBLE \
188 "roll $3, %%edi ; roll $13, %%edi\n\t" \
189 "roll $29, %%edi ; roll $19, %%edi\n\t"
191 #define VALGRIND_DO_CLIENT_REQUEST( \
192 _zzq_rlval, _zzq_default, _zzq_request, \
193 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
194 { volatile unsigned int _zzq_args[6]; \
195 volatile unsigned int _zzq_result; \
196 _zzq_args[0] = (unsigned int)(_zzq_request); \
197 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
198 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
199 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
200 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
201 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
202 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
203 /* %EDX = client_request ( %EAX ) */ \
204 "xchgl %%ebx,%%ebx" \
205 : "=d" (_zzq_result) \
206 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
209 _zzq_rlval = _zzq_result; \
212 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
213 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
214 volatile unsigned int __addr; \
215 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
216 /* %EAX = guest_NRADDR */ \
217 "xchgl %%ecx,%%ecx" \
222 _zzq_orig->nraddr = __addr; \
225 #define VALGRIND_CALL_NOREDIR_EAX \
226 __SPECIAL_INSTRUCTION_PREAMBLE \
227 /* call-noredir *%EAX */ \
228 "xchgl %%edx,%%edx\n\t"
229 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
231 /* ------------------------ amd64-{linux,darwin} --------------- */
233 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
237 unsigned long long int nraddr; /* where's the code? */
241 #define __SPECIAL_INSTRUCTION_PREAMBLE \
242 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
243 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
245 #define VALGRIND_DO_CLIENT_REQUEST( \
246 _zzq_rlval, _zzq_default, _zzq_request, \
247 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
248 { volatile unsigned long long int _zzq_args[6]; \
249 volatile unsigned long long int _zzq_result; \
250 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
251 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
252 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
253 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
254 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
255 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
256 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
257 /* %RDX = client_request ( %RAX ) */ \
258 "xchgq %%rbx,%%rbx" \
259 : "=d" (_zzq_result) \
260 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
263 _zzq_rlval = _zzq_result; \
266 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
267 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
268 volatile unsigned long long int __addr; \
269 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
270 /* %RAX = guest_NRADDR */ \
271 "xchgq %%rcx,%%rcx" \
276 _zzq_orig->nraddr = __addr; \
279 #define VALGRIND_CALL_NOREDIR_RAX \
280 __SPECIAL_INSTRUCTION_PREAMBLE \
281 /* call-noredir *%RAX */ \
282 "xchgq %%rdx,%%rdx\n\t"
283 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
285 /* ------------------------ ppc32-linux ------------------------ */
287 #if defined(PLAT_ppc32_linux)
291 unsigned int nraddr; /* where's the code? */
295 #define __SPECIAL_INSTRUCTION_PREAMBLE \
296 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
297 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
299 #define VALGRIND_DO_CLIENT_REQUEST( \
300 _zzq_rlval, _zzq_default, _zzq_request, \
301 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
303 { unsigned int _zzq_args[6]; \
304 unsigned int _zzq_result; \
305 unsigned int* _zzq_ptr; \
306 _zzq_args[0] = (unsigned int)(_zzq_request); \
307 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
308 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
309 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
310 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
311 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
312 _zzq_ptr = _zzq_args; \
313 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
314 "mr 4,%2\n\t" /*ptr*/ \
315 __SPECIAL_INSTRUCTION_PREAMBLE \
316 /* %R3 = client_request ( %R4 ) */ \
318 "mr %0,3" /*result*/ \
319 : "=b" (_zzq_result) \
320 : "b" (_zzq_default), "b" (_zzq_ptr) \
321 : "cc", "memory", "r3", "r4"); \
322 _zzq_rlval = _zzq_result; \
325 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
326 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
327 unsigned int __addr; \
328 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
329 /* %R3 = guest_NRADDR */ \
334 : "cc", "memory", "r3" \
336 _zzq_orig->nraddr = __addr; \
339 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
340 __SPECIAL_INSTRUCTION_PREAMBLE \
341 /* branch-and-link-to-noredir *%R11 */ \
343 #endif /* PLAT_ppc32_linux */
345 /* ------------------------ ppc64-linux ------------------------ */
347 #if defined(PLAT_ppc64_linux)
351 unsigned long long int nraddr; /* where's the code? */
352 unsigned long long int r2; /* what tocptr do we need? */
356 #define __SPECIAL_INSTRUCTION_PREAMBLE \
357 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
358 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
360 #define VALGRIND_DO_CLIENT_REQUEST( \
361 _zzq_rlval, _zzq_default, _zzq_request, \
362 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
364 { unsigned long long int _zzq_args[6]; \
365 register unsigned long long int _zzq_result __asm__("r3"); \
366 register unsigned long long int* _zzq_ptr __asm__("r4"); \
367 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
368 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
369 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
370 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
371 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
372 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
373 _zzq_ptr = _zzq_args; \
374 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
375 /* %R3 = client_request ( %R4 ) */ \
377 : "=r" (_zzq_result) \
378 : "0" (_zzq_default), "r" (_zzq_ptr) \
380 _zzq_rlval = _zzq_result; \
383 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
384 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
385 register unsigned long long int __addr __asm__("r3"); \
386 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
387 /* %R3 = guest_NRADDR */ \
393 _zzq_orig->nraddr = __addr; \
394 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
395 /* %R3 = guest_NRADDR_GPR2 */ \
401 _zzq_orig->r2 = __addr; \
404 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
405 __SPECIAL_INSTRUCTION_PREAMBLE \
406 /* branch-and-link-to-noredir *%R11 */ \
409 #endif /* PLAT_ppc64_linux */
411 /* ------------------------ ppc32-aix5 ------------------------- */
413 #if defined(PLAT_ppc32_aix5)
417 unsigned int nraddr; /* where's the code? */
418 unsigned int r2; /* what tocptr do we need? */
422 #define __SPECIAL_INSTRUCTION_PREAMBLE \
423 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
424 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
426 #define VALGRIND_DO_CLIENT_REQUEST( \
427 _zzq_rlval, _zzq_default, _zzq_request, \
428 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
430 { unsigned int _zzq_args[7]; \
431 register unsigned int _zzq_result; \
432 register unsigned int* _zzq_ptr; \
433 _zzq_args[0] = (unsigned int)(_zzq_request); \
434 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
435 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
436 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
437 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
438 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
439 _zzq_args[6] = (unsigned int)(_zzq_default); \
440 _zzq_ptr = _zzq_args; \
441 __asm__ volatile("mr 4,%1\n\t" \
443 __SPECIAL_INSTRUCTION_PREAMBLE \
444 /* %R3 = client_request ( %R4 ) */ \
447 : "=b" (_zzq_result) \
449 : "r3", "r4", "cc", "memory"); \
450 _zzq_rlval = _zzq_result; \
453 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
454 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
455 register unsigned int __addr; \
456 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
457 /* %R3 = guest_NRADDR */ \
462 : "r3", "cc", "memory" \
464 _zzq_orig->nraddr = __addr; \
465 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
466 /* %R3 = guest_NRADDR_GPR2 */ \
471 : "r3", "cc", "memory" \
473 _zzq_orig->r2 = __addr; \
476 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
477 __SPECIAL_INSTRUCTION_PREAMBLE \
478 /* branch-and-link-to-noredir *%R11 */ \
481 #endif /* PLAT_ppc32_aix5 */
483 /* ------------------------ ppc64-aix5 ------------------------- */
485 #if defined(PLAT_ppc64_aix5)
489 unsigned long long int nraddr; /* where's the code? */
490 unsigned long long int r2; /* what tocptr do we need? */
494 #define __SPECIAL_INSTRUCTION_PREAMBLE \
495 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
496 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
498 #define VALGRIND_DO_CLIENT_REQUEST( \
499 _zzq_rlval, _zzq_default, _zzq_request, \
500 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
502 { unsigned long long int _zzq_args[7]; \
503 register unsigned long long int _zzq_result; \
504 register unsigned long long int* _zzq_ptr; \
505 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
506 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
507 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
508 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
509 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
510 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
511 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
512 _zzq_ptr = _zzq_args; \
513 __asm__ volatile("mr 4,%1\n\t" \
515 __SPECIAL_INSTRUCTION_PREAMBLE \
516 /* %R3 = client_request ( %R4 ) */ \
519 : "=b" (_zzq_result) \
521 : "r3", "r4", "cc", "memory"); \
522 _zzq_rlval = _zzq_result; \
525 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
526 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
527 register unsigned long long int __addr; \
528 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
529 /* %R3 = guest_NRADDR */ \
534 : "r3", "cc", "memory" \
536 _zzq_orig->nraddr = __addr; \
537 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
538 /* %R3 = guest_NRADDR_GPR2 */ \
543 : "r3", "cc", "memory" \
545 _zzq_orig->r2 = __addr; \
548 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
549 __SPECIAL_INSTRUCTION_PREAMBLE \
550 /* branch-and-link-to-noredir *%R11 */ \
553 #endif /* PLAT_ppc64_aix5 */
555 /* Insert assembly code for other platforms here... */
557 #endif /* NVALGRIND */
560 /* ------------------------------------------------------------------ */
561 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
562 /* ugly. It's the least-worst tradeoff I can think of. */
563 /* ------------------------------------------------------------------ */
565 /* This section defines magic (a.k.a appalling-hack) macros for doing
566 guaranteed-no-redirection macros, so as to get from function
567 wrappers to the functions they are wrapping. The whole point is to
568 construct standard call sequences, but to do the call itself with a
569 special no-redirect call pseudo-instruction that the JIT
570 understands and handles specially. This section is long and
571 repetitious, and I can't see a way to make it shorter.
573 The naming scheme is as follows:
575 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
577 'W' stands for "word" and 'v' for "void". Hence there are
578 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
579 and for each, the possibility of returning a word-typed result, or
583 /* Use these to write the name of your wrapper. NOTE: duplicates
584 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
586 /* Use an extra level of macroisation so as to ensure the soname/fnname
587 args are fully macro-expanded before pasting them together. */
588 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
590 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
591 VG_CONCAT4(_vgwZU_,soname,_,fnname)
593 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
594 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
596 /* Use this macro from within a wrapper function to collect the
597 context (address and possibly other info) of the original function.
598 Once you have that you can then use it in one of the CALL_FN_
599 macros. The type of the argument _lval is OrigFn. */
600 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
602 /* Derivatives of the main macros below, for calling functions
605 #define CALL_FN_v_v(fnptr) \
606 do { volatile unsigned long _junk; \
607 CALL_FN_W_v(_junk,fnptr); } while (0)
609 #define CALL_FN_v_W(fnptr, arg1) \
610 do { volatile unsigned long _junk; \
611 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
613 #define CALL_FN_v_WW(fnptr, arg1,arg2) \
614 do { volatile unsigned long _junk; \
615 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
617 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
618 do { volatile unsigned long _junk; \
619 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
621 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
622 do { volatile unsigned long _junk; \
623 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
625 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
626 do { volatile unsigned long _junk; \
627 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
629 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
630 do { volatile unsigned long _junk; \
631 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
633 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
634 do { volatile unsigned long _junk; \
635 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
637 /* ------------------------- x86-{linux,darwin} ---------------- */
639 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
641 /* These regs are trashed by the hidden call. No need to mention eax
642 as gcc can already see that, plus causes gcc to bomb. */
643 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
645 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
648 #define CALL_FN_W_v(lval, orig) \
650 volatile OrigFn _orig = (orig); \
651 volatile unsigned long _argvec[1]; \
652 volatile unsigned long _res; \
653 _argvec[0] = (unsigned long)_orig.nraddr; \
655 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
656 VALGRIND_CALL_NOREDIR_EAX \
657 : /*out*/ "=a" (_res) \
658 : /*in*/ "a" (&_argvec[0]) \
659 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
661 lval = (__typeof__(lval)) _res; \
664 #define CALL_FN_W_W(lval, orig, arg1) \
666 volatile OrigFn _orig = (orig); \
667 volatile unsigned long _argvec[2]; \
668 volatile unsigned long _res; \
669 _argvec[0] = (unsigned long)_orig.nraddr; \
670 _argvec[1] = (unsigned long)(arg1); \
672 "pushl 4(%%eax)\n\t" \
673 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
674 VALGRIND_CALL_NOREDIR_EAX \
676 : /*out*/ "=a" (_res) \
677 : /*in*/ "a" (&_argvec[0]) \
678 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
680 lval = (__typeof__(lval)) _res; \
683 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
685 volatile OrigFn _orig = (orig); \
686 volatile unsigned long _argvec[3]; \
687 volatile unsigned long _res; \
688 _argvec[0] = (unsigned long)_orig.nraddr; \
689 _argvec[1] = (unsigned long)(arg1); \
690 _argvec[2] = (unsigned long)(arg2); \
692 "pushl 8(%%eax)\n\t" \
693 "pushl 4(%%eax)\n\t" \
694 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
695 VALGRIND_CALL_NOREDIR_EAX \
697 : /*out*/ "=a" (_res) \
698 : /*in*/ "a" (&_argvec[0]) \
699 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
701 lval = (__typeof__(lval)) _res; \
704 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
706 volatile OrigFn _orig = (orig); \
707 volatile unsigned long _argvec[4]; \
708 volatile unsigned long _res; \
709 _argvec[0] = (unsigned long)_orig.nraddr; \
710 _argvec[1] = (unsigned long)(arg1); \
711 _argvec[2] = (unsigned long)(arg2); \
712 _argvec[3] = (unsigned long)(arg3); \
714 "pushl 12(%%eax)\n\t" \
715 "pushl 8(%%eax)\n\t" \
716 "pushl 4(%%eax)\n\t" \
717 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
718 VALGRIND_CALL_NOREDIR_EAX \
719 "addl $12, %%esp\n" \
720 : /*out*/ "=a" (_res) \
721 : /*in*/ "a" (&_argvec[0]) \
722 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
724 lval = (__typeof__(lval)) _res; \
727 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
729 volatile OrigFn _orig = (orig); \
730 volatile unsigned long _argvec[5]; \
731 volatile unsigned long _res; \
732 _argvec[0] = (unsigned long)_orig.nraddr; \
733 _argvec[1] = (unsigned long)(arg1); \
734 _argvec[2] = (unsigned long)(arg2); \
735 _argvec[3] = (unsigned long)(arg3); \
736 _argvec[4] = (unsigned long)(arg4); \
738 "pushl 16(%%eax)\n\t" \
739 "pushl 12(%%eax)\n\t" \
740 "pushl 8(%%eax)\n\t" \
741 "pushl 4(%%eax)\n\t" \
742 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
743 VALGRIND_CALL_NOREDIR_EAX \
744 "addl $16, %%esp\n" \
745 : /*out*/ "=a" (_res) \
746 : /*in*/ "a" (&_argvec[0]) \
747 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
749 lval = (__typeof__(lval)) _res; \
752 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
754 volatile OrigFn _orig = (orig); \
755 volatile unsigned long _argvec[6]; \
756 volatile unsigned long _res; \
757 _argvec[0] = (unsigned long)_orig.nraddr; \
758 _argvec[1] = (unsigned long)(arg1); \
759 _argvec[2] = (unsigned long)(arg2); \
760 _argvec[3] = (unsigned long)(arg3); \
761 _argvec[4] = (unsigned long)(arg4); \
762 _argvec[5] = (unsigned long)(arg5); \
764 "pushl 20(%%eax)\n\t" \
765 "pushl 16(%%eax)\n\t" \
766 "pushl 12(%%eax)\n\t" \
767 "pushl 8(%%eax)\n\t" \
768 "pushl 4(%%eax)\n\t" \
769 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
770 VALGRIND_CALL_NOREDIR_EAX \
771 "addl $20, %%esp\n" \
772 : /*out*/ "=a" (_res) \
773 : /*in*/ "a" (&_argvec[0]) \
774 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
776 lval = (__typeof__(lval)) _res; \
779 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
781 volatile OrigFn _orig = (orig); \
782 volatile unsigned long _argvec[7]; \
783 volatile unsigned long _res; \
784 _argvec[0] = (unsigned long)_orig.nraddr; \
785 _argvec[1] = (unsigned long)(arg1); \
786 _argvec[2] = (unsigned long)(arg2); \
787 _argvec[3] = (unsigned long)(arg3); \
788 _argvec[4] = (unsigned long)(arg4); \
789 _argvec[5] = (unsigned long)(arg5); \
790 _argvec[6] = (unsigned long)(arg6); \
792 "pushl 24(%%eax)\n\t" \
793 "pushl 20(%%eax)\n\t" \
794 "pushl 16(%%eax)\n\t" \
795 "pushl 12(%%eax)\n\t" \
796 "pushl 8(%%eax)\n\t" \
797 "pushl 4(%%eax)\n\t" \
798 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
799 VALGRIND_CALL_NOREDIR_EAX \
800 "addl $24, %%esp\n" \
801 : /*out*/ "=a" (_res) \
802 : /*in*/ "a" (&_argvec[0]) \
803 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
805 lval = (__typeof__(lval)) _res; \
808 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
811 volatile OrigFn _orig = (orig); \
812 volatile unsigned long _argvec[8]; \
813 volatile unsigned long _res; \
814 _argvec[0] = (unsigned long)_orig.nraddr; \
815 _argvec[1] = (unsigned long)(arg1); \
816 _argvec[2] = (unsigned long)(arg2); \
817 _argvec[3] = (unsigned long)(arg3); \
818 _argvec[4] = (unsigned long)(arg4); \
819 _argvec[5] = (unsigned long)(arg5); \
820 _argvec[6] = (unsigned long)(arg6); \
821 _argvec[7] = (unsigned long)(arg7); \
823 "pushl 28(%%eax)\n\t" \
824 "pushl 24(%%eax)\n\t" \
825 "pushl 20(%%eax)\n\t" \
826 "pushl 16(%%eax)\n\t" \
827 "pushl 12(%%eax)\n\t" \
828 "pushl 8(%%eax)\n\t" \
829 "pushl 4(%%eax)\n\t" \
830 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
831 VALGRIND_CALL_NOREDIR_EAX \
832 "addl $28, %%esp\n" \
833 : /*out*/ "=a" (_res) \
834 : /*in*/ "a" (&_argvec[0]) \
835 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
837 lval = (__typeof__(lval)) _res; \
840 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
843 volatile OrigFn _orig = (orig); \
844 volatile unsigned long _argvec[9]; \
845 volatile unsigned long _res; \
846 _argvec[0] = (unsigned long)_orig.nraddr; \
847 _argvec[1] = (unsigned long)(arg1); \
848 _argvec[2] = (unsigned long)(arg2); \
849 _argvec[3] = (unsigned long)(arg3); \
850 _argvec[4] = (unsigned long)(arg4); \
851 _argvec[5] = (unsigned long)(arg5); \
852 _argvec[6] = (unsigned long)(arg6); \
853 _argvec[7] = (unsigned long)(arg7); \
854 _argvec[8] = (unsigned long)(arg8); \
856 "pushl 32(%%eax)\n\t" \
857 "pushl 28(%%eax)\n\t" \
858 "pushl 24(%%eax)\n\t" \
859 "pushl 20(%%eax)\n\t" \
860 "pushl 16(%%eax)\n\t" \
861 "pushl 12(%%eax)\n\t" \
862 "pushl 8(%%eax)\n\t" \
863 "pushl 4(%%eax)\n\t" \
864 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
865 VALGRIND_CALL_NOREDIR_EAX \
866 "addl $32, %%esp\n" \
867 : /*out*/ "=a" (_res) \
868 : /*in*/ "a" (&_argvec[0]) \
869 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
871 lval = (__typeof__(lval)) _res; \
874 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
877 volatile OrigFn _orig = (orig); \
878 volatile unsigned long _argvec[10]; \
879 volatile unsigned long _res; \
880 _argvec[0] = (unsigned long)_orig.nraddr; \
881 _argvec[1] = (unsigned long)(arg1); \
882 _argvec[2] = (unsigned long)(arg2); \
883 _argvec[3] = (unsigned long)(arg3); \
884 _argvec[4] = (unsigned long)(arg4); \
885 _argvec[5] = (unsigned long)(arg5); \
886 _argvec[6] = (unsigned long)(arg6); \
887 _argvec[7] = (unsigned long)(arg7); \
888 _argvec[8] = (unsigned long)(arg8); \
889 _argvec[9] = (unsigned long)(arg9); \
891 "pushl 36(%%eax)\n\t" \
892 "pushl 32(%%eax)\n\t" \
893 "pushl 28(%%eax)\n\t" \
894 "pushl 24(%%eax)\n\t" \
895 "pushl 20(%%eax)\n\t" \
896 "pushl 16(%%eax)\n\t" \
897 "pushl 12(%%eax)\n\t" \
898 "pushl 8(%%eax)\n\t" \
899 "pushl 4(%%eax)\n\t" \
900 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
901 VALGRIND_CALL_NOREDIR_EAX \
902 "addl $36, %%esp\n" \
903 : /*out*/ "=a" (_res) \
904 : /*in*/ "a" (&_argvec[0]) \
905 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
907 lval = (__typeof__(lval)) _res; \
910 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
911 arg7,arg8,arg9,arg10) \
913 volatile OrigFn _orig = (orig); \
914 volatile unsigned long _argvec[11]; \
915 volatile unsigned long _res; \
916 _argvec[0] = (unsigned long)_orig.nraddr; \
917 _argvec[1] = (unsigned long)(arg1); \
918 _argvec[2] = (unsigned long)(arg2); \
919 _argvec[3] = (unsigned long)(arg3); \
920 _argvec[4] = (unsigned long)(arg4); \
921 _argvec[5] = (unsigned long)(arg5); \
922 _argvec[6] = (unsigned long)(arg6); \
923 _argvec[7] = (unsigned long)(arg7); \
924 _argvec[8] = (unsigned long)(arg8); \
925 _argvec[9] = (unsigned long)(arg9); \
926 _argvec[10] = (unsigned long)(arg10); \
928 "pushl 40(%%eax)\n\t" \
929 "pushl 36(%%eax)\n\t" \
930 "pushl 32(%%eax)\n\t" \
931 "pushl 28(%%eax)\n\t" \
932 "pushl 24(%%eax)\n\t" \
933 "pushl 20(%%eax)\n\t" \
934 "pushl 16(%%eax)\n\t" \
935 "pushl 12(%%eax)\n\t" \
936 "pushl 8(%%eax)\n\t" \
937 "pushl 4(%%eax)\n\t" \
938 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
939 VALGRIND_CALL_NOREDIR_EAX \
940 "addl $40, %%esp\n" \
941 : /*out*/ "=a" (_res) \
942 : /*in*/ "a" (&_argvec[0]) \
943 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
945 lval = (__typeof__(lval)) _res; \
948 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
949 arg6,arg7,arg8,arg9,arg10, \
952 volatile OrigFn _orig = (orig); \
953 volatile unsigned long _argvec[12]; \
954 volatile unsigned long _res; \
955 _argvec[0] = (unsigned long)_orig.nraddr; \
956 _argvec[1] = (unsigned long)(arg1); \
957 _argvec[2] = (unsigned long)(arg2); \
958 _argvec[3] = (unsigned long)(arg3); \
959 _argvec[4] = (unsigned long)(arg4); \
960 _argvec[5] = (unsigned long)(arg5); \
961 _argvec[6] = (unsigned long)(arg6); \
962 _argvec[7] = (unsigned long)(arg7); \
963 _argvec[8] = (unsigned long)(arg8); \
964 _argvec[9] = (unsigned long)(arg9); \
965 _argvec[10] = (unsigned long)(arg10); \
966 _argvec[11] = (unsigned long)(arg11); \
968 "pushl 44(%%eax)\n\t" \
969 "pushl 40(%%eax)\n\t" \
970 "pushl 36(%%eax)\n\t" \
971 "pushl 32(%%eax)\n\t" \
972 "pushl 28(%%eax)\n\t" \
973 "pushl 24(%%eax)\n\t" \
974 "pushl 20(%%eax)\n\t" \
975 "pushl 16(%%eax)\n\t" \
976 "pushl 12(%%eax)\n\t" \
977 "pushl 8(%%eax)\n\t" \
978 "pushl 4(%%eax)\n\t" \
979 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
980 VALGRIND_CALL_NOREDIR_EAX \
981 "addl $44, %%esp\n" \
982 : /*out*/ "=a" (_res) \
983 : /*in*/ "a" (&_argvec[0]) \
984 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
986 lval = (__typeof__(lval)) _res; \
989 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
990 arg6,arg7,arg8,arg9,arg10, \
993 volatile OrigFn _orig = (orig); \
994 volatile unsigned long _argvec[13]; \
995 volatile unsigned long _res; \
996 _argvec[0] = (unsigned long)_orig.nraddr; \
997 _argvec[1] = (unsigned long)(arg1); \
998 _argvec[2] = (unsigned long)(arg2); \
999 _argvec[3] = (unsigned long)(arg3); \
1000 _argvec[4] = (unsigned long)(arg4); \
1001 _argvec[5] = (unsigned long)(arg5); \
1002 _argvec[6] = (unsigned long)(arg6); \
1003 _argvec[7] = (unsigned long)(arg7); \
1004 _argvec[8] = (unsigned long)(arg8); \
1005 _argvec[9] = (unsigned long)(arg9); \
1006 _argvec[10] = (unsigned long)(arg10); \
1007 _argvec[11] = (unsigned long)(arg11); \
1008 _argvec[12] = (unsigned long)(arg12); \
1010 "pushl 48(%%eax)\n\t" \
1011 "pushl 44(%%eax)\n\t" \
1012 "pushl 40(%%eax)\n\t" \
1013 "pushl 36(%%eax)\n\t" \
1014 "pushl 32(%%eax)\n\t" \
1015 "pushl 28(%%eax)\n\t" \
1016 "pushl 24(%%eax)\n\t" \
1017 "pushl 20(%%eax)\n\t" \
1018 "pushl 16(%%eax)\n\t" \
1019 "pushl 12(%%eax)\n\t" \
1020 "pushl 8(%%eax)\n\t" \
1021 "pushl 4(%%eax)\n\t" \
1022 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1023 VALGRIND_CALL_NOREDIR_EAX \
1024 "addl $48, %%esp\n" \
1025 : /*out*/ "=a" (_res) \
1026 : /*in*/ "a" (&_argvec[0]) \
1027 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1029 lval = (__typeof__(lval)) _res; \
1032 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
1034 /* ------------------------ amd64-{linux,darwin} --------------- */
1036 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
1038 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1040 /* These regs are trashed by the hidden call. */
1041 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1042 "rdi", "r8", "r9", "r10", "r11"
1044 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1047 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1048 macros. In order not to trash the stack redzone, we need to drop
1049 %rsp by 128 before the hidden call, and restore afterwards. The
1050 nastyness is that it is only by luck that the stack still appears
1051 to be unwindable during the hidden call - since then the behaviour
1052 of any routine using this macro does not match what the CFI data
1055 Why is this important? Imagine that a wrapper has a stack
1056 allocated local, and passes to the hidden call, a pointer to it.
1057 Because gcc does not know about the hidden call, it may allocate
1058 that local in the redzone. Unfortunately the hidden call may then
1059 trash it before it comes to use it. So we must step clear of the
1060 redzone, for the duration of the hidden call, to make it safe.
1062 Probably the same problem afflicts the other redzone-style ABIs too
1063 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1064 self describing (none of this CFI nonsense) so at least messing
1065 with the stack pointer doesn't give a danger of non-unwindable
1068 #define CALL_FN_W_v(lval, orig) \
1070 volatile OrigFn _orig = (orig); \
1071 volatile unsigned long _argvec[1]; \
1072 volatile unsigned long _res; \
1073 _argvec[0] = (unsigned long)_orig.nraddr; \
1075 "subq $128,%%rsp\n\t" \
1076 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1077 VALGRIND_CALL_NOREDIR_RAX \
1078 "addq $128,%%rsp\n\t" \
1079 : /*out*/ "=a" (_res) \
1080 : /*in*/ "a" (&_argvec[0]) \
1081 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1083 lval = (__typeof__(lval)) _res; \
1086 #define CALL_FN_W_W(lval, orig, arg1) \
1088 volatile OrigFn _orig = (orig); \
1089 volatile unsigned long _argvec[2]; \
1090 volatile unsigned long _res; \
1091 _argvec[0] = (unsigned long)_orig.nraddr; \
1092 _argvec[1] = (unsigned long)(arg1); \
1094 "subq $128,%%rsp\n\t" \
1095 "movq 8(%%rax), %%rdi\n\t" \
1096 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1097 VALGRIND_CALL_NOREDIR_RAX \
1098 "addq $128,%%rsp\n\t" \
1099 : /*out*/ "=a" (_res) \
1100 : /*in*/ "a" (&_argvec[0]) \
1101 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1103 lval = (__typeof__(lval)) _res; \
1106 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1108 volatile OrigFn _orig = (orig); \
1109 volatile unsigned long _argvec[3]; \
1110 volatile unsigned long _res; \
1111 _argvec[0] = (unsigned long)_orig.nraddr; \
1112 _argvec[1] = (unsigned long)(arg1); \
1113 _argvec[2] = (unsigned long)(arg2); \
1115 "subq $128,%%rsp\n\t" \
1116 "movq 16(%%rax), %%rsi\n\t" \
1117 "movq 8(%%rax), %%rdi\n\t" \
1118 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1119 VALGRIND_CALL_NOREDIR_RAX \
1120 "addq $128,%%rsp\n\t" \
1121 : /*out*/ "=a" (_res) \
1122 : /*in*/ "a" (&_argvec[0]) \
1123 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1125 lval = (__typeof__(lval)) _res; \
1128 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1130 volatile OrigFn _orig = (orig); \
1131 volatile unsigned long _argvec[4]; \
1132 volatile unsigned long _res; \
1133 _argvec[0] = (unsigned long)_orig.nraddr; \
1134 _argvec[1] = (unsigned long)(arg1); \
1135 _argvec[2] = (unsigned long)(arg2); \
1136 _argvec[3] = (unsigned long)(arg3); \
1138 "subq $128,%%rsp\n\t" \
1139 "movq 24(%%rax), %%rdx\n\t" \
1140 "movq 16(%%rax), %%rsi\n\t" \
1141 "movq 8(%%rax), %%rdi\n\t" \
1142 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1143 VALGRIND_CALL_NOREDIR_RAX \
1144 "addq $128,%%rsp\n\t" \
1145 : /*out*/ "=a" (_res) \
1146 : /*in*/ "a" (&_argvec[0]) \
1147 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1149 lval = (__typeof__(lval)) _res; \
1152 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1154 volatile OrigFn _orig = (orig); \
1155 volatile unsigned long _argvec[5]; \
1156 volatile unsigned long _res; \
1157 _argvec[0] = (unsigned long)_orig.nraddr; \
1158 _argvec[1] = (unsigned long)(arg1); \
1159 _argvec[2] = (unsigned long)(arg2); \
1160 _argvec[3] = (unsigned long)(arg3); \
1161 _argvec[4] = (unsigned long)(arg4); \
1163 "subq $128,%%rsp\n\t" \
1164 "movq 32(%%rax), %%rcx\n\t" \
1165 "movq 24(%%rax), %%rdx\n\t" \
1166 "movq 16(%%rax), %%rsi\n\t" \
1167 "movq 8(%%rax), %%rdi\n\t" \
1168 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1169 VALGRIND_CALL_NOREDIR_RAX \
1170 "addq $128,%%rsp\n\t" \
1171 : /*out*/ "=a" (_res) \
1172 : /*in*/ "a" (&_argvec[0]) \
1173 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1175 lval = (__typeof__(lval)) _res; \
1178 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1180 volatile OrigFn _orig = (orig); \
1181 volatile unsigned long _argvec[6]; \
1182 volatile unsigned long _res; \
1183 _argvec[0] = (unsigned long)_orig.nraddr; \
1184 _argvec[1] = (unsigned long)(arg1); \
1185 _argvec[2] = (unsigned long)(arg2); \
1186 _argvec[3] = (unsigned long)(arg3); \
1187 _argvec[4] = (unsigned long)(arg4); \
1188 _argvec[5] = (unsigned long)(arg5); \
1190 "subq $128,%%rsp\n\t" \
1191 "movq 40(%%rax), %%r8\n\t" \
1192 "movq 32(%%rax), %%rcx\n\t" \
1193 "movq 24(%%rax), %%rdx\n\t" \
1194 "movq 16(%%rax), %%rsi\n\t" \
1195 "movq 8(%%rax), %%rdi\n\t" \
1196 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1197 VALGRIND_CALL_NOREDIR_RAX \
1198 "addq $128,%%rsp\n\t" \
1199 : /*out*/ "=a" (_res) \
1200 : /*in*/ "a" (&_argvec[0]) \
1201 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1203 lval = (__typeof__(lval)) _res; \
1206 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1208 volatile OrigFn _orig = (orig); \
1209 volatile unsigned long _argvec[7]; \
1210 volatile unsigned long _res; \
1211 _argvec[0] = (unsigned long)_orig.nraddr; \
1212 _argvec[1] = (unsigned long)(arg1); \
1213 _argvec[2] = (unsigned long)(arg2); \
1214 _argvec[3] = (unsigned long)(arg3); \
1215 _argvec[4] = (unsigned long)(arg4); \
1216 _argvec[5] = (unsigned long)(arg5); \
1217 _argvec[6] = (unsigned long)(arg6); \
1219 "subq $128,%%rsp\n\t" \
1220 "movq 48(%%rax), %%r9\n\t" \
1221 "movq 40(%%rax), %%r8\n\t" \
1222 "movq 32(%%rax), %%rcx\n\t" \
1223 "movq 24(%%rax), %%rdx\n\t" \
1224 "movq 16(%%rax), %%rsi\n\t" \
1225 "movq 8(%%rax), %%rdi\n\t" \
1226 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1227 "addq $128,%%rsp\n\t" \
1228 VALGRIND_CALL_NOREDIR_RAX \
1229 : /*out*/ "=a" (_res) \
1230 : /*in*/ "a" (&_argvec[0]) \
1231 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1233 lval = (__typeof__(lval)) _res; \
1236 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1239 volatile OrigFn _orig = (orig); \
1240 volatile unsigned long _argvec[8]; \
1241 volatile unsigned long _res; \
1242 _argvec[0] = (unsigned long)_orig.nraddr; \
1243 _argvec[1] = (unsigned long)(arg1); \
1244 _argvec[2] = (unsigned long)(arg2); \
1245 _argvec[3] = (unsigned long)(arg3); \
1246 _argvec[4] = (unsigned long)(arg4); \
1247 _argvec[5] = (unsigned long)(arg5); \
1248 _argvec[6] = (unsigned long)(arg6); \
1249 _argvec[7] = (unsigned long)(arg7); \
1251 "subq $128,%%rsp\n\t" \
1252 "pushq 56(%%rax)\n\t" \
1253 "movq 48(%%rax), %%r9\n\t" \
1254 "movq 40(%%rax), %%r8\n\t" \
1255 "movq 32(%%rax), %%rcx\n\t" \
1256 "movq 24(%%rax), %%rdx\n\t" \
1257 "movq 16(%%rax), %%rsi\n\t" \
1258 "movq 8(%%rax), %%rdi\n\t" \
1259 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1260 VALGRIND_CALL_NOREDIR_RAX \
1261 "addq $8, %%rsp\n" \
1262 "addq $128,%%rsp\n\t" \
1263 : /*out*/ "=a" (_res) \
1264 : /*in*/ "a" (&_argvec[0]) \
1265 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1267 lval = (__typeof__(lval)) _res; \
1270 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1273 volatile OrigFn _orig = (orig); \
1274 volatile unsigned long _argvec[9]; \
1275 volatile unsigned long _res; \
1276 _argvec[0] = (unsigned long)_orig.nraddr; \
1277 _argvec[1] = (unsigned long)(arg1); \
1278 _argvec[2] = (unsigned long)(arg2); \
1279 _argvec[3] = (unsigned long)(arg3); \
1280 _argvec[4] = (unsigned long)(arg4); \
1281 _argvec[5] = (unsigned long)(arg5); \
1282 _argvec[6] = (unsigned long)(arg6); \
1283 _argvec[7] = (unsigned long)(arg7); \
1284 _argvec[8] = (unsigned long)(arg8); \
1286 "subq $128,%%rsp\n\t" \
1287 "pushq 64(%%rax)\n\t" \
1288 "pushq 56(%%rax)\n\t" \
1289 "movq 48(%%rax), %%r9\n\t" \
1290 "movq 40(%%rax), %%r8\n\t" \
1291 "movq 32(%%rax), %%rcx\n\t" \
1292 "movq 24(%%rax), %%rdx\n\t" \
1293 "movq 16(%%rax), %%rsi\n\t" \
1294 "movq 8(%%rax), %%rdi\n\t" \
1295 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1296 VALGRIND_CALL_NOREDIR_RAX \
1297 "addq $16, %%rsp\n" \
1298 "addq $128,%%rsp\n\t" \
1299 : /*out*/ "=a" (_res) \
1300 : /*in*/ "a" (&_argvec[0]) \
1301 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1303 lval = (__typeof__(lval)) _res; \
1306 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1309 volatile OrigFn _orig = (orig); \
1310 volatile unsigned long _argvec[10]; \
1311 volatile unsigned long _res; \
1312 _argvec[0] = (unsigned long)_orig.nraddr; \
1313 _argvec[1] = (unsigned long)(arg1); \
1314 _argvec[2] = (unsigned long)(arg2); \
1315 _argvec[3] = (unsigned long)(arg3); \
1316 _argvec[4] = (unsigned long)(arg4); \
1317 _argvec[5] = (unsigned long)(arg5); \
1318 _argvec[6] = (unsigned long)(arg6); \
1319 _argvec[7] = (unsigned long)(arg7); \
1320 _argvec[8] = (unsigned long)(arg8); \
1321 _argvec[9] = (unsigned long)(arg9); \
1323 "subq $128,%%rsp\n\t" \
1324 "pushq 72(%%rax)\n\t" \
1325 "pushq 64(%%rax)\n\t" \
1326 "pushq 56(%%rax)\n\t" \
1327 "movq 48(%%rax), %%r9\n\t" \
1328 "movq 40(%%rax), %%r8\n\t" \
1329 "movq 32(%%rax), %%rcx\n\t" \
1330 "movq 24(%%rax), %%rdx\n\t" \
1331 "movq 16(%%rax), %%rsi\n\t" \
1332 "movq 8(%%rax), %%rdi\n\t" \
1333 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1334 VALGRIND_CALL_NOREDIR_RAX \
1335 "addq $24, %%rsp\n" \
1336 "addq $128,%%rsp\n\t" \
1337 : /*out*/ "=a" (_res) \
1338 : /*in*/ "a" (&_argvec[0]) \
1339 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1341 lval = (__typeof__(lval)) _res; \
1344 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1345 arg7,arg8,arg9,arg10) \
1347 volatile OrigFn _orig = (orig); \
1348 volatile unsigned long _argvec[11]; \
1349 volatile unsigned long _res; \
1350 _argvec[0] = (unsigned long)_orig.nraddr; \
1351 _argvec[1] = (unsigned long)(arg1); \
1352 _argvec[2] = (unsigned long)(arg2); \
1353 _argvec[3] = (unsigned long)(arg3); \
1354 _argvec[4] = (unsigned long)(arg4); \
1355 _argvec[5] = (unsigned long)(arg5); \
1356 _argvec[6] = (unsigned long)(arg6); \
1357 _argvec[7] = (unsigned long)(arg7); \
1358 _argvec[8] = (unsigned long)(arg8); \
1359 _argvec[9] = (unsigned long)(arg9); \
1360 _argvec[10] = (unsigned long)(arg10); \
1362 "subq $128,%%rsp\n\t" \
1363 "pushq 80(%%rax)\n\t" \
1364 "pushq 72(%%rax)\n\t" \
1365 "pushq 64(%%rax)\n\t" \
1366 "pushq 56(%%rax)\n\t" \
1367 "movq 48(%%rax), %%r9\n\t" \
1368 "movq 40(%%rax), %%r8\n\t" \
1369 "movq 32(%%rax), %%rcx\n\t" \
1370 "movq 24(%%rax), %%rdx\n\t" \
1371 "movq 16(%%rax), %%rsi\n\t" \
1372 "movq 8(%%rax), %%rdi\n\t" \
1373 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1374 VALGRIND_CALL_NOREDIR_RAX \
1375 "addq $32, %%rsp\n" \
1376 "addq $128,%%rsp\n\t" \
1377 : /*out*/ "=a" (_res) \
1378 : /*in*/ "a" (&_argvec[0]) \
1379 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1381 lval = (__typeof__(lval)) _res; \
1384 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1385 arg7,arg8,arg9,arg10,arg11) \
1387 volatile OrigFn _orig = (orig); \
1388 volatile unsigned long _argvec[12]; \
1389 volatile unsigned long _res; \
1390 _argvec[0] = (unsigned long)_orig.nraddr; \
1391 _argvec[1] = (unsigned long)(arg1); \
1392 _argvec[2] = (unsigned long)(arg2); \
1393 _argvec[3] = (unsigned long)(arg3); \
1394 _argvec[4] = (unsigned long)(arg4); \
1395 _argvec[5] = (unsigned long)(arg5); \
1396 _argvec[6] = (unsigned long)(arg6); \
1397 _argvec[7] = (unsigned long)(arg7); \
1398 _argvec[8] = (unsigned long)(arg8); \
1399 _argvec[9] = (unsigned long)(arg9); \
1400 _argvec[10] = (unsigned long)(arg10); \
1401 _argvec[11] = (unsigned long)(arg11); \
1403 "subq $128,%%rsp\n\t" \
1404 "pushq 88(%%rax)\n\t" \
1405 "pushq 80(%%rax)\n\t" \
1406 "pushq 72(%%rax)\n\t" \
1407 "pushq 64(%%rax)\n\t" \
1408 "pushq 56(%%rax)\n\t" \
1409 "movq 48(%%rax), %%r9\n\t" \
1410 "movq 40(%%rax), %%r8\n\t" \
1411 "movq 32(%%rax), %%rcx\n\t" \
1412 "movq 24(%%rax), %%rdx\n\t" \
1413 "movq 16(%%rax), %%rsi\n\t" \
1414 "movq 8(%%rax), %%rdi\n\t" \
1415 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1416 VALGRIND_CALL_NOREDIR_RAX \
1417 "addq $40, %%rsp\n" \
1418 "addq $128,%%rsp\n\t" \
1419 : /*out*/ "=a" (_res) \
1420 : /*in*/ "a" (&_argvec[0]) \
1421 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1423 lval = (__typeof__(lval)) _res; \
1426 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1427 arg7,arg8,arg9,arg10,arg11,arg12) \
1429 volatile OrigFn _orig = (orig); \
1430 volatile unsigned long _argvec[13]; \
1431 volatile unsigned long _res; \
1432 _argvec[0] = (unsigned long)_orig.nraddr; \
1433 _argvec[1] = (unsigned long)(arg1); \
1434 _argvec[2] = (unsigned long)(arg2); \
1435 _argvec[3] = (unsigned long)(arg3); \
1436 _argvec[4] = (unsigned long)(arg4); \
1437 _argvec[5] = (unsigned long)(arg5); \
1438 _argvec[6] = (unsigned long)(arg6); \
1439 _argvec[7] = (unsigned long)(arg7); \
1440 _argvec[8] = (unsigned long)(arg8); \
1441 _argvec[9] = (unsigned long)(arg9); \
1442 _argvec[10] = (unsigned long)(arg10); \
1443 _argvec[11] = (unsigned long)(arg11); \
1444 _argvec[12] = (unsigned long)(arg12); \
1446 "subq $128,%%rsp\n\t" \
1447 "pushq 96(%%rax)\n\t" \
1448 "pushq 88(%%rax)\n\t" \
1449 "pushq 80(%%rax)\n\t" \
1450 "pushq 72(%%rax)\n\t" \
1451 "pushq 64(%%rax)\n\t" \
1452 "pushq 56(%%rax)\n\t" \
1453 "movq 48(%%rax), %%r9\n\t" \
1454 "movq 40(%%rax), %%r8\n\t" \
1455 "movq 32(%%rax), %%rcx\n\t" \
1456 "movq 24(%%rax), %%rdx\n\t" \
1457 "movq 16(%%rax), %%rsi\n\t" \
1458 "movq 8(%%rax), %%rdi\n\t" \
1459 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1460 VALGRIND_CALL_NOREDIR_RAX \
1461 "addq $48, %%rsp\n" \
1462 "addq $128,%%rsp\n\t" \
1463 : /*out*/ "=a" (_res) \
1464 : /*in*/ "a" (&_argvec[0]) \
1465 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1467 lval = (__typeof__(lval)) _res; \
1470 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
1472 /* ------------------------ ppc32-linux ------------------------ */
1474 #if defined(PLAT_ppc32_linux)
1476 /* This is useful for finding out about the on-stack stuff:
1478 extern int f9 ( int,int,int,int,int,int,int,int,int );
1479 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1480 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1481 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1484 return f9(11,22,33,44,55,66,77,88,99);
1487 return f10(11,22,33,44,55,66,77,88,99,110);
1490 return f11(11,22,33,44,55,66,77,88,99,110,121);
1493 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1497 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1499 /* These regs are trashed by the hidden call. */
1500 #define __CALLER_SAVED_REGS \
1501 "lr", "ctr", "xer", \
1502 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1503 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1506 /* These CALL_FN_ macros assume that on ppc32-linux,
1507 sizeof(unsigned long) == 4. */
1509 #define CALL_FN_W_v(lval, orig) \
1511 volatile OrigFn _orig = (orig); \
1512 volatile unsigned long _argvec[1]; \
1513 volatile unsigned long _res; \
1514 _argvec[0] = (unsigned long)_orig.nraddr; \
1517 "lwz 11,0(11)\n\t" /* target->r11 */ \
1518 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1520 : /*out*/ "=r" (_res) \
1521 : /*in*/ "r" (&_argvec[0]) \
1522 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1524 lval = (__typeof__(lval)) _res; \
1527 #define CALL_FN_W_W(lval, orig, arg1) \
1529 volatile OrigFn _orig = (orig); \
1530 volatile unsigned long _argvec[2]; \
1531 volatile unsigned long _res; \
1532 _argvec[0] = (unsigned long)_orig.nraddr; \
1533 _argvec[1] = (unsigned long)arg1; \
1536 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1537 "lwz 11,0(11)\n\t" /* target->r11 */ \
1538 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1540 : /*out*/ "=r" (_res) \
1541 : /*in*/ "r" (&_argvec[0]) \
1542 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1544 lval = (__typeof__(lval)) _res; \
1547 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1549 volatile OrigFn _orig = (orig); \
1550 volatile unsigned long _argvec[3]; \
1551 volatile unsigned long _res; \
1552 _argvec[0] = (unsigned long)_orig.nraddr; \
1553 _argvec[1] = (unsigned long)arg1; \
1554 _argvec[2] = (unsigned long)arg2; \
1557 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1559 "lwz 11,0(11)\n\t" /* target->r11 */ \
1560 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1562 : /*out*/ "=r" (_res) \
1563 : /*in*/ "r" (&_argvec[0]) \
1564 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1566 lval = (__typeof__(lval)) _res; \
1569 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1571 volatile OrigFn _orig = (orig); \
1572 volatile unsigned long _argvec[4]; \
1573 volatile unsigned long _res; \
1574 _argvec[0] = (unsigned long)_orig.nraddr; \
1575 _argvec[1] = (unsigned long)arg1; \
1576 _argvec[2] = (unsigned long)arg2; \
1577 _argvec[3] = (unsigned long)arg3; \
1580 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1582 "lwz 5,12(11)\n\t" \
1583 "lwz 11,0(11)\n\t" /* target->r11 */ \
1584 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1586 : /*out*/ "=r" (_res) \
1587 : /*in*/ "r" (&_argvec[0]) \
1588 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1590 lval = (__typeof__(lval)) _res; \
1593 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1595 volatile OrigFn _orig = (orig); \
1596 volatile unsigned long _argvec[5]; \
1597 volatile unsigned long _res; \
1598 _argvec[0] = (unsigned long)_orig.nraddr; \
1599 _argvec[1] = (unsigned long)arg1; \
1600 _argvec[2] = (unsigned long)arg2; \
1601 _argvec[3] = (unsigned long)arg3; \
1602 _argvec[4] = (unsigned long)arg4; \
1605 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1607 "lwz 5,12(11)\n\t" \
1608 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1609 "lwz 11,0(11)\n\t" /* target->r11 */ \
1610 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1612 : /*out*/ "=r" (_res) \
1613 : /*in*/ "r" (&_argvec[0]) \
1614 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1616 lval = (__typeof__(lval)) _res; \
1619 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1621 volatile OrigFn _orig = (orig); \
1622 volatile unsigned long _argvec[6]; \
1623 volatile unsigned long _res; \
1624 _argvec[0] = (unsigned long)_orig.nraddr; \
1625 _argvec[1] = (unsigned long)arg1; \
1626 _argvec[2] = (unsigned long)arg2; \
1627 _argvec[3] = (unsigned long)arg3; \
1628 _argvec[4] = (unsigned long)arg4; \
1629 _argvec[5] = (unsigned long)arg5; \
1632 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1634 "lwz 5,12(11)\n\t" \
1635 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1636 "lwz 7,20(11)\n\t" \
1637 "lwz 11,0(11)\n\t" /* target->r11 */ \
1638 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1640 : /*out*/ "=r" (_res) \
1641 : /*in*/ "r" (&_argvec[0]) \
1642 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1644 lval = (__typeof__(lval)) _res; \
1647 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1649 volatile OrigFn _orig = (orig); \
1650 volatile unsigned long _argvec[7]; \
1651 volatile unsigned long _res; \
1652 _argvec[0] = (unsigned long)_orig.nraddr; \
1653 _argvec[1] = (unsigned long)arg1; \
1654 _argvec[2] = (unsigned long)arg2; \
1655 _argvec[3] = (unsigned long)arg3; \
1656 _argvec[4] = (unsigned long)arg4; \
1657 _argvec[5] = (unsigned long)arg5; \
1658 _argvec[6] = (unsigned long)arg6; \
1661 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1663 "lwz 5,12(11)\n\t" \
1664 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1665 "lwz 7,20(11)\n\t" \
1666 "lwz 8,24(11)\n\t" \
1667 "lwz 11,0(11)\n\t" /* target->r11 */ \
1668 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1670 : /*out*/ "=r" (_res) \
1671 : /*in*/ "r" (&_argvec[0]) \
1672 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1674 lval = (__typeof__(lval)) _res; \
1677 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1680 volatile OrigFn _orig = (orig); \
1681 volatile unsigned long _argvec[8]; \
1682 volatile unsigned long _res; \
1683 _argvec[0] = (unsigned long)_orig.nraddr; \
1684 _argvec[1] = (unsigned long)arg1; \
1685 _argvec[2] = (unsigned long)arg2; \
1686 _argvec[3] = (unsigned long)arg3; \
1687 _argvec[4] = (unsigned long)arg4; \
1688 _argvec[5] = (unsigned long)arg5; \
1689 _argvec[6] = (unsigned long)arg6; \
1690 _argvec[7] = (unsigned long)arg7; \
1693 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1695 "lwz 5,12(11)\n\t" \
1696 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1697 "lwz 7,20(11)\n\t" \
1698 "lwz 8,24(11)\n\t" \
1699 "lwz 9,28(11)\n\t" \
1700 "lwz 11,0(11)\n\t" /* target->r11 */ \
1701 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1703 : /*out*/ "=r" (_res) \
1704 : /*in*/ "r" (&_argvec[0]) \
1705 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1707 lval = (__typeof__(lval)) _res; \
1710 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1713 volatile OrigFn _orig = (orig); \
1714 volatile unsigned long _argvec[9]; \
1715 volatile unsigned long _res; \
1716 _argvec[0] = (unsigned long)_orig.nraddr; \
1717 _argvec[1] = (unsigned long)arg1; \
1718 _argvec[2] = (unsigned long)arg2; \
1719 _argvec[3] = (unsigned long)arg3; \
1720 _argvec[4] = (unsigned long)arg4; \
1721 _argvec[5] = (unsigned long)arg5; \
1722 _argvec[6] = (unsigned long)arg6; \
1723 _argvec[7] = (unsigned long)arg7; \
1724 _argvec[8] = (unsigned long)arg8; \
1727 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1729 "lwz 5,12(11)\n\t" \
1730 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1731 "lwz 7,20(11)\n\t" \
1732 "lwz 8,24(11)\n\t" \
1733 "lwz 9,28(11)\n\t" \
1734 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1735 "lwz 11,0(11)\n\t" /* target->r11 */ \
1736 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1738 : /*out*/ "=r" (_res) \
1739 : /*in*/ "r" (&_argvec[0]) \
1740 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1742 lval = (__typeof__(lval)) _res; \
1745 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1748 volatile OrigFn _orig = (orig); \
1749 volatile unsigned long _argvec[10]; \
1750 volatile unsigned long _res; \
1751 _argvec[0] = (unsigned long)_orig.nraddr; \
1752 _argvec[1] = (unsigned long)arg1; \
1753 _argvec[2] = (unsigned long)arg2; \
1754 _argvec[3] = (unsigned long)arg3; \
1755 _argvec[4] = (unsigned long)arg4; \
1756 _argvec[5] = (unsigned long)arg5; \
1757 _argvec[6] = (unsigned long)arg6; \
1758 _argvec[7] = (unsigned long)arg7; \
1759 _argvec[8] = (unsigned long)arg8; \
1760 _argvec[9] = (unsigned long)arg9; \
1763 "addi 1,1,-16\n\t" \
1765 "lwz 3,36(11)\n\t" \
1768 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1770 "lwz 5,12(11)\n\t" \
1771 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1772 "lwz 7,20(11)\n\t" \
1773 "lwz 8,24(11)\n\t" \
1774 "lwz 9,28(11)\n\t" \
1775 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1776 "lwz 11,0(11)\n\t" /* target->r11 */ \
1777 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1780 : /*out*/ "=r" (_res) \
1781 : /*in*/ "r" (&_argvec[0]) \
1782 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1784 lval = (__typeof__(lval)) _res; \
1787 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1788 arg7,arg8,arg9,arg10) \
1790 volatile OrigFn _orig = (orig); \
1791 volatile unsigned long _argvec[11]; \
1792 volatile unsigned long _res; \
1793 _argvec[0] = (unsigned long)_orig.nraddr; \
1794 _argvec[1] = (unsigned long)arg1; \
1795 _argvec[2] = (unsigned long)arg2; \
1796 _argvec[3] = (unsigned long)arg3; \
1797 _argvec[4] = (unsigned long)arg4; \
1798 _argvec[5] = (unsigned long)arg5; \
1799 _argvec[6] = (unsigned long)arg6; \
1800 _argvec[7] = (unsigned long)arg7; \
1801 _argvec[8] = (unsigned long)arg8; \
1802 _argvec[9] = (unsigned long)arg9; \
1803 _argvec[10] = (unsigned long)arg10; \
1806 "addi 1,1,-16\n\t" \
1808 "lwz 3,40(11)\n\t" \
1811 "lwz 3,36(11)\n\t" \
1814 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1816 "lwz 5,12(11)\n\t" \
1817 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1818 "lwz 7,20(11)\n\t" \
1819 "lwz 8,24(11)\n\t" \
1820 "lwz 9,28(11)\n\t" \
1821 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1822 "lwz 11,0(11)\n\t" /* target->r11 */ \
1823 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1826 : /*out*/ "=r" (_res) \
1827 : /*in*/ "r" (&_argvec[0]) \
1828 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1830 lval = (__typeof__(lval)) _res; \
1833 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1834 arg7,arg8,arg9,arg10,arg11) \
1836 volatile OrigFn _orig = (orig); \
1837 volatile unsigned long _argvec[12]; \
1838 volatile unsigned long _res; \
1839 _argvec[0] = (unsigned long)_orig.nraddr; \
1840 _argvec[1] = (unsigned long)arg1; \
1841 _argvec[2] = (unsigned long)arg2; \
1842 _argvec[3] = (unsigned long)arg3; \
1843 _argvec[4] = (unsigned long)arg4; \
1844 _argvec[5] = (unsigned long)arg5; \
1845 _argvec[6] = (unsigned long)arg6; \
1846 _argvec[7] = (unsigned long)arg7; \
1847 _argvec[8] = (unsigned long)arg8; \
1848 _argvec[9] = (unsigned long)arg9; \
1849 _argvec[10] = (unsigned long)arg10; \
1850 _argvec[11] = (unsigned long)arg11; \
1853 "addi 1,1,-32\n\t" \
1855 "lwz 3,44(11)\n\t" \
1858 "lwz 3,40(11)\n\t" \
1861 "lwz 3,36(11)\n\t" \
1864 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1866 "lwz 5,12(11)\n\t" \
1867 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1868 "lwz 7,20(11)\n\t" \
1869 "lwz 8,24(11)\n\t" \
1870 "lwz 9,28(11)\n\t" \
1871 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1872 "lwz 11,0(11)\n\t" /* target->r11 */ \
1873 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1876 : /*out*/ "=r" (_res) \
1877 : /*in*/ "r" (&_argvec[0]) \
1878 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1880 lval = (__typeof__(lval)) _res; \
1883 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1884 arg7,arg8,arg9,arg10,arg11,arg12) \
1886 volatile OrigFn _orig = (orig); \
1887 volatile unsigned long _argvec[13]; \
1888 volatile unsigned long _res; \
1889 _argvec[0] = (unsigned long)_orig.nraddr; \
1890 _argvec[1] = (unsigned long)arg1; \
1891 _argvec[2] = (unsigned long)arg2; \
1892 _argvec[3] = (unsigned long)arg3; \
1893 _argvec[4] = (unsigned long)arg4; \
1894 _argvec[5] = (unsigned long)arg5; \
1895 _argvec[6] = (unsigned long)arg6; \
1896 _argvec[7] = (unsigned long)arg7; \
1897 _argvec[8] = (unsigned long)arg8; \
1898 _argvec[9] = (unsigned long)arg9; \
1899 _argvec[10] = (unsigned long)arg10; \
1900 _argvec[11] = (unsigned long)arg11; \
1901 _argvec[12] = (unsigned long)arg12; \
1904 "addi 1,1,-32\n\t" \
1906 "lwz 3,48(11)\n\t" \
1909 "lwz 3,44(11)\n\t" \
1912 "lwz 3,40(11)\n\t" \
1915 "lwz 3,36(11)\n\t" \
1918 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1920 "lwz 5,12(11)\n\t" \
1921 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1922 "lwz 7,20(11)\n\t" \
1923 "lwz 8,24(11)\n\t" \
1924 "lwz 9,28(11)\n\t" \
1925 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1926 "lwz 11,0(11)\n\t" /* target->r11 */ \
1927 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1930 : /*out*/ "=r" (_res) \
1931 : /*in*/ "r" (&_argvec[0]) \
1932 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1934 lval = (__typeof__(lval)) _res; \
1937 #endif /* PLAT_ppc32_linux */
1939 /* ------------------------ ppc64-linux ------------------------ */
1941 #if defined(PLAT_ppc64_linux)
1943 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1945 /* These regs are trashed by the hidden call. */
1946 #define __CALLER_SAVED_REGS \
1947 "lr", "ctr", "xer", \
1948 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1949 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1952 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1955 #define CALL_FN_W_v(lval, orig) \
1957 volatile OrigFn _orig = (orig); \
1958 volatile unsigned long _argvec[3+0]; \
1959 volatile unsigned long _res; \
1960 /* _argvec[0] holds current r2 across the call */ \
1961 _argvec[1] = (unsigned long)_orig.r2; \
1962 _argvec[2] = (unsigned long)_orig.nraddr; \
1965 "std 2,-16(11)\n\t" /* save tocptr */ \
1966 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1967 "ld 11, 0(11)\n\t" /* target->r11 */ \
1968 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1971 "ld 2,-16(11)" /* restore tocptr */ \
1972 : /*out*/ "=r" (_res) \
1973 : /*in*/ "r" (&_argvec[2]) \
1974 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1976 lval = (__typeof__(lval)) _res; \
1979 #define CALL_FN_W_W(lval, orig, arg1) \
1981 volatile OrigFn _orig = (orig); \
1982 volatile unsigned long _argvec[3+1]; \
1983 volatile unsigned long _res; \
1984 /* _argvec[0] holds current r2 across the call */ \
1985 _argvec[1] = (unsigned long)_orig.r2; \
1986 _argvec[2] = (unsigned long)_orig.nraddr; \
1987 _argvec[2+1] = (unsigned long)arg1; \
1990 "std 2,-16(11)\n\t" /* save tocptr */ \
1991 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1992 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1993 "ld 11, 0(11)\n\t" /* target->r11 */ \
1994 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1997 "ld 2,-16(11)" /* restore tocptr */ \
1998 : /*out*/ "=r" (_res) \
1999 : /*in*/ "r" (&_argvec[2]) \
2000 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2002 lval = (__typeof__(lval)) _res; \
2005 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2007 volatile OrigFn _orig = (orig); \
2008 volatile unsigned long _argvec[3+2]; \
2009 volatile unsigned long _res; \
2010 /* _argvec[0] holds current r2 across the call */ \
2011 _argvec[1] = (unsigned long)_orig.r2; \
2012 _argvec[2] = (unsigned long)_orig.nraddr; \
2013 _argvec[2+1] = (unsigned long)arg1; \
2014 _argvec[2+2] = (unsigned long)arg2; \
2017 "std 2,-16(11)\n\t" /* save tocptr */ \
2018 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2019 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2020 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2021 "ld 11, 0(11)\n\t" /* target->r11 */ \
2022 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2025 "ld 2,-16(11)" /* restore tocptr */ \
2026 : /*out*/ "=r" (_res) \
2027 : /*in*/ "r" (&_argvec[2]) \
2028 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2030 lval = (__typeof__(lval)) _res; \
2033 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2035 volatile OrigFn _orig = (orig); \
2036 volatile unsigned long _argvec[3+3]; \
2037 volatile unsigned long _res; \
2038 /* _argvec[0] holds current r2 across the call */ \
2039 _argvec[1] = (unsigned long)_orig.r2; \
2040 _argvec[2] = (unsigned long)_orig.nraddr; \
2041 _argvec[2+1] = (unsigned long)arg1; \
2042 _argvec[2+2] = (unsigned long)arg2; \
2043 _argvec[2+3] = (unsigned long)arg3; \
2046 "std 2,-16(11)\n\t" /* save tocptr */ \
2047 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2048 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2049 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2050 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2051 "ld 11, 0(11)\n\t" /* target->r11 */ \
2052 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2055 "ld 2,-16(11)" /* restore tocptr */ \
2056 : /*out*/ "=r" (_res) \
2057 : /*in*/ "r" (&_argvec[2]) \
2058 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2060 lval = (__typeof__(lval)) _res; \
2063 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2065 volatile OrigFn _orig = (orig); \
2066 volatile unsigned long _argvec[3+4]; \
2067 volatile unsigned long _res; \
2068 /* _argvec[0] holds current r2 across the call */ \
2069 _argvec[1] = (unsigned long)_orig.r2; \
2070 _argvec[2] = (unsigned long)_orig.nraddr; \
2071 _argvec[2+1] = (unsigned long)arg1; \
2072 _argvec[2+2] = (unsigned long)arg2; \
2073 _argvec[2+3] = (unsigned long)arg3; \
2074 _argvec[2+4] = (unsigned long)arg4; \
2077 "std 2,-16(11)\n\t" /* save tocptr */ \
2078 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2079 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2080 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2081 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2082 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2083 "ld 11, 0(11)\n\t" /* target->r11 */ \
2084 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2087 "ld 2,-16(11)" /* restore tocptr */ \
2088 : /*out*/ "=r" (_res) \
2089 : /*in*/ "r" (&_argvec[2]) \
2090 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2092 lval = (__typeof__(lval)) _res; \
2095 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2097 volatile OrigFn _orig = (orig); \
2098 volatile unsigned long _argvec[3+5]; \
2099 volatile unsigned long _res; \
2100 /* _argvec[0] holds current r2 across the call */ \
2101 _argvec[1] = (unsigned long)_orig.r2; \
2102 _argvec[2] = (unsigned long)_orig.nraddr; \
2103 _argvec[2+1] = (unsigned long)arg1; \
2104 _argvec[2+2] = (unsigned long)arg2; \
2105 _argvec[2+3] = (unsigned long)arg3; \
2106 _argvec[2+4] = (unsigned long)arg4; \
2107 _argvec[2+5] = (unsigned long)arg5; \
2110 "std 2,-16(11)\n\t" /* save tocptr */ \
2111 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2112 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2113 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2114 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2115 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2116 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2117 "ld 11, 0(11)\n\t" /* target->r11 */ \
2118 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2121 "ld 2,-16(11)" /* restore tocptr */ \
2122 : /*out*/ "=r" (_res) \
2123 : /*in*/ "r" (&_argvec[2]) \
2124 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2126 lval = (__typeof__(lval)) _res; \
2129 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2131 volatile OrigFn _orig = (orig); \
2132 volatile unsigned long _argvec[3+6]; \
2133 volatile unsigned long _res; \
2134 /* _argvec[0] holds current r2 across the call */ \
2135 _argvec[1] = (unsigned long)_orig.r2; \
2136 _argvec[2] = (unsigned long)_orig.nraddr; \
2137 _argvec[2+1] = (unsigned long)arg1; \
2138 _argvec[2+2] = (unsigned long)arg2; \
2139 _argvec[2+3] = (unsigned long)arg3; \
2140 _argvec[2+4] = (unsigned long)arg4; \
2141 _argvec[2+5] = (unsigned long)arg5; \
2142 _argvec[2+6] = (unsigned long)arg6; \
2145 "std 2,-16(11)\n\t" /* save tocptr */ \
2146 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2147 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2148 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2149 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2150 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2151 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2152 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2153 "ld 11, 0(11)\n\t" /* target->r11 */ \
2154 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2157 "ld 2,-16(11)" /* restore tocptr */ \
2158 : /*out*/ "=r" (_res) \
2159 : /*in*/ "r" (&_argvec[2]) \
2160 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2162 lval = (__typeof__(lval)) _res; \
2165 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2168 volatile OrigFn _orig = (orig); \
2169 volatile unsigned long _argvec[3+7]; \
2170 volatile unsigned long _res; \
2171 /* _argvec[0] holds current r2 across the call */ \
2172 _argvec[1] = (unsigned long)_orig.r2; \
2173 _argvec[2] = (unsigned long)_orig.nraddr; \
2174 _argvec[2+1] = (unsigned long)arg1; \
2175 _argvec[2+2] = (unsigned long)arg2; \
2176 _argvec[2+3] = (unsigned long)arg3; \
2177 _argvec[2+4] = (unsigned long)arg4; \
2178 _argvec[2+5] = (unsigned long)arg5; \
2179 _argvec[2+6] = (unsigned long)arg6; \
2180 _argvec[2+7] = (unsigned long)arg7; \
2183 "std 2,-16(11)\n\t" /* save tocptr */ \
2184 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2185 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2186 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2187 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2188 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2189 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2190 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2191 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2192 "ld 11, 0(11)\n\t" /* target->r11 */ \
2193 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2196 "ld 2,-16(11)" /* restore tocptr */ \
2197 : /*out*/ "=r" (_res) \
2198 : /*in*/ "r" (&_argvec[2]) \
2199 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2201 lval = (__typeof__(lval)) _res; \
2204 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2207 volatile OrigFn _orig = (orig); \
2208 volatile unsigned long _argvec[3+8]; \
2209 volatile unsigned long _res; \
2210 /* _argvec[0] holds current r2 across the call */ \
2211 _argvec[1] = (unsigned long)_orig.r2; \
2212 _argvec[2] = (unsigned long)_orig.nraddr; \
2213 _argvec[2+1] = (unsigned long)arg1; \
2214 _argvec[2+2] = (unsigned long)arg2; \
2215 _argvec[2+3] = (unsigned long)arg3; \
2216 _argvec[2+4] = (unsigned long)arg4; \
2217 _argvec[2+5] = (unsigned long)arg5; \
2218 _argvec[2+6] = (unsigned long)arg6; \
2219 _argvec[2+7] = (unsigned long)arg7; \
2220 _argvec[2+8] = (unsigned long)arg8; \
2223 "std 2,-16(11)\n\t" /* save tocptr */ \
2224 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2225 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2226 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2227 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2228 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2229 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2230 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2231 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2232 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2233 "ld 11, 0(11)\n\t" /* target->r11 */ \
2234 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2237 "ld 2,-16(11)" /* restore tocptr */ \
2238 : /*out*/ "=r" (_res) \
2239 : /*in*/ "r" (&_argvec[2]) \
2240 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2242 lval = (__typeof__(lval)) _res; \
2245 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2248 volatile OrigFn _orig = (orig); \
2249 volatile unsigned long _argvec[3+9]; \
2250 volatile unsigned long _res; \
2251 /* _argvec[0] holds current r2 across the call */ \
2252 _argvec[1] = (unsigned long)_orig.r2; \
2253 _argvec[2] = (unsigned long)_orig.nraddr; \
2254 _argvec[2+1] = (unsigned long)arg1; \
2255 _argvec[2+2] = (unsigned long)arg2; \
2256 _argvec[2+3] = (unsigned long)arg3; \
2257 _argvec[2+4] = (unsigned long)arg4; \
2258 _argvec[2+5] = (unsigned long)arg5; \
2259 _argvec[2+6] = (unsigned long)arg6; \
2260 _argvec[2+7] = (unsigned long)arg7; \
2261 _argvec[2+8] = (unsigned long)arg8; \
2262 _argvec[2+9] = (unsigned long)arg9; \
2265 "std 2,-16(11)\n\t" /* save tocptr */ \
2266 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2267 "addi 1,1,-128\n\t" /* expand stack frame */ \
2270 "std 3,112(1)\n\t" \
2272 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2273 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2274 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2275 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2276 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2277 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2278 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2279 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2280 "ld 11, 0(11)\n\t" /* target->r11 */ \
2281 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2284 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2285 "addi 1,1,128" /* restore frame */ \
2286 : /*out*/ "=r" (_res) \
2287 : /*in*/ "r" (&_argvec[2]) \
2288 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2290 lval = (__typeof__(lval)) _res; \
2293 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2294 arg7,arg8,arg9,arg10) \
2296 volatile OrigFn _orig = (orig); \
2297 volatile unsigned long _argvec[3+10]; \
2298 volatile unsigned long _res; \
2299 /* _argvec[0] holds current r2 across the call */ \
2300 _argvec[1] = (unsigned long)_orig.r2; \
2301 _argvec[2] = (unsigned long)_orig.nraddr; \
2302 _argvec[2+1] = (unsigned long)arg1; \
2303 _argvec[2+2] = (unsigned long)arg2; \
2304 _argvec[2+3] = (unsigned long)arg3; \
2305 _argvec[2+4] = (unsigned long)arg4; \
2306 _argvec[2+5] = (unsigned long)arg5; \
2307 _argvec[2+6] = (unsigned long)arg6; \
2308 _argvec[2+7] = (unsigned long)arg7; \
2309 _argvec[2+8] = (unsigned long)arg8; \
2310 _argvec[2+9] = (unsigned long)arg9; \
2311 _argvec[2+10] = (unsigned long)arg10; \
2314 "std 2,-16(11)\n\t" /* save tocptr */ \
2315 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2316 "addi 1,1,-128\n\t" /* expand stack frame */ \
2319 "std 3,120(1)\n\t" \
2322 "std 3,112(1)\n\t" \
2324 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2325 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2326 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2327 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2328 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2329 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2330 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2331 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2332 "ld 11, 0(11)\n\t" /* target->r11 */ \
2333 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2336 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2337 "addi 1,1,128" /* restore frame */ \
2338 : /*out*/ "=r" (_res) \
2339 : /*in*/ "r" (&_argvec[2]) \
2340 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2342 lval = (__typeof__(lval)) _res; \
2345 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2346 arg7,arg8,arg9,arg10,arg11) \
2348 volatile OrigFn _orig = (orig); \
2349 volatile unsigned long _argvec[3+11]; \
2350 volatile unsigned long _res; \
2351 /* _argvec[0] holds current r2 across the call */ \
2352 _argvec[1] = (unsigned long)_orig.r2; \
2353 _argvec[2] = (unsigned long)_orig.nraddr; \
2354 _argvec[2+1] = (unsigned long)arg1; \
2355 _argvec[2+2] = (unsigned long)arg2; \
2356 _argvec[2+3] = (unsigned long)arg3; \
2357 _argvec[2+4] = (unsigned long)arg4; \
2358 _argvec[2+5] = (unsigned long)arg5; \
2359 _argvec[2+6] = (unsigned long)arg6; \
2360 _argvec[2+7] = (unsigned long)arg7; \
2361 _argvec[2+8] = (unsigned long)arg8; \
2362 _argvec[2+9] = (unsigned long)arg9; \
2363 _argvec[2+10] = (unsigned long)arg10; \
2364 _argvec[2+11] = (unsigned long)arg11; \
2367 "std 2,-16(11)\n\t" /* save tocptr */ \
2368 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2369 "addi 1,1,-144\n\t" /* expand stack frame */ \
2372 "std 3,128(1)\n\t" \
2375 "std 3,120(1)\n\t" \
2378 "std 3,112(1)\n\t" \
2380 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2381 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2382 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2383 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2384 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2385 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2386 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2387 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2388 "ld 11, 0(11)\n\t" /* target->r11 */ \
2389 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2392 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2393 "addi 1,1,144" /* restore frame */ \
2394 : /*out*/ "=r" (_res) \
2395 : /*in*/ "r" (&_argvec[2]) \
2396 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2398 lval = (__typeof__(lval)) _res; \
2401 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2402 arg7,arg8,arg9,arg10,arg11,arg12) \
2404 volatile OrigFn _orig = (orig); \
2405 volatile unsigned long _argvec[3+12]; \
2406 volatile unsigned long _res; \
2407 /* _argvec[0] holds current r2 across the call */ \
2408 _argvec[1] = (unsigned long)_orig.r2; \
2409 _argvec[2] = (unsigned long)_orig.nraddr; \
2410 _argvec[2+1] = (unsigned long)arg1; \
2411 _argvec[2+2] = (unsigned long)arg2; \
2412 _argvec[2+3] = (unsigned long)arg3; \
2413 _argvec[2+4] = (unsigned long)arg4; \
2414 _argvec[2+5] = (unsigned long)arg5; \
2415 _argvec[2+6] = (unsigned long)arg6; \
2416 _argvec[2+7] = (unsigned long)arg7; \
2417 _argvec[2+8] = (unsigned long)arg8; \
2418 _argvec[2+9] = (unsigned long)arg9; \
2419 _argvec[2+10] = (unsigned long)arg10; \
2420 _argvec[2+11] = (unsigned long)arg11; \
2421 _argvec[2+12] = (unsigned long)arg12; \
2424 "std 2,-16(11)\n\t" /* save tocptr */ \
2425 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2426 "addi 1,1,-144\n\t" /* expand stack frame */ \
2429 "std 3,136(1)\n\t" \
2432 "std 3,128(1)\n\t" \
2435 "std 3,120(1)\n\t" \
2438 "std 3,112(1)\n\t" \
2440 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2441 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2442 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2443 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2444 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2445 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2446 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2447 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2448 "ld 11, 0(11)\n\t" /* target->r11 */ \
2449 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2452 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2453 "addi 1,1,144" /* restore frame */ \
2454 : /*out*/ "=r" (_res) \
2455 : /*in*/ "r" (&_argvec[2]) \
2456 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2458 lval = (__typeof__(lval)) _res; \
2461 #endif /* PLAT_ppc64_linux */
2463 /* ------------------------ ppc32-aix5 ------------------------- */
2465 #if defined(PLAT_ppc32_aix5)
2467 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2469 /* These regs are trashed by the hidden call. */
2470 #define __CALLER_SAVED_REGS \
2471 "lr", "ctr", "xer", \
2472 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2473 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2476 /* Expand the stack frame, copying enough info that unwinding
2477 still works. Trashes r3. */
2479 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2480 "addi 1,1,-" #_n_fr "\n\t" \
2481 "lwz 3," #_n_fr "(1)\n\t" \
2484 #define VG_CONTRACT_FRAME_BY(_n_fr) \
2485 "addi 1,1," #_n_fr "\n\t"
2487 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2490 #define CALL_FN_W_v(lval, orig) \
2492 volatile OrigFn _orig = (orig); \
2493 volatile unsigned long _argvec[3+0]; \
2494 volatile unsigned long _res; \
2495 /* _argvec[0] holds current r2 across the call */ \
2496 _argvec[1] = (unsigned long)_orig.r2; \
2497 _argvec[2] = (unsigned long)_orig.nraddr; \
2500 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2501 "stw 2,-8(11)\n\t" /* save tocptr */ \
2502 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2503 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2504 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2507 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2508 VG_CONTRACT_FRAME_BY(512) \
2509 : /*out*/ "=r" (_res) \
2510 : /*in*/ "r" (&_argvec[2]) \
2511 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2513 lval = (__typeof__(lval)) _res; \
2516 #define CALL_FN_W_W(lval, orig, arg1) \
2518 volatile OrigFn _orig = (orig); \
2519 volatile unsigned long _argvec[3+1]; \
2520 volatile unsigned long _res; \
2521 /* _argvec[0] holds current r2 across the call */ \
2522 _argvec[1] = (unsigned long)_orig.r2; \
2523 _argvec[2] = (unsigned long)_orig.nraddr; \
2524 _argvec[2+1] = (unsigned long)arg1; \
2527 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2528 "stw 2,-8(11)\n\t" /* save tocptr */ \
2529 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2530 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2531 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2532 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2535 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2536 VG_CONTRACT_FRAME_BY(512) \
2537 : /*out*/ "=r" (_res) \
2538 : /*in*/ "r" (&_argvec[2]) \
2539 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2541 lval = (__typeof__(lval)) _res; \
2544 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2546 volatile OrigFn _orig = (orig); \
2547 volatile unsigned long _argvec[3+2]; \
2548 volatile unsigned long _res; \
2549 /* _argvec[0] holds current r2 across the call */ \
2550 _argvec[1] = (unsigned long)_orig.r2; \
2551 _argvec[2] = (unsigned long)_orig.nraddr; \
2552 _argvec[2+1] = (unsigned long)arg1; \
2553 _argvec[2+2] = (unsigned long)arg2; \
2556 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2557 "stw 2,-8(11)\n\t" /* save tocptr */ \
2558 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2559 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2560 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2561 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2562 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2565 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2566 VG_CONTRACT_FRAME_BY(512) \
2567 : /*out*/ "=r" (_res) \
2568 : /*in*/ "r" (&_argvec[2]) \
2569 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2571 lval = (__typeof__(lval)) _res; \
2574 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2576 volatile OrigFn _orig = (orig); \
2577 volatile unsigned long _argvec[3+3]; \
2578 volatile unsigned long _res; \
2579 /* _argvec[0] holds current r2 across the call */ \
2580 _argvec[1] = (unsigned long)_orig.r2; \
2581 _argvec[2] = (unsigned long)_orig.nraddr; \
2582 _argvec[2+1] = (unsigned long)arg1; \
2583 _argvec[2+2] = (unsigned long)arg2; \
2584 _argvec[2+3] = (unsigned long)arg3; \
2587 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2588 "stw 2,-8(11)\n\t" /* save tocptr */ \
2589 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2590 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2591 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2592 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2593 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2594 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2597 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2598 VG_CONTRACT_FRAME_BY(512) \
2599 : /*out*/ "=r" (_res) \
2600 : /*in*/ "r" (&_argvec[2]) \
2601 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2603 lval = (__typeof__(lval)) _res; \
2606 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2608 volatile OrigFn _orig = (orig); \
2609 volatile unsigned long _argvec[3+4]; \
2610 volatile unsigned long _res; \
2611 /* _argvec[0] holds current r2 across the call */ \
2612 _argvec[1] = (unsigned long)_orig.r2; \
2613 _argvec[2] = (unsigned long)_orig.nraddr; \
2614 _argvec[2+1] = (unsigned long)arg1; \
2615 _argvec[2+2] = (unsigned long)arg2; \
2616 _argvec[2+3] = (unsigned long)arg3; \
2617 _argvec[2+4] = (unsigned long)arg4; \
2620 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2621 "stw 2,-8(11)\n\t" /* save tocptr */ \
2622 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2623 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2624 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2625 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2626 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2627 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2628 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2631 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2632 VG_CONTRACT_FRAME_BY(512) \
2633 : /*out*/ "=r" (_res) \
2634 : /*in*/ "r" (&_argvec[2]) \
2635 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2637 lval = (__typeof__(lval)) _res; \
2640 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2642 volatile OrigFn _orig = (orig); \
2643 volatile unsigned long _argvec[3+5]; \
2644 volatile unsigned long _res; \
2645 /* _argvec[0] holds current r2 across the call */ \
2646 _argvec[1] = (unsigned long)_orig.r2; \
2647 _argvec[2] = (unsigned long)_orig.nraddr; \
2648 _argvec[2+1] = (unsigned long)arg1; \
2649 _argvec[2+2] = (unsigned long)arg2; \
2650 _argvec[2+3] = (unsigned long)arg3; \
2651 _argvec[2+4] = (unsigned long)arg4; \
2652 _argvec[2+5] = (unsigned long)arg5; \
2655 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2656 "stw 2,-8(11)\n\t" /* save tocptr */ \
2657 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2658 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2659 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2660 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2661 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2662 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2663 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2664 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2667 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2668 VG_CONTRACT_FRAME_BY(512) \
2669 : /*out*/ "=r" (_res) \
2670 : /*in*/ "r" (&_argvec[2]) \
2671 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2673 lval = (__typeof__(lval)) _res; \
2676 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2678 volatile OrigFn _orig = (orig); \
2679 volatile unsigned long _argvec[3+6]; \
2680 volatile unsigned long _res; \
2681 /* _argvec[0] holds current r2 across the call */ \
2682 _argvec[1] = (unsigned long)_orig.r2; \
2683 _argvec[2] = (unsigned long)_orig.nraddr; \
2684 _argvec[2+1] = (unsigned long)arg1; \
2685 _argvec[2+2] = (unsigned long)arg2; \
2686 _argvec[2+3] = (unsigned long)arg3; \
2687 _argvec[2+4] = (unsigned long)arg4; \
2688 _argvec[2+5] = (unsigned long)arg5; \
2689 _argvec[2+6] = (unsigned long)arg6; \
2692 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2693 "stw 2,-8(11)\n\t" /* save tocptr */ \
2694 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2695 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2696 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2697 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2698 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2699 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2700 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2701 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2702 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2705 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2706 VG_CONTRACT_FRAME_BY(512) \
2707 : /*out*/ "=r" (_res) \
2708 : /*in*/ "r" (&_argvec[2]) \
2709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2711 lval = (__typeof__(lval)) _res; \
2714 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2717 volatile OrigFn _orig = (orig); \
2718 volatile unsigned long _argvec[3+7]; \
2719 volatile unsigned long _res; \
2720 /* _argvec[0] holds current r2 across the call */ \
2721 _argvec[1] = (unsigned long)_orig.r2; \
2722 _argvec[2] = (unsigned long)_orig.nraddr; \
2723 _argvec[2+1] = (unsigned long)arg1; \
2724 _argvec[2+2] = (unsigned long)arg2; \
2725 _argvec[2+3] = (unsigned long)arg3; \
2726 _argvec[2+4] = (unsigned long)arg4; \
2727 _argvec[2+5] = (unsigned long)arg5; \
2728 _argvec[2+6] = (unsigned long)arg6; \
2729 _argvec[2+7] = (unsigned long)arg7; \
2732 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2733 "stw 2,-8(11)\n\t" /* save tocptr */ \
2734 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2735 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2736 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2737 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2738 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2739 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2740 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2741 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2742 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2743 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2746 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2747 VG_CONTRACT_FRAME_BY(512) \
2748 : /*out*/ "=r" (_res) \
2749 : /*in*/ "r" (&_argvec[2]) \
2750 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2752 lval = (__typeof__(lval)) _res; \
2755 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2758 volatile OrigFn _orig = (orig); \
2759 volatile unsigned long _argvec[3+8]; \
2760 volatile unsigned long _res; \
2761 /* _argvec[0] holds current r2 across the call */ \
2762 _argvec[1] = (unsigned long)_orig.r2; \
2763 _argvec[2] = (unsigned long)_orig.nraddr; \
2764 _argvec[2+1] = (unsigned long)arg1; \
2765 _argvec[2+2] = (unsigned long)arg2; \
2766 _argvec[2+3] = (unsigned long)arg3; \
2767 _argvec[2+4] = (unsigned long)arg4; \
2768 _argvec[2+5] = (unsigned long)arg5; \
2769 _argvec[2+6] = (unsigned long)arg6; \
2770 _argvec[2+7] = (unsigned long)arg7; \
2771 _argvec[2+8] = (unsigned long)arg8; \
2774 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2775 "stw 2,-8(11)\n\t" /* save tocptr */ \
2776 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2777 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2778 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2779 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2780 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2781 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2782 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2783 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2784 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2785 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2786 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2789 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2790 VG_CONTRACT_FRAME_BY(512) \
2791 : /*out*/ "=r" (_res) \
2792 : /*in*/ "r" (&_argvec[2]) \
2793 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2795 lval = (__typeof__(lval)) _res; \
2798 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2801 volatile OrigFn _orig = (orig); \
2802 volatile unsigned long _argvec[3+9]; \
2803 volatile unsigned long _res; \
2804 /* _argvec[0] holds current r2 across the call */ \
2805 _argvec[1] = (unsigned long)_orig.r2; \
2806 _argvec[2] = (unsigned long)_orig.nraddr; \
2807 _argvec[2+1] = (unsigned long)arg1; \
2808 _argvec[2+2] = (unsigned long)arg2; \
2809 _argvec[2+3] = (unsigned long)arg3; \
2810 _argvec[2+4] = (unsigned long)arg4; \
2811 _argvec[2+5] = (unsigned long)arg5; \
2812 _argvec[2+6] = (unsigned long)arg6; \
2813 _argvec[2+7] = (unsigned long)arg7; \
2814 _argvec[2+8] = (unsigned long)arg8; \
2815 _argvec[2+9] = (unsigned long)arg9; \
2818 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2819 "stw 2,-8(11)\n\t" /* save tocptr */ \
2820 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2821 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2823 "lwz 3,36(11)\n\t" \
2826 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2827 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2828 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2829 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2830 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2831 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2832 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2833 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2834 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2835 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2838 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2839 VG_CONTRACT_FRAME_BY(64) \
2840 VG_CONTRACT_FRAME_BY(512) \
2841 : /*out*/ "=r" (_res) \
2842 : /*in*/ "r" (&_argvec[2]) \
2843 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2845 lval = (__typeof__(lval)) _res; \
2848 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2849 arg7,arg8,arg9,arg10) \
2851 volatile OrigFn _orig = (orig); \
2852 volatile unsigned long _argvec[3+10]; \
2853 volatile unsigned long _res; \
2854 /* _argvec[0] holds current r2 across the call */ \
2855 _argvec[1] = (unsigned long)_orig.r2; \
2856 _argvec[2] = (unsigned long)_orig.nraddr; \
2857 _argvec[2+1] = (unsigned long)arg1; \
2858 _argvec[2+2] = (unsigned long)arg2; \
2859 _argvec[2+3] = (unsigned long)arg3; \
2860 _argvec[2+4] = (unsigned long)arg4; \
2861 _argvec[2+5] = (unsigned long)arg5; \
2862 _argvec[2+6] = (unsigned long)arg6; \
2863 _argvec[2+7] = (unsigned long)arg7; \
2864 _argvec[2+8] = (unsigned long)arg8; \
2865 _argvec[2+9] = (unsigned long)arg9; \
2866 _argvec[2+10] = (unsigned long)arg10; \
2869 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2870 "stw 2,-8(11)\n\t" /* save tocptr */ \
2871 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2872 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2874 "lwz 3,40(11)\n\t" \
2877 "lwz 3,36(11)\n\t" \
2880 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2881 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2882 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2883 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2884 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2885 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2886 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2887 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2888 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2889 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2892 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2893 VG_CONTRACT_FRAME_BY(64) \
2894 VG_CONTRACT_FRAME_BY(512) \
2895 : /*out*/ "=r" (_res) \
2896 : /*in*/ "r" (&_argvec[2]) \
2897 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2899 lval = (__typeof__(lval)) _res; \
2902 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2903 arg7,arg8,arg9,arg10,arg11) \
2905 volatile OrigFn _orig = (orig); \
2906 volatile unsigned long _argvec[3+11]; \
2907 volatile unsigned long _res; \
2908 /* _argvec[0] holds current r2 across the call */ \
2909 _argvec[1] = (unsigned long)_orig.r2; \
2910 _argvec[2] = (unsigned long)_orig.nraddr; \
2911 _argvec[2+1] = (unsigned long)arg1; \
2912 _argvec[2+2] = (unsigned long)arg2; \
2913 _argvec[2+3] = (unsigned long)arg3; \
2914 _argvec[2+4] = (unsigned long)arg4; \
2915 _argvec[2+5] = (unsigned long)arg5; \
2916 _argvec[2+6] = (unsigned long)arg6; \
2917 _argvec[2+7] = (unsigned long)arg7; \
2918 _argvec[2+8] = (unsigned long)arg8; \
2919 _argvec[2+9] = (unsigned long)arg9; \
2920 _argvec[2+10] = (unsigned long)arg10; \
2921 _argvec[2+11] = (unsigned long)arg11; \
2924 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2925 "stw 2,-8(11)\n\t" /* save tocptr */ \
2926 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2927 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2929 "lwz 3,44(11)\n\t" \
2932 "lwz 3,40(11)\n\t" \
2935 "lwz 3,36(11)\n\t" \
2938 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2939 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2940 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2941 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2942 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2943 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2944 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2945 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2946 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2947 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2950 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2951 VG_CONTRACT_FRAME_BY(72) \
2952 VG_CONTRACT_FRAME_BY(512) \
2953 : /*out*/ "=r" (_res) \
2954 : /*in*/ "r" (&_argvec[2]) \
2955 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2957 lval = (__typeof__(lval)) _res; \
2960 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2961 arg7,arg8,arg9,arg10,arg11,arg12) \
2963 volatile OrigFn _orig = (orig); \
2964 volatile unsigned long _argvec[3+12]; \
2965 volatile unsigned long _res; \
2966 /* _argvec[0] holds current r2 across the call */ \
2967 _argvec[1] = (unsigned long)_orig.r2; \
2968 _argvec[2] = (unsigned long)_orig.nraddr; \
2969 _argvec[2+1] = (unsigned long)arg1; \
2970 _argvec[2+2] = (unsigned long)arg2; \
2971 _argvec[2+3] = (unsigned long)arg3; \
2972 _argvec[2+4] = (unsigned long)arg4; \
2973 _argvec[2+5] = (unsigned long)arg5; \
2974 _argvec[2+6] = (unsigned long)arg6; \
2975 _argvec[2+7] = (unsigned long)arg7; \
2976 _argvec[2+8] = (unsigned long)arg8; \
2977 _argvec[2+9] = (unsigned long)arg9; \
2978 _argvec[2+10] = (unsigned long)arg10; \
2979 _argvec[2+11] = (unsigned long)arg11; \
2980 _argvec[2+12] = (unsigned long)arg12; \
2983 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2984 "stw 2,-8(11)\n\t" /* save tocptr */ \
2985 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2986 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2988 "lwz 3,48(11)\n\t" \
2991 "lwz 3,44(11)\n\t" \
2994 "lwz 3,40(11)\n\t" \
2997 "lwz 3,36(11)\n\t" \
3000 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3001 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3002 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3003 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3004 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3005 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3006 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3007 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3008 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3009 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3012 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3013 VG_CONTRACT_FRAME_BY(72) \
3014 VG_CONTRACT_FRAME_BY(512) \
3015 : /*out*/ "=r" (_res) \
3016 : /*in*/ "r" (&_argvec[2]) \
3017 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3019 lval = (__typeof__(lval)) _res; \
3022 #endif /* PLAT_ppc32_aix5 */
3024 /* ------------------------ ppc64-aix5 ------------------------- */
3026 #if defined(PLAT_ppc64_aix5)
3028 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3030 /* These regs are trashed by the hidden call. */
3031 #define __CALLER_SAVED_REGS \
3032 "lr", "ctr", "xer", \
3033 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3034 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3037 /* Expand the stack frame, copying enough info that unwinding
3038 still works. Trashes r3. */
3040 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3041 "addi 1,1,-" #_n_fr "\n\t" \
3042 "ld 3," #_n_fr "(1)\n\t" \
3045 #define VG_CONTRACT_FRAME_BY(_n_fr) \
3046 "addi 1,1," #_n_fr "\n\t"
3048 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3051 #define CALL_FN_W_v(lval, orig) \
3053 volatile OrigFn _orig = (orig); \
3054 volatile unsigned long _argvec[3+0]; \
3055 volatile unsigned long _res; \
3056 /* _argvec[0] holds current r2 across the call */ \
3057 _argvec[1] = (unsigned long)_orig.r2; \
3058 _argvec[2] = (unsigned long)_orig.nraddr; \
3061 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3062 "std 2,-16(11)\n\t" /* save tocptr */ \
3063 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3064 "ld 11, 0(11)\n\t" /* target->r11 */ \
3065 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3068 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3069 VG_CONTRACT_FRAME_BY(512) \
3070 : /*out*/ "=r" (_res) \
3071 : /*in*/ "r" (&_argvec[2]) \
3072 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3074 lval = (__typeof__(lval)) _res; \
3077 #define CALL_FN_W_W(lval, orig, arg1) \
3079 volatile OrigFn _orig = (orig); \
3080 volatile unsigned long _argvec[3+1]; \
3081 volatile unsigned long _res; \
3082 /* _argvec[0] holds current r2 across the call */ \
3083 _argvec[1] = (unsigned long)_orig.r2; \
3084 _argvec[2] = (unsigned long)_orig.nraddr; \
3085 _argvec[2+1] = (unsigned long)arg1; \
3088 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3089 "std 2,-16(11)\n\t" /* save tocptr */ \
3090 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3091 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3092 "ld 11, 0(11)\n\t" /* target->r11 */ \
3093 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3096 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3097 VG_CONTRACT_FRAME_BY(512) \
3098 : /*out*/ "=r" (_res) \
3099 : /*in*/ "r" (&_argvec[2]) \
3100 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3102 lval = (__typeof__(lval)) _res; \
3105 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3107 volatile OrigFn _orig = (orig); \
3108 volatile unsigned long _argvec[3+2]; \
3109 volatile unsigned long _res; \
3110 /* _argvec[0] holds current r2 across the call */ \
3111 _argvec[1] = (unsigned long)_orig.r2; \
3112 _argvec[2] = (unsigned long)_orig.nraddr; \
3113 _argvec[2+1] = (unsigned long)arg1; \
3114 _argvec[2+2] = (unsigned long)arg2; \
3117 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3118 "std 2,-16(11)\n\t" /* save tocptr */ \
3119 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3120 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3121 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3122 "ld 11, 0(11)\n\t" /* target->r11 */ \
3123 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3126 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3127 VG_CONTRACT_FRAME_BY(512) \
3128 : /*out*/ "=r" (_res) \
3129 : /*in*/ "r" (&_argvec[2]) \
3130 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3132 lval = (__typeof__(lval)) _res; \
3135 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3137 volatile OrigFn _orig = (orig); \
3138 volatile unsigned long _argvec[3+3]; \
3139 volatile unsigned long _res; \
3140 /* _argvec[0] holds current r2 across the call */ \
3141 _argvec[1] = (unsigned long)_orig.r2; \
3142 _argvec[2] = (unsigned long)_orig.nraddr; \
3143 _argvec[2+1] = (unsigned long)arg1; \
3144 _argvec[2+2] = (unsigned long)arg2; \
3145 _argvec[2+3] = (unsigned long)arg3; \
3148 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3149 "std 2,-16(11)\n\t" /* save tocptr */ \
3150 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3151 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3152 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3153 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3154 "ld 11, 0(11)\n\t" /* target->r11 */ \
3155 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3158 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3159 VG_CONTRACT_FRAME_BY(512) \
3160 : /*out*/ "=r" (_res) \
3161 : /*in*/ "r" (&_argvec[2]) \
3162 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3164 lval = (__typeof__(lval)) _res; \
3167 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3169 volatile OrigFn _orig = (orig); \
3170 volatile unsigned long _argvec[3+4]; \
3171 volatile unsigned long _res; \
3172 /* _argvec[0] holds current r2 across the call */ \
3173 _argvec[1] = (unsigned long)_orig.r2; \
3174 _argvec[2] = (unsigned long)_orig.nraddr; \
3175 _argvec[2+1] = (unsigned long)arg1; \
3176 _argvec[2+2] = (unsigned long)arg2; \
3177 _argvec[2+3] = (unsigned long)arg3; \
3178 _argvec[2+4] = (unsigned long)arg4; \
3181 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3182 "std 2,-16(11)\n\t" /* save tocptr */ \
3183 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3184 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3185 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3186 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3187 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3188 "ld 11, 0(11)\n\t" /* target->r11 */ \
3189 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3192 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3193 VG_CONTRACT_FRAME_BY(512) \
3194 : /*out*/ "=r" (_res) \
3195 : /*in*/ "r" (&_argvec[2]) \
3196 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3198 lval = (__typeof__(lval)) _res; \
3201 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3203 volatile OrigFn _orig = (orig); \
3204 volatile unsigned long _argvec[3+5]; \
3205 volatile unsigned long _res; \
3206 /* _argvec[0] holds current r2 across the call */ \
3207 _argvec[1] = (unsigned long)_orig.r2; \
3208 _argvec[2] = (unsigned long)_orig.nraddr; \
3209 _argvec[2+1] = (unsigned long)arg1; \
3210 _argvec[2+2] = (unsigned long)arg2; \
3211 _argvec[2+3] = (unsigned long)arg3; \
3212 _argvec[2+4] = (unsigned long)arg4; \
3213 _argvec[2+5] = (unsigned long)arg5; \
3216 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3217 "std 2,-16(11)\n\t" /* save tocptr */ \
3218 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3219 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3220 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3221 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3222 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3223 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3224 "ld 11, 0(11)\n\t" /* target->r11 */ \
3225 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3228 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3229 VG_CONTRACT_FRAME_BY(512) \
3230 : /*out*/ "=r" (_res) \
3231 : /*in*/ "r" (&_argvec[2]) \
3232 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3234 lval = (__typeof__(lval)) _res; \
3237 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3239 volatile OrigFn _orig = (orig); \
3240 volatile unsigned long _argvec[3+6]; \
3241 volatile unsigned long _res; \
3242 /* _argvec[0] holds current r2 across the call */ \
3243 _argvec[1] = (unsigned long)_orig.r2; \
3244 _argvec[2] = (unsigned long)_orig.nraddr; \
3245 _argvec[2+1] = (unsigned long)arg1; \
3246 _argvec[2+2] = (unsigned long)arg2; \
3247 _argvec[2+3] = (unsigned long)arg3; \
3248 _argvec[2+4] = (unsigned long)arg4; \
3249 _argvec[2+5] = (unsigned long)arg5; \
3250 _argvec[2+6] = (unsigned long)arg6; \
3253 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3254 "std 2,-16(11)\n\t" /* save tocptr */ \
3255 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3256 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3257 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3258 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3259 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3260 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3261 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3262 "ld 11, 0(11)\n\t" /* target->r11 */ \
3263 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3266 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3267 VG_CONTRACT_FRAME_BY(512) \
3268 : /*out*/ "=r" (_res) \
3269 : /*in*/ "r" (&_argvec[2]) \
3270 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3272 lval = (__typeof__(lval)) _res; \
3275 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3278 volatile OrigFn _orig = (orig); \
3279 volatile unsigned long _argvec[3+7]; \
3280 volatile unsigned long _res; \
3281 /* _argvec[0] holds current r2 across the call */ \
3282 _argvec[1] = (unsigned long)_orig.r2; \
3283 _argvec[2] = (unsigned long)_orig.nraddr; \
3284 _argvec[2+1] = (unsigned long)arg1; \
3285 _argvec[2+2] = (unsigned long)arg2; \
3286 _argvec[2+3] = (unsigned long)arg3; \
3287 _argvec[2+4] = (unsigned long)arg4; \
3288 _argvec[2+5] = (unsigned long)arg5; \
3289 _argvec[2+6] = (unsigned long)arg6; \
3290 _argvec[2+7] = (unsigned long)arg7; \
3293 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3294 "std 2,-16(11)\n\t" /* save tocptr */ \
3295 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3296 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3297 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3298 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3299 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3300 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3301 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3302 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3303 "ld 11, 0(11)\n\t" /* target->r11 */ \
3304 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3307 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3308 VG_CONTRACT_FRAME_BY(512) \
3309 : /*out*/ "=r" (_res) \
3310 : /*in*/ "r" (&_argvec[2]) \
3311 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3313 lval = (__typeof__(lval)) _res; \
3316 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3319 volatile OrigFn _orig = (orig); \
3320 volatile unsigned long _argvec[3+8]; \
3321 volatile unsigned long _res; \
3322 /* _argvec[0] holds current r2 across the call */ \
3323 _argvec[1] = (unsigned long)_orig.r2; \
3324 _argvec[2] = (unsigned long)_orig.nraddr; \
3325 _argvec[2+1] = (unsigned long)arg1; \
3326 _argvec[2+2] = (unsigned long)arg2; \
3327 _argvec[2+3] = (unsigned long)arg3; \
3328 _argvec[2+4] = (unsigned long)arg4; \
3329 _argvec[2+5] = (unsigned long)arg5; \
3330 _argvec[2+6] = (unsigned long)arg6; \
3331 _argvec[2+7] = (unsigned long)arg7; \
3332 _argvec[2+8] = (unsigned long)arg8; \
3335 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3336 "std 2,-16(11)\n\t" /* save tocptr */ \
3337 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3338 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3339 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3340 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3341 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3342 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3343 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3344 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3345 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3346 "ld 11, 0(11)\n\t" /* target->r11 */ \
3347 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3350 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3351 VG_CONTRACT_FRAME_BY(512) \
3352 : /*out*/ "=r" (_res) \
3353 : /*in*/ "r" (&_argvec[2]) \
3354 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3356 lval = (__typeof__(lval)) _res; \
3359 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3362 volatile OrigFn _orig = (orig); \
3363 volatile unsigned long _argvec[3+9]; \
3364 volatile unsigned long _res; \
3365 /* _argvec[0] holds current r2 across the call */ \
3366 _argvec[1] = (unsigned long)_orig.r2; \
3367 _argvec[2] = (unsigned long)_orig.nraddr; \
3368 _argvec[2+1] = (unsigned long)arg1; \
3369 _argvec[2+2] = (unsigned long)arg2; \
3370 _argvec[2+3] = (unsigned long)arg3; \
3371 _argvec[2+4] = (unsigned long)arg4; \
3372 _argvec[2+5] = (unsigned long)arg5; \
3373 _argvec[2+6] = (unsigned long)arg6; \
3374 _argvec[2+7] = (unsigned long)arg7; \
3375 _argvec[2+8] = (unsigned long)arg8; \
3376 _argvec[2+9] = (unsigned long)arg9; \
3379 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3380 "std 2,-16(11)\n\t" /* save tocptr */ \
3381 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3382 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3385 "std 3,112(1)\n\t" \
3387 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3388 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3389 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3390 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3391 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3392 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3393 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3394 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3395 "ld 11, 0(11)\n\t" /* target->r11 */ \
3396 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3399 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3400 VG_CONTRACT_FRAME_BY(128) \
3401 VG_CONTRACT_FRAME_BY(512) \
3402 : /*out*/ "=r" (_res) \
3403 : /*in*/ "r" (&_argvec[2]) \
3404 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3406 lval = (__typeof__(lval)) _res; \
3409 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3410 arg7,arg8,arg9,arg10) \
3412 volatile OrigFn _orig = (orig); \
3413 volatile unsigned long _argvec[3+10]; \
3414 volatile unsigned long _res; \
3415 /* _argvec[0] holds current r2 across the call */ \
3416 _argvec[1] = (unsigned long)_orig.r2; \
3417 _argvec[2] = (unsigned long)_orig.nraddr; \
3418 _argvec[2+1] = (unsigned long)arg1; \
3419 _argvec[2+2] = (unsigned long)arg2; \
3420 _argvec[2+3] = (unsigned long)arg3; \
3421 _argvec[2+4] = (unsigned long)arg4; \
3422 _argvec[2+5] = (unsigned long)arg5; \
3423 _argvec[2+6] = (unsigned long)arg6; \
3424 _argvec[2+7] = (unsigned long)arg7; \
3425 _argvec[2+8] = (unsigned long)arg8; \
3426 _argvec[2+9] = (unsigned long)arg9; \
3427 _argvec[2+10] = (unsigned long)arg10; \
3430 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3431 "std 2,-16(11)\n\t" /* save tocptr */ \
3432 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3433 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3436 "std 3,120(1)\n\t" \
3439 "std 3,112(1)\n\t" \
3441 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3442 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3443 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3444 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3445 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3446 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3447 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3448 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3449 "ld 11, 0(11)\n\t" /* target->r11 */ \
3450 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3453 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3454 VG_CONTRACT_FRAME_BY(128) \
3455 VG_CONTRACT_FRAME_BY(512) \
3456 : /*out*/ "=r" (_res) \
3457 : /*in*/ "r" (&_argvec[2]) \
3458 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3460 lval = (__typeof__(lval)) _res; \
3463 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3464 arg7,arg8,arg9,arg10,arg11) \
3466 volatile OrigFn _orig = (orig); \
3467 volatile unsigned long _argvec[3+11]; \
3468 volatile unsigned long _res; \
3469 /* _argvec[0] holds current r2 across the call */ \
3470 _argvec[1] = (unsigned long)_orig.r2; \
3471 _argvec[2] = (unsigned long)_orig.nraddr; \
3472 _argvec[2+1] = (unsigned long)arg1; \
3473 _argvec[2+2] = (unsigned long)arg2; \
3474 _argvec[2+3] = (unsigned long)arg3; \
3475 _argvec[2+4] = (unsigned long)arg4; \
3476 _argvec[2+5] = (unsigned long)arg5; \
3477 _argvec[2+6] = (unsigned long)arg6; \
3478 _argvec[2+7] = (unsigned long)arg7; \
3479 _argvec[2+8] = (unsigned long)arg8; \
3480 _argvec[2+9] = (unsigned long)arg9; \
3481 _argvec[2+10] = (unsigned long)arg10; \
3482 _argvec[2+11] = (unsigned long)arg11; \
3485 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3486 "std 2,-16(11)\n\t" /* save tocptr */ \
3487 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3488 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3491 "std 3,128(1)\n\t" \
3494 "std 3,120(1)\n\t" \
3497 "std 3,112(1)\n\t" \
3499 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3500 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3501 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3502 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3503 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3504 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3505 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3506 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3507 "ld 11, 0(11)\n\t" /* target->r11 */ \
3508 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3511 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3512 VG_CONTRACT_FRAME_BY(144) \
3513 VG_CONTRACT_FRAME_BY(512) \
3514 : /*out*/ "=r" (_res) \
3515 : /*in*/ "r" (&_argvec[2]) \
3516 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3518 lval = (__typeof__(lval)) _res; \
3521 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3522 arg7,arg8,arg9,arg10,arg11,arg12) \
3524 volatile OrigFn _orig = (orig); \
3525 volatile unsigned long _argvec[3+12]; \
3526 volatile unsigned long _res; \
3527 /* _argvec[0] holds current r2 across the call */ \
3528 _argvec[1] = (unsigned long)_orig.r2; \
3529 _argvec[2] = (unsigned long)_orig.nraddr; \
3530 _argvec[2+1] = (unsigned long)arg1; \
3531 _argvec[2+2] = (unsigned long)arg2; \
3532 _argvec[2+3] = (unsigned long)arg3; \
3533 _argvec[2+4] = (unsigned long)arg4; \
3534 _argvec[2+5] = (unsigned long)arg5; \
3535 _argvec[2+6] = (unsigned long)arg6; \
3536 _argvec[2+7] = (unsigned long)arg7; \
3537 _argvec[2+8] = (unsigned long)arg8; \
3538 _argvec[2+9] = (unsigned long)arg9; \
3539 _argvec[2+10] = (unsigned long)arg10; \
3540 _argvec[2+11] = (unsigned long)arg11; \
3541 _argvec[2+12] = (unsigned long)arg12; \
3544 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3545 "std 2,-16(11)\n\t" /* save tocptr */ \
3546 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3547 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3550 "std 3,136(1)\n\t" \
3553 "std 3,128(1)\n\t" \
3556 "std 3,120(1)\n\t" \
3559 "std 3,112(1)\n\t" \
3561 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3562 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3563 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3564 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3565 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3566 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3567 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3568 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3569 "ld 11, 0(11)\n\t" /* target->r11 */ \
3570 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3573 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3574 VG_CONTRACT_FRAME_BY(144) \
3575 VG_CONTRACT_FRAME_BY(512) \
3576 : /*out*/ "=r" (_res) \
3577 : /*in*/ "r" (&_argvec[2]) \
3578 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3580 lval = (__typeof__(lval)) _res; \
3583 #endif /* PLAT_ppc64_aix5 */
3586 /* ------------------------------------------------------------------ */
3587 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
3589 /* ------------------------------------------------------------------ */
3591 /* Some request codes. There are many more of these, but most are not
3592 exposed to end-user view. These are the public ones, all of the
3593 form 0x1000 + small_number.
3595 Core ones are in the range 0x00000000--0x0000ffff. The non-public
3596 ones start at 0x2000.
3599 /* These macros are used by tools -- they must be public, but don't
3600 embed them into other programs. */
3601 #define VG_USERREQ_TOOL_BASE(a,b) \
3602 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
3603 #define VG_IS_TOOL_USERREQ(a, b, v) \
3604 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
3606 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3607 This enum comprises an ABI exported by Valgrind to programs
3608 which use client requests. DO NOT CHANGE THE ORDER OF THESE
3609 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
3611 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
3612 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
3614 /* These allow any function to be called from the simulated
3615 CPU but run on the real CPU. Nb: the first arg passed to
3616 the function is always the ThreadId of the running
3617 thread! So CLIENT_CALL0 actually requires a 1 arg
3619 VG_USERREQ__CLIENT_CALL0 = 0x1101,
3620 VG_USERREQ__CLIENT_CALL1 = 0x1102,
3621 VG_USERREQ__CLIENT_CALL2 = 0x1103,
3622 VG_USERREQ__CLIENT_CALL3 = 0x1104,
3624 /* Can be useful in regression testing suites -- eg. can
3625 send Valgrind's output to /dev/null and still count
3627 VG_USERREQ__COUNT_ERRORS = 0x1201,
3629 /* These are useful and can be interpreted by any tool that
3630 tracks malloc() et al, by using vg_replace_malloc.c. */
3631 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
3632 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
3633 /* Memory pool support. */
3634 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
3635 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
3636 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
3637 VG_USERREQ__MEMPOOL_FREE = 0x1306,
3638 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
3639 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
3640 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
3641 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
3643 /* Allow printfs to valgrind log. */
3644 VG_USERREQ__PRINTF = 0x1401,
3645 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
3647 /* Stack support. */
3648 VG_USERREQ__STACK_REGISTER = 0x1501,
3649 VG_USERREQ__STACK_DEREGISTER = 0x1502,
3650 VG_USERREQ__STACK_CHANGE = 0x1503,
3653 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
3656 #if !defined(__GNUC__)
3657 # define __extension__ /* */
3660 /* Returns the number of Valgrinds this code is running under. That
3661 is, 0 if running natively, 1 if running under Valgrind, 2 if
3662 running under Valgrind which is running under another Valgrind,
3664 #if defined(HOST_WIN32) || defined(TARGET_WIN32)
3665 #define RUNNING_ON_VALGRIND 0
3667 #define RUNNING_ON_VALGRIND __extension__ \
3668 ({unsigned int _qzz_res; \
3669 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
3670 VG_USERREQ__RUNNING_ON_VALGRIND, \
3676 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3677 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
3678 since it provides a way to make sure valgrind will retranslate the
3679 invalidated area. Returns no value. */
3680 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
3681 {unsigned int _qzz_res; \
3682 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3683 VG_USERREQ__DISCARD_TRANSLATIONS, \
3684 _qzz_addr, _qzz_len, 0, 0, 0); \
3688 /* These requests are for getting Valgrind itself to print something.
3689 Possibly with a backtrace. This is a really ugly hack. The return value
3690 is the number of characters printed, excluding the "**<pid>** " part at the
3691 start and the backtrace (if present). */
3693 #if defined(NVALGRIND)
3695 # define VALGRIND_PRINTF(...)
3696 # define VALGRIND_PRINTF_BACKTRACE(...)
3698 #else /* NVALGRIND */
3700 /* Modern GCC will optimize the static routine out if unused,
3701 and unused attribute will shut down warnings about it. */
3702 static int VALGRIND_PRINTF(const char *format, ...)
3703 __attribute__((format(__printf__, 1, 2), __unused__));
3705 VALGRIND_PRINTF(const char *format, ...)
3707 unsigned long _qzz_res;
3709 va_start(vargs, format);
3710 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
3711 (unsigned long)format, (unsigned long)vargs,
3714 return (int)_qzz_res;
3717 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3718 __attribute__((format(__printf__, 1, 2), __unused__));
3720 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3722 unsigned long _qzz_res;
3724 va_start(vargs, format);
3725 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
3726 (unsigned long)format, (unsigned long)vargs,
3729 return (int)_qzz_res;
3732 #endif /* NVALGRIND */
3735 /* These requests allow control to move from the simulated CPU to the
3736 real CPU, calling an arbitary function.
3738 Note that the current ThreadId is inserted as the first argument.
3741 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3743 requires f to have this signature:
3745 Word f(Word tid, Word arg1, Word arg2)
3747 where "Word" is a word-sized type.
3749 Note that these client requests are not entirely reliable. For example,
3750 if you call a function with them that subsequently calls printf(),
3751 there's a high chance Valgrind will crash. Generally, your prospects of
3752 these working are made higher if the called function does not refer to
3753 any global variables, and does not refer to any libc or other functions
3754 (printf et al). Any kind of entanglement with libc or dynamic linking is
3755 likely to have a bad outcome, for tricky reasons which we've grappled
3756 with a lot in the past.
3758 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
3760 ({unsigned long _qyy_res; \
3761 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3762 VG_USERREQ__CLIENT_CALL0, \
3768 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
3770 ({unsigned long _qyy_res; \
3771 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3772 VG_USERREQ__CLIENT_CALL1, \
3774 _qyy_arg1, 0, 0, 0); \
3778 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
3780 ({unsigned long _qyy_res; \
3781 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3782 VG_USERREQ__CLIENT_CALL2, \
3784 _qyy_arg1, _qyy_arg2, 0, 0); \
3788 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
3790 ({unsigned long _qyy_res; \
3791 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3792 VG_USERREQ__CLIENT_CALL3, \
3794 _qyy_arg1, _qyy_arg2, \
3800 /* Counts the number of errors that have been recorded by a tool. Nb:
3801 the tool must record the errors with VG_(maybe_record_error)() or
3802 VG_(unique_error)() for them to be counted. */
3803 #define VALGRIND_COUNT_ERRORS \
3805 ({unsigned int _qyy_res; \
3806 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3807 VG_USERREQ__COUNT_ERRORS, \
3812 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
3813 when heap blocks are allocated in order to give accurate results. This
3814 happens automatically for the standard allocator functions such as
3815 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
3818 But if your program uses a custom allocator, this doesn't automatically
3819 happen, and Valgrind will not do as well. For example, if you allocate
3820 superblocks with mmap() and then allocates chunks of the superblocks, all
3821 Valgrind's observations will be at the mmap() level and it won't know that
3822 the chunks should be considered separate entities. In Memcheck's case,
3823 that means you probably won't get heap block overrun detection (because
3824 there won't be redzones marked as unaddressable) and you definitely won't
3825 get any leak detection.
3827 The following client requests allow a custom allocator to be annotated so
3828 that it can be handled accurately by Valgrind.
3830 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
3831 by a malloc()-like function. For Memcheck (an illustrative case), this
3834 - It records that the block has been allocated. This means any addresses
3835 within the block mentioned in error messages will be
3836 identified as belonging to the block. It also means that if the block
3837 isn't freed it will be detected by the leak checker.
3839 - It marks the block as being addressable and undefined (if 'is_zeroed' is
3840 not set), or addressable and defined (if 'is_zeroed' is set). This
3841 controls how accesses to the block by the program are handled.
3843 'addr' is the start of the usable block (ie. after any
3844 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
3845 can apply redzones -- these are blocks of padding at the start and end of
3846 each block. Adding redzones is recommended as it makes it much more likely
3847 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
3848 zeroed (or filled with another predictable value), as is the case for
3851 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
3852 heap block -- that will be used by the client program -- is allocated.
3853 It's best to put it at the outermost level of the allocator if possible;
3854 for example, if you have a function my_alloc() which calls
3855 internal_alloc(), and the client request is put inside internal_alloc(),
3856 stack traces relating to the heap block will contain entries for both
3857 my_alloc() and internal_alloc(), which is probably not what you want.
3859 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
3860 custom blocks from within a heap block, B, that has been allocated with
3861 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
3862 -- the custom blocks will take precedence.
3864 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
3865 Memcheck, it does two things:
3867 - It records that the block has been deallocated. This assumes that the
3868 block was annotated as having been allocated via
3869 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3871 - It marks the block as being unaddressable.
3873 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
3874 heap block is deallocated.
3876 In many cases, these two client requests will not be enough to get your
3877 allocator working well with Memcheck. More specifically, if your allocator
3878 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
3879 will be necessary to mark the memory as addressable just before the zeroing
3880 occurs, otherwise you'll get a lot of invalid write errors. For example,
3881 you'll need to do this if your allocator recycles freed blocks, but it
3882 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
3883 Alternatively, if your allocator reuses freed blocks for allocator-internal
3884 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
3886 Really, what's happening is a blurring of the lines between the client
3887 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
3888 memory should be considered unaddressable to the client program, but the
3889 allocator knows more than the rest of the client program and so may be able
3890 to safely access it. Extra client requests are necessary for Valgrind to
3891 understand the distinction between the allocator and the rest of the
3894 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
3895 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
3897 Ignored if addr == 0.
3899 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
3900 {unsigned int _qzz_res; \
3901 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3902 VG_USERREQ__MALLOCLIKE_BLOCK, \
3903 addr, sizeB, rzB, is_zeroed, 0); \
3906 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3907 Ignored if addr == 0.
3909 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
3910 {unsigned int _qzz_res; \
3911 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3912 VG_USERREQ__FREELIKE_BLOCK, \
3913 addr, rzB, 0, 0, 0); \
3916 /* Create a memory pool. */
3917 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
3918 {unsigned int _qzz_res; \
3919 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3920 VG_USERREQ__CREATE_MEMPOOL, \
3921 pool, rzB, is_zeroed, 0, 0); \
3924 /* Destroy a memory pool. */
3925 #define VALGRIND_DESTROY_MEMPOOL(pool) \
3926 {unsigned int _qzz_res; \
3927 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3928 VG_USERREQ__DESTROY_MEMPOOL, \
3929 pool, 0, 0, 0, 0); \
3932 /* Associate a piece of memory with a memory pool. */
3933 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
3934 {unsigned int _qzz_res; \
3935 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3936 VG_USERREQ__MEMPOOL_ALLOC, \
3937 pool, addr, size, 0, 0); \
3940 /* Disassociate a piece of memory from a memory pool. */
3941 #define VALGRIND_MEMPOOL_FREE(pool, addr) \
3942 {unsigned int _qzz_res; \
3943 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3944 VG_USERREQ__MEMPOOL_FREE, \
3945 pool, addr, 0, 0, 0); \
3948 /* Disassociate any pieces outside a particular range. */
3949 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
3950 {unsigned int _qzz_res; \
3951 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3952 VG_USERREQ__MEMPOOL_TRIM, \
3953 pool, addr, size, 0, 0); \
3956 /* Resize and/or move a piece associated with a memory pool. */
3957 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
3958 {unsigned int _qzz_res; \
3959 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3960 VG_USERREQ__MOVE_MEMPOOL, \
3961 poolA, poolB, 0, 0, 0); \
3964 /* Resize and/or move a piece associated with a memory pool. */
3965 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
3966 {unsigned int _qzz_res; \
3967 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3968 VG_USERREQ__MEMPOOL_CHANGE, \
3969 pool, addrA, addrB, size, 0); \
3972 /* Return 1 if a mempool exists, else 0. */
3973 #define VALGRIND_MEMPOOL_EXISTS(pool) \
3975 ({unsigned int _qzz_res; \
3976 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3977 VG_USERREQ__MEMPOOL_EXISTS, \
3978 pool, 0, 0, 0, 0); \
3982 /* Mark a piece of memory as being a stack. Returns a stack id. */
3983 #define VALGRIND_STACK_REGISTER(start, end) \
3985 ({unsigned int _qzz_res; \
3986 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3987 VG_USERREQ__STACK_REGISTER, \
3988 start, end, 0, 0, 0); \
3992 /* Unmark the piece of memory associated with a stack id as being a
3994 #define VALGRIND_STACK_DEREGISTER(id) \
3995 {unsigned int _qzz_res; \
3996 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3997 VG_USERREQ__STACK_DEREGISTER, \
4001 /* Change the start and end address of the stack id. */
4002 #define VALGRIND_STACK_CHANGE(id, start, end) \
4003 {unsigned int _qzz_res; \
4004 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4005 VG_USERREQ__STACK_CHANGE, \
4006 id, start, end, 0, 0); \
4009 /* Load PDB debug info for Wine PE image_map. */
4010 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4011 {unsigned int _qzz_res; \
4012 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4013 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4014 fd, ptr, total_size, delta, 0); \
4018 #undef PLAT_x86_linux
4019 #undef PLAT_amd64_linux
4020 #undef PLAT_ppc32_linux
4021 #undef PLAT_ppc64_linux
4022 #undef PLAT_ppc32_aix5
4023 #undef PLAT_ppc64_aix5
4025 #else /* __GNUC__ */
4026 #define RUNNING_ON_VALGRIND 0
4028 #endif /* __VALGRIND_H */