2 ----------------------------------------------------------------
4 Notice that the following BSD-style license applies to this one
5 file (valgrind.h) only. The rest of Valgrind is licensed under the
6 terms of the GNU General Public License, version 2, unless
7 otherwise indicated. See the COPYING file in the source
8 distribution for details.
10 ----------------------------------------------------------------
12 This file is part of Valgrind, a dynamic binary instrumentation
15 Copyright (C) 2000-2009 Julian Seward. All rights reserved.
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
24 2. The origin of this software must not be misrepresented; you must
25 not claim that you wrote the original software. If you use this
26 software in a product, an acknowledgment in the product
27 documentation would be appreciated but is not required.
29 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
32 4. The name of the author may not be used to endorse or promote
33 products derived from this software without specific prior written
36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 ----------------------------------------------------------------
50 Notice that the above BSD-style license applies to this one file
51 (valgrind.h) only. The entire rest of Valgrind is licensed under
52 the terms of the GNU General Public License, version 2. See the
53 COPYING file in the source distribution for details.
55 ----------------------------------------------------------------
59 /* This file is for inclusion into client (your!) code.
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
67 consumes very few (eg. 7) instructions, so the resulting performance
68 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
78 /* Nb: this file might be included in a file compiled with -ansi. So
79 we can't use C++ style "//" comments nor the "asm" keyword (instead
82 /* Derive some tags indicating what the target platform is. Note
83 that in this file we're using the compiler's CPP symbols for
84 identifying architectures, which are different to the ones we use
85 within the rest of Valgrind. Note, __powerpc__ is active for both
86 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
87 latter (on Linux, that is).
89 Misc note: how to find out what's predefined in gcc by default:
90 gcc -Wp,-dM somefile.c
92 #undef PLAT_ppc64_aix5
93 #undef PLAT_ppc32_aix5
94 #undef PLAT_x86_darwin
95 #undef PLAT_amd64_darwin
97 #undef PLAT_amd64_linux
98 #undef PLAT_ppc32_linux
99 #undef PLAT_ppc64_linux
100 #undef PLAT_arm_linux
102 #if defined(_AIX) && defined(__64BIT__)
103 # define PLAT_ppc64_aix5 1
104 #elif defined(_AIX) && !defined(__64BIT__)
105 # define PLAT_ppc32_aix5 1
106 #elif defined(__APPLE__) && defined(__i386__)
107 # define PLAT_x86_darwin 1
108 #elif defined(__APPLE__) && defined(__x86_64__)
109 # define PLAT_amd64_darwin 1
110 #elif defined(__linux__) && defined(__i386__)
111 # define PLAT_x86_linux 1
112 #elif defined(__linux__) && defined(__x86_64__)
113 # define PLAT_amd64_linux 1
114 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
115 # define PLAT_ppc32_linux 1
116 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
117 # define PLAT_ppc64_linux 1
118 #elif defined(__linux__) && defined(__arm__)
119 # define PLAT_arm_linux 1
121 /* If we're not compiling for our target platform, don't generate
123 # if !defined(NVALGRIND)
129 /* ------------------------------------------------------------------ */
130 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
131 /* in here of use to end-users -- skip to the next section. */
132 /* ------------------------------------------------------------------ */
134 #if defined(NVALGRIND)
136 /* Define NVALGRIND to completely remove the Valgrind magic sequence
137 from the compiled code (analogous to NDEBUG's effects on
139 #define VALGRIND_DO_CLIENT_REQUEST( \
140 _zzq_rlval, _zzq_default, _zzq_request, \
141 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
143 (_zzq_rlval) = (_zzq_default); \
146 #else /* ! NVALGRIND */
148 /* The following defines the magic code sequences which the JITter
149 spots and handles magically. Don't look too closely at them as
150 they will rot your brain.
152 The assembly code sequences for all architectures is in this one
153 file. This is because this file must be stand-alone, and we don't
154 want to have multiple files.
156 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
157 value gets put in the return slot, so that everything works when
158 this is executed not under Valgrind. Args are passed in a memory
159 block, and so there's no intrinsic limit to the number that could
160 be passed, but it's currently five.
163 _zzq_rlval result lvalue
164 _zzq_default default value (result returned when running on real CPU)
165 _zzq_request request code
166 _zzq_arg1..5 request params
168 The other two macros are used to support function wrapping, and are
169 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
170 guest's NRADDR pseudo-register and whatever other information is
171 needed to safely run the call original from the wrapper: on
172 ppc64-linux, the R2 value at the divert point is also needed. This
173 information is abstracted into a user-visible type, OrigFn.
175 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
176 guest, but guarantees that the branch instruction will not be
177 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
178 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
179 complete inline asm, since it needs to be combined with more magic
180 inline asm stuff to be useful.
183 /* ------------------------- x86-{linux,darwin} ---------------- */
185 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
189 unsigned int nraddr
; /* where's the code? */
193 #define __SPECIAL_INSTRUCTION_PREAMBLE \
194 "roll $3, %%edi ; roll $13, %%edi\n\t" \
195 "roll $29, %%edi ; roll $19, %%edi\n\t"
197 #define VALGRIND_DO_CLIENT_REQUEST( \
198 _zzq_rlval, _zzq_default, _zzq_request, \
199 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
200 { volatile unsigned int _zzq_args[6]; \
201 volatile unsigned int _zzq_result; \
202 _zzq_args[0] = (unsigned int)(_zzq_request); \
203 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
204 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
205 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
206 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
207 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
208 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
209 /* %EDX = client_request ( %EAX ) */ \
210 "xchgl %%ebx,%%ebx" \
211 : "=d" (_zzq_result) \
212 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
215 _zzq_rlval = _zzq_result; \
218 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
219 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
220 volatile unsigned int __addr; \
221 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
222 /* %EAX = guest_NRADDR */ \
223 "xchgl %%ecx,%%ecx" \
228 _zzq_orig->nraddr = __addr; \
231 #define VALGRIND_CALL_NOREDIR_EAX \
232 __SPECIAL_INSTRUCTION_PREAMBLE \
233 /* call-noredir *%EAX */ \
234 "xchgl %%edx,%%edx\n\t"
235 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
237 /* ------------------------ amd64-{linux,darwin} --------------- */
239 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
243 unsigned long long int nraddr
; /* where's the code? */
247 #define __SPECIAL_INSTRUCTION_PREAMBLE \
248 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
249 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
251 #define VALGRIND_DO_CLIENT_REQUEST( \
252 _zzq_rlval, _zzq_default, _zzq_request, \
253 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
254 { volatile unsigned long long int _zzq_args[6]; \
255 volatile unsigned long long int _zzq_result; \
256 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
257 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
258 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
259 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
260 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
261 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
262 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
263 /* %RDX = client_request ( %RAX ) */ \
264 "xchgq %%rbx,%%rbx" \
265 : "=d" (_zzq_result) \
266 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
269 _zzq_rlval = _zzq_result; \
272 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
273 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
274 volatile unsigned long long int __addr; \
275 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
276 /* %RAX = guest_NRADDR */ \
277 "xchgq %%rcx,%%rcx" \
282 _zzq_orig->nraddr = __addr; \
285 #define VALGRIND_CALL_NOREDIR_RAX \
286 __SPECIAL_INSTRUCTION_PREAMBLE \
287 /* call-noredir *%RAX */ \
288 "xchgq %%rdx,%%rdx\n\t"
289 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
291 /* ------------------------ ppc32-linux ------------------------ */
293 #if defined(PLAT_ppc32_linux)
297 unsigned int nraddr
; /* where's the code? */
301 #define __SPECIAL_INSTRUCTION_PREAMBLE \
302 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
303 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
305 #define VALGRIND_DO_CLIENT_REQUEST( \
306 _zzq_rlval, _zzq_default, _zzq_request, \
307 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
309 { unsigned int _zzq_args[6]; \
310 unsigned int _zzq_result; \
311 unsigned int* _zzq_ptr; \
312 _zzq_args[0] = (unsigned int)(_zzq_request); \
313 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
314 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
315 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
316 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
317 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
318 _zzq_ptr = _zzq_args; \
319 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
320 "mr 4,%2\n\t" /*ptr*/ \
321 __SPECIAL_INSTRUCTION_PREAMBLE \
322 /* %R3 = client_request ( %R4 ) */ \
324 "mr %0,3" /*result*/ \
325 : "=b" (_zzq_result) \
326 : "b" (_zzq_default), "b" (_zzq_ptr) \
327 : "cc", "memory", "r3", "r4"); \
328 _zzq_rlval = _zzq_result; \
331 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
332 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
333 unsigned int __addr; \
334 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
335 /* %R3 = guest_NRADDR */ \
340 : "cc", "memory", "r3" \
342 _zzq_orig->nraddr = __addr; \
345 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
346 __SPECIAL_INSTRUCTION_PREAMBLE \
347 /* branch-and-link-to-noredir *%R11 */ \
349 #endif /* PLAT_ppc32_linux */
351 /* ------------------------ ppc64-linux ------------------------ */
353 #if defined(PLAT_ppc64_linux)
357 unsigned long long int nraddr
; /* where's the code? */
358 unsigned long long int r2
; /* what tocptr do we need? */
362 #define __SPECIAL_INSTRUCTION_PREAMBLE \
363 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
364 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
366 #define VALGRIND_DO_CLIENT_REQUEST( \
367 _zzq_rlval, _zzq_default, _zzq_request, \
368 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
370 { unsigned long long int _zzq_args[6]; \
371 register unsigned long long int _zzq_result __asm__("r3"); \
372 register unsigned long long int* _zzq_ptr __asm__("r4"); \
373 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
374 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
375 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
376 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
377 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
378 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
379 _zzq_ptr = _zzq_args; \
380 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
381 /* %R3 = client_request ( %R4 ) */ \
383 : "=r" (_zzq_result) \
384 : "0" (_zzq_default), "r" (_zzq_ptr) \
386 _zzq_rlval = _zzq_result; \
389 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
390 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
391 register unsigned long long int __addr __asm__("r3"); \
392 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
393 /* %R3 = guest_NRADDR */ \
399 _zzq_orig->nraddr = __addr; \
400 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
401 /* %R3 = guest_NRADDR_GPR2 */ \
407 _zzq_orig->r2 = __addr; \
410 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
411 __SPECIAL_INSTRUCTION_PREAMBLE \
412 /* branch-and-link-to-noredir *%R11 */ \
415 #endif /* PLAT_ppc64_linux */
417 /* ------------------------- arm-linux ------------------------- */
419 #if defined(PLAT_arm_linux)
423 unsigned int nraddr
; /* where's the code? */
427 #define __SPECIAL_INSTRUCTION_PREAMBLE \
428 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
429 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
431 #define VALGRIND_DO_CLIENT_REQUEST( \
432 _zzq_rlval, _zzq_default, _zzq_request, \
433 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
435 { volatile unsigned int _zzq_args[6]; \
436 volatile unsigned int _zzq_result; \
437 _zzq_args[0] = (unsigned int)(_zzq_request); \
438 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
439 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
440 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
441 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
442 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
443 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
444 "mov r4, %2\n\t" /*ptr*/ \
445 __SPECIAL_INSTRUCTION_PREAMBLE \
446 /* R3 = client_request ( R4 ) */ \
447 "orr r10, r10, r10\n\t" \
448 "mov %0, r3" /*result*/ \
449 : "=r" (_zzq_result) \
450 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
451 : "cc","memory", "r3", "r4"); \
452 _zzq_rlval = _zzq_result; \
455 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
456 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
457 unsigned int __addr; \
458 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
459 /* R3 = guest_NRADDR */ \
460 "orr r11, r11, r11\n\t" \
464 : "cc", "memory", "r3" \
466 _zzq_orig->nraddr = __addr; \
469 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
470 __SPECIAL_INSTRUCTION_PREAMBLE \
471 /* branch-and-link-to-noredir *%R4 */ \
472 "orr r12, r12, r12\n\t"
474 #endif /* PLAT_arm_linux */
476 /* ------------------------ ppc32-aix5 ------------------------- */
478 #if defined(PLAT_ppc32_aix5)
482 unsigned int nraddr
; /* where's the code? */
483 unsigned int r2
; /* what tocptr do we need? */
487 #define __SPECIAL_INSTRUCTION_PREAMBLE \
488 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
489 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
491 #define VALGRIND_DO_CLIENT_REQUEST( \
492 _zzq_rlval, _zzq_default, _zzq_request, \
493 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
495 { unsigned int _zzq_args[7]; \
496 register unsigned int _zzq_result; \
497 register unsigned int* _zzq_ptr; \
498 _zzq_args[0] = (unsigned int)(_zzq_request); \
499 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
500 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
501 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
502 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
503 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
504 _zzq_args[6] = (unsigned int)(_zzq_default); \
505 _zzq_ptr = _zzq_args; \
506 __asm__ volatile("mr 4,%1\n\t" \
508 __SPECIAL_INSTRUCTION_PREAMBLE \
509 /* %R3 = client_request ( %R4 ) */ \
512 : "=b" (_zzq_result) \
514 : "r3", "r4", "cc", "memory"); \
515 _zzq_rlval = _zzq_result; \
518 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
519 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
520 register unsigned int __addr; \
521 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
522 /* %R3 = guest_NRADDR */ \
527 : "r3", "cc", "memory" \
529 _zzq_orig->nraddr = __addr; \
530 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
531 /* %R3 = guest_NRADDR_GPR2 */ \
536 : "r3", "cc", "memory" \
538 _zzq_orig->r2 = __addr; \
541 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
542 __SPECIAL_INSTRUCTION_PREAMBLE \
543 /* branch-and-link-to-noredir *%R11 */ \
546 #endif /* PLAT_ppc32_aix5 */
548 /* ------------------------ ppc64-aix5 ------------------------- */
550 #if defined(PLAT_ppc64_aix5)
554 unsigned long long int nraddr
; /* where's the code? */
555 unsigned long long int r2
; /* what tocptr do we need? */
559 #define __SPECIAL_INSTRUCTION_PREAMBLE \
560 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
561 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
563 #define VALGRIND_DO_CLIENT_REQUEST( \
564 _zzq_rlval, _zzq_default, _zzq_request, \
565 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
567 { unsigned long long int _zzq_args[7]; \
568 register unsigned long long int _zzq_result; \
569 register unsigned long long int* _zzq_ptr; \
570 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
571 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
572 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
573 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
574 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
575 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
576 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
577 _zzq_ptr = _zzq_args; \
578 __asm__ volatile("mr 4,%1\n\t" \
580 __SPECIAL_INSTRUCTION_PREAMBLE \
581 /* %R3 = client_request ( %R4 ) */ \
584 : "=b" (_zzq_result) \
586 : "r3", "r4", "cc", "memory"); \
587 _zzq_rlval = _zzq_result; \
590 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
591 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
592 register unsigned long long int __addr; \
593 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
594 /* %R3 = guest_NRADDR */ \
599 : "r3", "cc", "memory" \
601 _zzq_orig->nraddr = __addr; \
602 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
603 /* %R3 = guest_NRADDR_GPR2 */ \
608 : "r3", "cc", "memory" \
610 _zzq_orig->r2 = __addr; \
613 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
614 __SPECIAL_INSTRUCTION_PREAMBLE \
615 /* branch-and-link-to-noredir *%R11 */ \
618 #endif /* PLAT_ppc64_aix5 */
620 /* Insert assembly code for other platforms here... */
622 #endif /* NVALGRIND */
625 /* ------------------------------------------------------------------ */
626 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
627 /* ugly. It's the least-worst tradeoff I can think of. */
628 /* ------------------------------------------------------------------ */
630 /* This section defines magic (a.k.a appalling-hack) macros for doing
631 guaranteed-no-redirection macros, so as to get from function
632 wrappers to the functions they are wrapping. The whole point is to
633 construct standard call sequences, but to do the call itself with a
634 special no-redirect call pseudo-instruction that the JIT
635 understands and handles specially. This section is long and
636 repetitious, and I can't see a way to make it shorter.
638 The naming scheme is as follows:
640 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
642 'W' stands for "word" and 'v' for "void". Hence there are
643 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
644 and for each, the possibility of returning a word-typed result, or
648 /* Use these to write the name of your wrapper. NOTE: duplicates
649 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
651 /* Use an extra level of macroisation so as to ensure the soname/fnname
652 args are fully macro-expanded before pasting them together. */
653 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
655 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
656 VG_CONCAT4(_vgwZU_,soname,_,fnname)
658 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
659 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
661 /* Use this macro from within a wrapper function to collect the
662 context (address and possibly other info) of the original function.
663 Once you have that you can then use it in one of the CALL_FN_
664 macros. The type of the argument _lval is OrigFn. */
665 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
667 /* Derivatives of the main macros below, for calling functions
670 #define CALL_FN_v_v(fnptr) \
671 do { volatile unsigned long _junk; \
672 CALL_FN_W_v(_junk,fnptr); } while (0)
674 #define CALL_FN_v_W(fnptr, arg1) \
675 do { volatile unsigned long _junk; \
676 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
678 #define CALL_FN_v_WW(fnptr, arg1,arg2) \
679 do { volatile unsigned long _junk; \
680 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
682 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
683 do { volatile unsigned long _junk; \
684 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
686 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
687 do { volatile unsigned long _junk; \
688 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
690 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
691 do { volatile unsigned long _junk; \
692 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
694 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
695 do { volatile unsigned long _junk; \
696 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
698 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
699 do { volatile unsigned long _junk; \
700 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
702 /* ------------------------- x86-{linux,darwin} ---------------- */
704 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
706 /* These regs are trashed by the hidden call. No need to mention eax
707 as gcc can already see that, plus causes gcc to bomb. */
708 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
710 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
713 #define CALL_FN_W_v(lval, orig) \
715 volatile OrigFn _orig = (orig); \
716 volatile unsigned long _argvec[1]; \
717 volatile unsigned long _res; \
718 _argvec[0] = (unsigned long)_orig.nraddr; \
720 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
721 VALGRIND_CALL_NOREDIR_EAX \
722 : /*out*/ "=a" (_res) \
723 : /*in*/ "a" (&_argvec[0]) \
724 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
726 lval = (__typeof__(lval)) _res; \
729 #define CALL_FN_W_W(lval, orig, arg1) \
731 volatile OrigFn _orig = (orig); \
732 volatile unsigned long _argvec[2]; \
733 volatile unsigned long _res; \
734 _argvec[0] = (unsigned long)_orig.nraddr; \
735 _argvec[1] = (unsigned long)(arg1); \
737 "pushl 4(%%eax)\n\t" \
738 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
739 VALGRIND_CALL_NOREDIR_EAX \
741 : /*out*/ "=a" (_res) \
742 : /*in*/ "a" (&_argvec[0]) \
743 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
745 lval = (__typeof__(lval)) _res; \
748 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
750 volatile OrigFn _orig = (orig); \
751 volatile unsigned long _argvec[3]; \
752 volatile unsigned long _res; \
753 _argvec[0] = (unsigned long)_orig.nraddr; \
754 _argvec[1] = (unsigned long)(arg1); \
755 _argvec[2] = (unsigned long)(arg2); \
757 "pushl 8(%%eax)\n\t" \
758 "pushl 4(%%eax)\n\t" \
759 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
760 VALGRIND_CALL_NOREDIR_EAX \
762 : /*out*/ "=a" (_res) \
763 : /*in*/ "a" (&_argvec[0]) \
764 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
766 lval = (__typeof__(lval)) _res; \
769 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
771 volatile OrigFn _orig = (orig); \
772 volatile unsigned long _argvec[4]; \
773 volatile unsigned long _res; \
774 _argvec[0] = (unsigned long)_orig.nraddr; \
775 _argvec[1] = (unsigned long)(arg1); \
776 _argvec[2] = (unsigned long)(arg2); \
777 _argvec[3] = (unsigned long)(arg3); \
779 "pushl 12(%%eax)\n\t" \
780 "pushl 8(%%eax)\n\t" \
781 "pushl 4(%%eax)\n\t" \
782 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
783 VALGRIND_CALL_NOREDIR_EAX \
784 "addl $12, %%esp\n" \
785 : /*out*/ "=a" (_res) \
786 : /*in*/ "a" (&_argvec[0]) \
787 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
789 lval = (__typeof__(lval)) _res; \
792 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
794 volatile OrigFn _orig = (orig); \
795 volatile unsigned long _argvec[5]; \
796 volatile unsigned long _res; \
797 _argvec[0] = (unsigned long)_orig.nraddr; \
798 _argvec[1] = (unsigned long)(arg1); \
799 _argvec[2] = (unsigned long)(arg2); \
800 _argvec[3] = (unsigned long)(arg3); \
801 _argvec[4] = (unsigned long)(arg4); \
803 "pushl 16(%%eax)\n\t" \
804 "pushl 12(%%eax)\n\t" \
805 "pushl 8(%%eax)\n\t" \
806 "pushl 4(%%eax)\n\t" \
807 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
808 VALGRIND_CALL_NOREDIR_EAX \
809 "addl $16, %%esp\n" \
810 : /*out*/ "=a" (_res) \
811 : /*in*/ "a" (&_argvec[0]) \
812 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
814 lval = (__typeof__(lval)) _res; \
817 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
819 volatile OrigFn _orig = (orig); \
820 volatile unsigned long _argvec[6]; \
821 volatile unsigned long _res; \
822 _argvec[0] = (unsigned long)_orig.nraddr; \
823 _argvec[1] = (unsigned long)(arg1); \
824 _argvec[2] = (unsigned long)(arg2); \
825 _argvec[3] = (unsigned long)(arg3); \
826 _argvec[4] = (unsigned long)(arg4); \
827 _argvec[5] = (unsigned long)(arg5); \
829 "pushl 20(%%eax)\n\t" \
830 "pushl 16(%%eax)\n\t" \
831 "pushl 12(%%eax)\n\t" \
832 "pushl 8(%%eax)\n\t" \
833 "pushl 4(%%eax)\n\t" \
834 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
835 VALGRIND_CALL_NOREDIR_EAX \
836 "addl $20, %%esp\n" \
837 : /*out*/ "=a" (_res) \
838 : /*in*/ "a" (&_argvec[0]) \
839 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
841 lval = (__typeof__(lval)) _res; \
844 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
846 volatile OrigFn _orig = (orig); \
847 volatile unsigned long _argvec[7]; \
848 volatile unsigned long _res; \
849 _argvec[0] = (unsigned long)_orig.nraddr; \
850 _argvec[1] = (unsigned long)(arg1); \
851 _argvec[2] = (unsigned long)(arg2); \
852 _argvec[3] = (unsigned long)(arg3); \
853 _argvec[4] = (unsigned long)(arg4); \
854 _argvec[5] = (unsigned long)(arg5); \
855 _argvec[6] = (unsigned long)(arg6); \
857 "pushl 24(%%eax)\n\t" \
858 "pushl 20(%%eax)\n\t" \
859 "pushl 16(%%eax)\n\t" \
860 "pushl 12(%%eax)\n\t" \
861 "pushl 8(%%eax)\n\t" \
862 "pushl 4(%%eax)\n\t" \
863 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
864 VALGRIND_CALL_NOREDIR_EAX \
865 "addl $24, %%esp\n" \
866 : /*out*/ "=a" (_res) \
867 : /*in*/ "a" (&_argvec[0]) \
868 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
870 lval = (__typeof__(lval)) _res; \
873 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
876 volatile OrigFn _orig = (orig); \
877 volatile unsigned long _argvec[8]; \
878 volatile unsigned long _res; \
879 _argvec[0] = (unsigned long)_orig.nraddr; \
880 _argvec[1] = (unsigned long)(arg1); \
881 _argvec[2] = (unsigned long)(arg2); \
882 _argvec[3] = (unsigned long)(arg3); \
883 _argvec[4] = (unsigned long)(arg4); \
884 _argvec[5] = (unsigned long)(arg5); \
885 _argvec[6] = (unsigned long)(arg6); \
886 _argvec[7] = (unsigned long)(arg7); \
888 "pushl 28(%%eax)\n\t" \
889 "pushl 24(%%eax)\n\t" \
890 "pushl 20(%%eax)\n\t" \
891 "pushl 16(%%eax)\n\t" \
892 "pushl 12(%%eax)\n\t" \
893 "pushl 8(%%eax)\n\t" \
894 "pushl 4(%%eax)\n\t" \
895 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
896 VALGRIND_CALL_NOREDIR_EAX \
897 "addl $28, %%esp\n" \
898 : /*out*/ "=a" (_res) \
899 : /*in*/ "a" (&_argvec[0]) \
900 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
902 lval = (__typeof__(lval)) _res; \
905 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
908 volatile OrigFn _orig = (orig); \
909 volatile unsigned long _argvec[9]; \
910 volatile unsigned long _res; \
911 _argvec[0] = (unsigned long)_orig.nraddr; \
912 _argvec[1] = (unsigned long)(arg1); \
913 _argvec[2] = (unsigned long)(arg2); \
914 _argvec[3] = (unsigned long)(arg3); \
915 _argvec[4] = (unsigned long)(arg4); \
916 _argvec[5] = (unsigned long)(arg5); \
917 _argvec[6] = (unsigned long)(arg6); \
918 _argvec[7] = (unsigned long)(arg7); \
919 _argvec[8] = (unsigned long)(arg8); \
921 "pushl 32(%%eax)\n\t" \
922 "pushl 28(%%eax)\n\t" \
923 "pushl 24(%%eax)\n\t" \
924 "pushl 20(%%eax)\n\t" \
925 "pushl 16(%%eax)\n\t" \
926 "pushl 12(%%eax)\n\t" \
927 "pushl 8(%%eax)\n\t" \
928 "pushl 4(%%eax)\n\t" \
929 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
930 VALGRIND_CALL_NOREDIR_EAX \
931 "addl $32, %%esp\n" \
932 : /*out*/ "=a" (_res) \
933 : /*in*/ "a" (&_argvec[0]) \
934 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
936 lval = (__typeof__(lval)) _res; \
939 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
942 volatile OrigFn _orig = (orig); \
943 volatile unsigned long _argvec[10]; \
944 volatile unsigned long _res; \
945 _argvec[0] = (unsigned long)_orig.nraddr; \
946 _argvec[1] = (unsigned long)(arg1); \
947 _argvec[2] = (unsigned long)(arg2); \
948 _argvec[3] = (unsigned long)(arg3); \
949 _argvec[4] = (unsigned long)(arg4); \
950 _argvec[5] = (unsigned long)(arg5); \
951 _argvec[6] = (unsigned long)(arg6); \
952 _argvec[7] = (unsigned long)(arg7); \
953 _argvec[8] = (unsigned long)(arg8); \
954 _argvec[9] = (unsigned long)(arg9); \
956 "pushl 36(%%eax)\n\t" \
957 "pushl 32(%%eax)\n\t" \
958 "pushl 28(%%eax)\n\t" \
959 "pushl 24(%%eax)\n\t" \
960 "pushl 20(%%eax)\n\t" \
961 "pushl 16(%%eax)\n\t" \
962 "pushl 12(%%eax)\n\t" \
963 "pushl 8(%%eax)\n\t" \
964 "pushl 4(%%eax)\n\t" \
965 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
966 VALGRIND_CALL_NOREDIR_EAX \
967 "addl $36, %%esp\n" \
968 : /*out*/ "=a" (_res) \
969 : /*in*/ "a" (&_argvec[0]) \
970 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
972 lval = (__typeof__(lval)) _res; \
975 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
976 arg7,arg8,arg9,arg10) \
978 volatile OrigFn _orig = (orig); \
979 volatile unsigned long _argvec[11]; \
980 volatile unsigned long _res; \
981 _argvec[0] = (unsigned long)_orig.nraddr; \
982 _argvec[1] = (unsigned long)(arg1); \
983 _argvec[2] = (unsigned long)(arg2); \
984 _argvec[3] = (unsigned long)(arg3); \
985 _argvec[4] = (unsigned long)(arg4); \
986 _argvec[5] = (unsigned long)(arg5); \
987 _argvec[6] = (unsigned long)(arg6); \
988 _argvec[7] = (unsigned long)(arg7); \
989 _argvec[8] = (unsigned long)(arg8); \
990 _argvec[9] = (unsigned long)(arg9); \
991 _argvec[10] = (unsigned long)(arg10); \
993 "pushl 40(%%eax)\n\t" \
994 "pushl 36(%%eax)\n\t" \
995 "pushl 32(%%eax)\n\t" \
996 "pushl 28(%%eax)\n\t" \
997 "pushl 24(%%eax)\n\t" \
998 "pushl 20(%%eax)\n\t" \
999 "pushl 16(%%eax)\n\t" \
1000 "pushl 12(%%eax)\n\t" \
1001 "pushl 8(%%eax)\n\t" \
1002 "pushl 4(%%eax)\n\t" \
1003 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1004 VALGRIND_CALL_NOREDIR_EAX \
1005 "addl $40, %%esp\n" \
1006 : /*out*/ "=a" (_res) \
1007 : /*in*/ "a" (&_argvec[0]) \
1008 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1010 lval = (__typeof__(lval)) _res; \
1013 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1014 arg6,arg7,arg8,arg9,arg10, \
1017 volatile OrigFn _orig = (orig); \
1018 volatile unsigned long _argvec[12]; \
1019 volatile unsigned long _res; \
1020 _argvec[0] = (unsigned long)_orig.nraddr; \
1021 _argvec[1] = (unsigned long)(arg1); \
1022 _argvec[2] = (unsigned long)(arg2); \
1023 _argvec[3] = (unsigned long)(arg3); \
1024 _argvec[4] = (unsigned long)(arg4); \
1025 _argvec[5] = (unsigned long)(arg5); \
1026 _argvec[6] = (unsigned long)(arg6); \
1027 _argvec[7] = (unsigned long)(arg7); \
1028 _argvec[8] = (unsigned long)(arg8); \
1029 _argvec[9] = (unsigned long)(arg9); \
1030 _argvec[10] = (unsigned long)(arg10); \
1031 _argvec[11] = (unsigned long)(arg11); \
1033 "pushl 44(%%eax)\n\t" \
1034 "pushl 40(%%eax)\n\t" \
1035 "pushl 36(%%eax)\n\t" \
1036 "pushl 32(%%eax)\n\t" \
1037 "pushl 28(%%eax)\n\t" \
1038 "pushl 24(%%eax)\n\t" \
1039 "pushl 20(%%eax)\n\t" \
1040 "pushl 16(%%eax)\n\t" \
1041 "pushl 12(%%eax)\n\t" \
1042 "pushl 8(%%eax)\n\t" \
1043 "pushl 4(%%eax)\n\t" \
1044 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1045 VALGRIND_CALL_NOREDIR_EAX \
1046 "addl $44, %%esp\n" \
1047 : /*out*/ "=a" (_res) \
1048 : /*in*/ "a" (&_argvec[0]) \
1049 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1051 lval = (__typeof__(lval)) _res; \
1054 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1055 arg6,arg7,arg8,arg9,arg10, \
1058 volatile OrigFn _orig = (orig); \
1059 volatile unsigned long _argvec[13]; \
1060 volatile unsigned long _res; \
1061 _argvec[0] = (unsigned long)_orig.nraddr; \
1062 _argvec[1] = (unsigned long)(arg1); \
1063 _argvec[2] = (unsigned long)(arg2); \
1064 _argvec[3] = (unsigned long)(arg3); \
1065 _argvec[4] = (unsigned long)(arg4); \
1066 _argvec[5] = (unsigned long)(arg5); \
1067 _argvec[6] = (unsigned long)(arg6); \
1068 _argvec[7] = (unsigned long)(arg7); \
1069 _argvec[8] = (unsigned long)(arg8); \
1070 _argvec[9] = (unsigned long)(arg9); \
1071 _argvec[10] = (unsigned long)(arg10); \
1072 _argvec[11] = (unsigned long)(arg11); \
1073 _argvec[12] = (unsigned long)(arg12); \
1075 "pushl 48(%%eax)\n\t" \
1076 "pushl 44(%%eax)\n\t" \
1077 "pushl 40(%%eax)\n\t" \
1078 "pushl 36(%%eax)\n\t" \
1079 "pushl 32(%%eax)\n\t" \
1080 "pushl 28(%%eax)\n\t" \
1081 "pushl 24(%%eax)\n\t" \
1082 "pushl 20(%%eax)\n\t" \
1083 "pushl 16(%%eax)\n\t" \
1084 "pushl 12(%%eax)\n\t" \
1085 "pushl 8(%%eax)\n\t" \
1086 "pushl 4(%%eax)\n\t" \
1087 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1088 VALGRIND_CALL_NOREDIR_EAX \
1089 "addl $48, %%esp\n" \
1090 : /*out*/ "=a" (_res) \
1091 : /*in*/ "a" (&_argvec[0]) \
1092 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1094 lval = (__typeof__(lval)) _res; \
1097 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
1099 /* ------------------------ amd64-{linux,darwin} --------------- */
1101 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
1103 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1105 /* These regs are trashed by the hidden call. */
1106 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1107 "rdi", "r8", "r9", "r10", "r11"
1109 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1112 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1113 macros. In order not to trash the stack redzone, we need to drop
1114 %rsp by 128 before the hidden call, and restore afterwards. The
1115 nastyness is that it is only by luck that the stack still appears
1116 to be unwindable during the hidden call - since then the behaviour
1117 of any routine using this macro does not match what the CFI data
1120 Why is this important? Imagine that a wrapper has a stack
1121 allocated local, and passes to the hidden call, a pointer to it.
1122 Because gcc does not know about the hidden call, it may allocate
1123 that local in the redzone. Unfortunately the hidden call may then
1124 trash it before it comes to use it. So we must step clear of the
1125 redzone, for the duration of the hidden call, to make it safe.
1127 Probably the same problem afflicts the other redzone-style ABIs too
1128 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1129 self describing (none of this CFI nonsense) so at least messing
1130 with the stack pointer doesn't give a danger of non-unwindable
1133 #define CALL_FN_W_v(lval, orig) \
1135 volatile OrigFn _orig = (orig); \
1136 volatile unsigned long _argvec[1]; \
1137 volatile unsigned long _res; \
1138 _argvec[0] = (unsigned long)_orig.nraddr; \
1140 "subq $128,%%rsp\n\t" \
1141 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1142 VALGRIND_CALL_NOREDIR_RAX \
1143 "addq $128,%%rsp\n\t" \
1144 : /*out*/ "=a" (_res) \
1145 : /*in*/ "a" (&_argvec[0]) \
1146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1148 lval = (__typeof__(lval)) _res; \
1151 #define CALL_FN_W_W(lval, orig, arg1) \
1153 volatile OrigFn _orig = (orig); \
1154 volatile unsigned long _argvec[2]; \
1155 volatile unsigned long _res; \
1156 _argvec[0] = (unsigned long)_orig.nraddr; \
1157 _argvec[1] = (unsigned long)(arg1); \
1159 "subq $128,%%rsp\n\t" \
1160 "movq 8(%%rax), %%rdi\n\t" \
1161 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1162 VALGRIND_CALL_NOREDIR_RAX \
1163 "addq $128,%%rsp\n\t" \
1164 : /*out*/ "=a" (_res) \
1165 : /*in*/ "a" (&_argvec[0]) \
1166 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1168 lval = (__typeof__(lval)) _res; \
1171 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1173 volatile OrigFn _orig = (orig); \
1174 volatile unsigned long _argvec[3]; \
1175 volatile unsigned long _res; \
1176 _argvec[0] = (unsigned long)_orig.nraddr; \
1177 _argvec[1] = (unsigned long)(arg1); \
1178 _argvec[2] = (unsigned long)(arg2); \
1180 "subq $128,%%rsp\n\t" \
1181 "movq 16(%%rax), %%rsi\n\t" \
1182 "movq 8(%%rax), %%rdi\n\t" \
1183 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1184 VALGRIND_CALL_NOREDIR_RAX \
1185 "addq $128,%%rsp\n\t" \
1186 : /*out*/ "=a" (_res) \
1187 : /*in*/ "a" (&_argvec[0]) \
1188 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1190 lval = (__typeof__(lval)) _res; \
1193 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1195 volatile OrigFn _orig = (orig); \
1196 volatile unsigned long _argvec[4]; \
1197 volatile unsigned long _res; \
1198 _argvec[0] = (unsigned long)_orig.nraddr; \
1199 _argvec[1] = (unsigned long)(arg1); \
1200 _argvec[2] = (unsigned long)(arg2); \
1201 _argvec[3] = (unsigned long)(arg3); \
1203 "subq $128,%%rsp\n\t" \
1204 "movq 24(%%rax), %%rdx\n\t" \
1205 "movq 16(%%rax), %%rsi\n\t" \
1206 "movq 8(%%rax), %%rdi\n\t" \
1207 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1208 VALGRIND_CALL_NOREDIR_RAX \
1209 "addq $128,%%rsp\n\t" \
1210 : /*out*/ "=a" (_res) \
1211 : /*in*/ "a" (&_argvec[0]) \
1212 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1214 lval = (__typeof__(lval)) _res; \
1217 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1219 volatile OrigFn _orig = (orig); \
1220 volatile unsigned long _argvec[5]; \
1221 volatile unsigned long _res; \
1222 _argvec[0] = (unsigned long)_orig.nraddr; \
1223 _argvec[1] = (unsigned long)(arg1); \
1224 _argvec[2] = (unsigned long)(arg2); \
1225 _argvec[3] = (unsigned long)(arg3); \
1226 _argvec[4] = (unsigned long)(arg4); \
1228 "subq $128,%%rsp\n\t" \
1229 "movq 32(%%rax), %%rcx\n\t" \
1230 "movq 24(%%rax), %%rdx\n\t" \
1231 "movq 16(%%rax), %%rsi\n\t" \
1232 "movq 8(%%rax), %%rdi\n\t" \
1233 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1234 VALGRIND_CALL_NOREDIR_RAX \
1235 "addq $128,%%rsp\n\t" \
1236 : /*out*/ "=a" (_res) \
1237 : /*in*/ "a" (&_argvec[0]) \
1238 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1240 lval = (__typeof__(lval)) _res; \
1243 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1245 volatile OrigFn _orig = (orig); \
1246 volatile unsigned long _argvec[6]; \
1247 volatile unsigned long _res; \
1248 _argvec[0] = (unsigned long)_orig.nraddr; \
1249 _argvec[1] = (unsigned long)(arg1); \
1250 _argvec[2] = (unsigned long)(arg2); \
1251 _argvec[3] = (unsigned long)(arg3); \
1252 _argvec[4] = (unsigned long)(arg4); \
1253 _argvec[5] = (unsigned long)(arg5); \
1255 "subq $128,%%rsp\n\t" \
1256 "movq 40(%%rax), %%r8\n\t" \
1257 "movq 32(%%rax), %%rcx\n\t" \
1258 "movq 24(%%rax), %%rdx\n\t" \
1259 "movq 16(%%rax), %%rsi\n\t" \
1260 "movq 8(%%rax), %%rdi\n\t" \
1261 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1262 VALGRIND_CALL_NOREDIR_RAX \
1263 "addq $128,%%rsp\n\t" \
1264 : /*out*/ "=a" (_res) \
1265 : /*in*/ "a" (&_argvec[0]) \
1266 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1268 lval = (__typeof__(lval)) _res; \
1271 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1273 volatile OrigFn _orig = (orig); \
1274 volatile unsigned long _argvec[7]; \
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); \
1284 "subq $128,%%rsp\n\t" \
1285 "movq 48(%%rax), %%r9\n\t" \
1286 "movq 40(%%rax), %%r8\n\t" \
1287 "movq 32(%%rax), %%rcx\n\t" \
1288 "movq 24(%%rax), %%rdx\n\t" \
1289 "movq 16(%%rax), %%rsi\n\t" \
1290 "movq 8(%%rax), %%rdi\n\t" \
1291 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1292 "addq $128,%%rsp\n\t" \
1293 VALGRIND_CALL_NOREDIR_RAX \
1294 : /*out*/ "=a" (_res) \
1295 : /*in*/ "a" (&_argvec[0]) \
1296 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1298 lval = (__typeof__(lval)) _res; \
1301 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1304 volatile OrigFn _orig = (orig); \
1305 volatile unsigned long _argvec[8]; \
1306 volatile unsigned long _res; \
1307 _argvec[0] = (unsigned long)_orig.nraddr; \
1308 _argvec[1] = (unsigned long)(arg1); \
1309 _argvec[2] = (unsigned long)(arg2); \
1310 _argvec[3] = (unsigned long)(arg3); \
1311 _argvec[4] = (unsigned long)(arg4); \
1312 _argvec[5] = (unsigned long)(arg5); \
1313 _argvec[6] = (unsigned long)(arg6); \
1314 _argvec[7] = (unsigned long)(arg7); \
1316 "subq $128,%%rsp\n\t" \
1317 "pushq 56(%%rax)\n\t" \
1318 "movq 48(%%rax), %%r9\n\t" \
1319 "movq 40(%%rax), %%r8\n\t" \
1320 "movq 32(%%rax), %%rcx\n\t" \
1321 "movq 24(%%rax), %%rdx\n\t" \
1322 "movq 16(%%rax), %%rsi\n\t" \
1323 "movq 8(%%rax), %%rdi\n\t" \
1324 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1325 VALGRIND_CALL_NOREDIR_RAX \
1326 "addq $8, %%rsp\n" \
1327 "addq $128,%%rsp\n\t" \
1328 : /*out*/ "=a" (_res) \
1329 : /*in*/ "a" (&_argvec[0]) \
1330 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1332 lval = (__typeof__(lval)) _res; \
1335 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1338 volatile OrigFn _orig = (orig); \
1339 volatile unsigned long _argvec[9]; \
1340 volatile unsigned long _res; \
1341 _argvec[0] = (unsigned long)_orig.nraddr; \
1342 _argvec[1] = (unsigned long)(arg1); \
1343 _argvec[2] = (unsigned long)(arg2); \
1344 _argvec[3] = (unsigned long)(arg3); \
1345 _argvec[4] = (unsigned long)(arg4); \
1346 _argvec[5] = (unsigned long)(arg5); \
1347 _argvec[6] = (unsigned long)(arg6); \
1348 _argvec[7] = (unsigned long)(arg7); \
1349 _argvec[8] = (unsigned long)(arg8); \
1351 "subq $128,%%rsp\n\t" \
1352 "pushq 64(%%rax)\n\t" \
1353 "pushq 56(%%rax)\n\t" \
1354 "movq 48(%%rax), %%r9\n\t" \
1355 "movq 40(%%rax), %%r8\n\t" \
1356 "movq 32(%%rax), %%rcx\n\t" \
1357 "movq 24(%%rax), %%rdx\n\t" \
1358 "movq 16(%%rax), %%rsi\n\t" \
1359 "movq 8(%%rax), %%rdi\n\t" \
1360 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1361 VALGRIND_CALL_NOREDIR_RAX \
1362 "addq $16, %%rsp\n" \
1363 "addq $128,%%rsp\n\t" \
1364 : /*out*/ "=a" (_res) \
1365 : /*in*/ "a" (&_argvec[0]) \
1366 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1368 lval = (__typeof__(lval)) _res; \
1371 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1374 volatile OrigFn _orig = (orig); \
1375 volatile unsigned long _argvec[10]; \
1376 volatile unsigned long _res; \
1377 _argvec[0] = (unsigned long)_orig.nraddr; \
1378 _argvec[1] = (unsigned long)(arg1); \
1379 _argvec[2] = (unsigned long)(arg2); \
1380 _argvec[3] = (unsigned long)(arg3); \
1381 _argvec[4] = (unsigned long)(arg4); \
1382 _argvec[5] = (unsigned long)(arg5); \
1383 _argvec[6] = (unsigned long)(arg6); \
1384 _argvec[7] = (unsigned long)(arg7); \
1385 _argvec[8] = (unsigned long)(arg8); \
1386 _argvec[9] = (unsigned long)(arg9); \
1388 "subq $128,%%rsp\n\t" \
1389 "pushq 72(%%rax)\n\t" \
1390 "pushq 64(%%rax)\n\t" \
1391 "pushq 56(%%rax)\n\t" \
1392 "movq 48(%%rax), %%r9\n\t" \
1393 "movq 40(%%rax), %%r8\n\t" \
1394 "movq 32(%%rax), %%rcx\n\t" \
1395 "movq 24(%%rax), %%rdx\n\t" \
1396 "movq 16(%%rax), %%rsi\n\t" \
1397 "movq 8(%%rax), %%rdi\n\t" \
1398 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1399 VALGRIND_CALL_NOREDIR_RAX \
1400 "addq $24, %%rsp\n" \
1401 "addq $128,%%rsp\n\t" \
1402 : /*out*/ "=a" (_res) \
1403 : /*in*/ "a" (&_argvec[0]) \
1404 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1406 lval = (__typeof__(lval)) _res; \
1409 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1410 arg7,arg8,arg9,arg10) \
1412 volatile OrigFn _orig = (orig); \
1413 volatile unsigned long _argvec[11]; \
1414 volatile unsigned long _res; \
1415 _argvec[0] = (unsigned long)_orig.nraddr; \
1416 _argvec[1] = (unsigned long)(arg1); \
1417 _argvec[2] = (unsigned long)(arg2); \
1418 _argvec[3] = (unsigned long)(arg3); \
1419 _argvec[4] = (unsigned long)(arg4); \
1420 _argvec[5] = (unsigned long)(arg5); \
1421 _argvec[6] = (unsigned long)(arg6); \
1422 _argvec[7] = (unsigned long)(arg7); \
1423 _argvec[8] = (unsigned long)(arg8); \
1424 _argvec[9] = (unsigned long)(arg9); \
1425 _argvec[10] = (unsigned long)(arg10); \
1427 "subq $128,%%rsp\n\t" \
1428 "pushq 80(%%rax)\n\t" \
1429 "pushq 72(%%rax)\n\t" \
1430 "pushq 64(%%rax)\n\t" \
1431 "pushq 56(%%rax)\n\t" \
1432 "movq 48(%%rax), %%r9\n\t" \
1433 "movq 40(%%rax), %%r8\n\t" \
1434 "movq 32(%%rax), %%rcx\n\t" \
1435 "movq 24(%%rax), %%rdx\n\t" \
1436 "movq 16(%%rax), %%rsi\n\t" \
1437 "movq 8(%%rax), %%rdi\n\t" \
1438 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1439 VALGRIND_CALL_NOREDIR_RAX \
1440 "addq $32, %%rsp\n" \
1441 "addq $128,%%rsp\n\t" \
1442 : /*out*/ "=a" (_res) \
1443 : /*in*/ "a" (&_argvec[0]) \
1444 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1446 lval = (__typeof__(lval)) _res; \
1449 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1450 arg7,arg8,arg9,arg10,arg11) \
1452 volatile OrigFn _orig = (orig); \
1453 volatile unsigned long _argvec[12]; \
1454 volatile unsigned long _res; \
1455 _argvec[0] = (unsigned long)_orig.nraddr; \
1456 _argvec[1] = (unsigned long)(arg1); \
1457 _argvec[2] = (unsigned long)(arg2); \
1458 _argvec[3] = (unsigned long)(arg3); \
1459 _argvec[4] = (unsigned long)(arg4); \
1460 _argvec[5] = (unsigned long)(arg5); \
1461 _argvec[6] = (unsigned long)(arg6); \
1462 _argvec[7] = (unsigned long)(arg7); \
1463 _argvec[8] = (unsigned long)(arg8); \
1464 _argvec[9] = (unsigned long)(arg9); \
1465 _argvec[10] = (unsigned long)(arg10); \
1466 _argvec[11] = (unsigned long)(arg11); \
1468 "subq $128,%%rsp\n\t" \
1469 "pushq 88(%%rax)\n\t" \
1470 "pushq 80(%%rax)\n\t" \
1471 "pushq 72(%%rax)\n\t" \
1472 "pushq 64(%%rax)\n\t" \
1473 "pushq 56(%%rax)\n\t" \
1474 "movq 48(%%rax), %%r9\n\t" \
1475 "movq 40(%%rax), %%r8\n\t" \
1476 "movq 32(%%rax), %%rcx\n\t" \
1477 "movq 24(%%rax), %%rdx\n\t" \
1478 "movq 16(%%rax), %%rsi\n\t" \
1479 "movq 8(%%rax), %%rdi\n\t" \
1480 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1481 VALGRIND_CALL_NOREDIR_RAX \
1482 "addq $40, %%rsp\n" \
1483 "addq $128,%%rsp\n\t" \
1484 : /*out*/ "=a" (_res) \
1485 : /*in*/ "a" (&_argvec[0]) \
1486 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1488 lval = (__typeof__(lval)) _res; \
1491 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1492 arg7,arg8,arg9,arg10,arg11,arg12) \
1494 volatile OrigFn _orig = (orig); \
1495 volatile unsigned long _argvec[13]; \
1496 volatile unsigned long _res; \
1497 _argvec[0] = (unsigned long)_orig.nraddr; \
1498 _argvec[1] = (unsigned long)(arg1); \
1499 _argvec[2] = (unsigned long)(arg2); \
1500 _argvec[3] = (unsigned long)(arg3); \
1501 _argvec[4] = (unsigned long)(arg4); \
1502 _argvec[5] = (unsigned long)(arg5); \
1503 _argvec[6] = (unsigned long)(arg6); \
1504 _argvec[7] = (unsigned long)(arg7); \
1505 _argvec[8] = (unsigned long)(arg8); \
1506 _argvec[9] = (unsigned long)(arg9); \
1507 _argvec[10] = (unsigned long)(arg10); \
1508 _argvec[11] = (unsigned long)(arg11); \
1509 _argvec[12] = (unsigned long)(arg12); \
1511 "subq $128,%%rsp\n\t" \
1512 "pushq 96(%%rax)\n\t" \
1513 "pushq 88(%%rax)\n\t" \
1514 "pushq 80(%%rax)\n\t" \
1515 "pushq 72(%%rax)\n\t" \
1516 "pushq 64(%%rax)\n\t" \
1517 "pushq 56(%%rax)\n\t" \
1518 "movq 48(%%rax), %%r9\n\t" \
1519 "movq 40(%%rax), %%r8\n\t" \
1520 "movq 32(%%rax), %%rcx\n\t" \
1521 "movq 24(%%rax), %%rdx\n\t" \
1522 "movq 16(%%rax), %%rsi\n\t" \
1523 "movq 8(%%rax), %%rdi\n\t" \
1524 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1525 VALGRIND_CALL_NOREDIR_RAX \
1526 "addq $48, %%rsp\n" \
1527 "addq $128,%%rsp\n\t" \
1528 : /*out*/ "=a" (_res) \
1529 : /*in*/ "a" (&_argvec[0]) \
1530 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1532 lval = (__typeof__(lval)) _res; \
1535 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
1537 /* ------------------------ ppc32-linux ------------------------ */
1539 #if defined(PLAT_ppc32_linux)
1541 /* This is useful for finding out about the on-stack stuff:
1543 extern int f9 ( int,int,int,int,int,int,int,int,int );
1544 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1545 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1546 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1549 return f9(11,22,33,44,55,66,77,88,99);
1552 return f10(11,22,33,44,55,66,77,88,99,110);
1555 return f11(11,22,33,44,55,66,77,88,99,110,121);
1558 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1562 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1564 /* These regs are trashed by the hidden call. */
1565 #define __CALLER_SAVED_REGS \
1566 "lr", "ctr", "xer", \
1567 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1568 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1571 /* These CALL_FN_ macros assume that on ppc32-linux,
1572 sizeof(unsigned long) == 4. */
1574 #define CALL_FN_W_v(lval, orig) \
1576 volatile OrigFn _orig = (orig); \
1577 volatile unsigned long _argvec[1]; \
1578 volatile unsigned long _res; \
1579 _argvec[0] = (unsigned long)_orig.nraddr; \
1582 "lwz 11,0(11)\n\t" /* target->r11 */ \
1583 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1585 : /*out*/ "=r" (_res) \
1586 : /*in*/ "r" (&_argvec[0]) \
1587 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1589 lval = (__typeof__(lval)) _res; \
1592 #define CALL_FN_W_W(lval, orig, arg1) \
1594 volatile OrigFn _orig = (orig); \
1595 volatile unsigned long _argvec[2]; \
1596 volatile unsigned long _res; \
1597 _argvec[0] = (unsigned long)_orig.nraddr; \
1598 _argvec[1] = (unsigned long)arg1; \
1601 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1602 "lwz 11,0(11)\n\t" /* target->r11 */ \
1603 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1605 : /*out*/ "=r" (_res) \
1606 : /*in*/ "r" (&_argvec[0]) \
1607 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1609 lval = (__typeof__(lval)) _res; \
1612 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1614 volatile OrigFn _orig = (orig); \
1615 volatile unsigned long _argvec[3]; \
1616 volatile unsigned long _res; \
1617 _argvec[0] = (unsigned long)_orig.nraddr; \
1618 _argvec[1] = (unsigned long)arg1; \
1619 _argvec[2] = (unsigned long)arg2; \
1622 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1624 "lwz 11,0(11)\n\t" /* target->r11 */ \
1625 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1627 : /*out*/ "=r" (_res) \
1628 : /*in*/ "r" (&_argvec[0]) \
1629 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1631 lval = (__typeof__(lval)) _res; \
1634 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1636 volatile OrigFn _orig = (orig); \
1637 volatile unsigned long _argvec[4]; \
1638 volatile unsigned long _res; \
1639 _argvec[0] = (unsigned long)_orig.nraddr; \
1640 _argvec[1] = (unsigned long)arg1; \
1641 _argvec[2] = (unsigned long)arg2; \
1642 _argvec[3] = (unsigned long)arg3; \
1645 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1647 "lwz 5,12(11)\n\t" \
1648 "lwz 11,0(11)\n\t" /* target->r11 */ \
1649 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1651 : /*out*/ "=r" (_res) \
1652 : /*in*/ "r" (&_argvec[0]) \
1653 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1655 lval = (__typeof__(lval)) _res; \
1658 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1660 volatile OrigFn _orig = (orig); \
1661 volatile unsigned long _argvec[5]; \
1662 volatile unsigned long _res; \
1663 _argvec[0] = (unsigned long)_orig.nraddr; \
1664 _argvec[1] = (unsigned long)arg1; \
1665 _argvec[2] = (unsigned long)arg2; \
1666 _argvec[3] = (unsigned long)arg3; \
1667 _argvec[4] = (unsigned long)arg4; \
1670 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1672 "lwz 5,12(11)\n\t" \
1673 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1674 "lwz 11,0(11)\n\t" /* target->r11 */ \
1675 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1677 : /*out*/ "=r" (_res) \
1678 : /*in*/ "r" (&_argvec[0]) \
1679 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1681 lval = (__typeof__(lval)) _res; \
1684 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1686 volatile OrigFn _orig = (orig); \
1687 volatile unsigned long _argvec[6]; \
1688 volatile unsigned long _res; \
1689 _argvec[0] = (unsigned long)_orig.nraddr; \
1690 _argvec[1] = (unsigned long)arg1; \
1691 _argvec[2] = (unsigned long)arg2; \
1692 _argvec[3] = (unsigned long)arg3; \
1693 _argvec[4] = (unsigned long)arg4; \
1694 _argvec[5] = (unsigned long)arg5; \
1697 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1699 "lwz 5,12(11)\n\t" \
1700 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1701 "lwz 7,20(11)\n\t" \
1702 "lwz 11,0(11)\n\t" /* target->r11 */ \
1703 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1705 : /*out*/ "=r" (_res) \
1706 : /*in*/ "r" (&_argvec[0]) \
1707 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1709 lval = (__typeof__(lval)) _res; \
1712 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1714 volatile OrigFn _orig = (orig); \
1715 volatile unsigned long _argvec[7]; \
1716 volatile unsigned long _res; \
1717 _argvec[0] = (unsigned long)_orig.nraddr; \
1718 _argvec[1] = (unsigned long)arg1; \
1719 _argvec[2] = (unsigned long)arg2; \
1720 _argvec[3] = (unsigned long)arg3; \
1721 _argvec[4] = (unsigned long)arg4; \
1722 _argvec[5] = (unsigned long)arg5; \
1723 _argvec[6] = (unsigned long)arg6; \
1726 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1728 "lwz 5,12(11)\n\t" \
1729 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1730 "lwz 7,20(11)\n\t" \
1731 "lwz 8,24(11)\n\t" \
1732 "lwz 11,0(11)\n\t" /* target->r11 */ \
1733 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1735 : /*out*/ "=r" (_res) \
1736 : /*in*/ "r" (&_argvec[0]) \
1737 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1739 lval = (__typeof__(lval)) _res; \
1742 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1745 volatile OrigFn _orig = (orig); \
1746 volatile unsigned long _argvec[8]; \
1747 volatile unsigned long _res; \
1748 _argvec[0] = (unsigned long)_orig.nraddr; \
1749 _argvec[1] = (unsigned long)arg1; \
1750 _argvec[2] = (unsigned long)arg2; \
1751 _argvec[3] = (unsigned long)arg3; \
1752 _argvec[4] = (unsigned long)arg4; \
1753 _argvec[5] = (unsigned long)arg5; \
1754 _argvec[6] = (unsigned long)arg6; \
1755 _argvec[7] = (unsigned long)arg7; \
1758 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1760 "lwz 5,12(11)\n\t" \
1761 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1762 "lwz 7,20(11)\n\t" \
1763 "lwz 8,24(11)\n\t" \
1764 "lwz 9,28(11)\n\t" \
1765 "lwz 11,0(11)\n\t" /* target->r11 */ \
1766 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1768 : /*out*/ "=r" (_res) \
1769 : /*in*/ "r" (&_argvec[0]) \
1770 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1772 lval = (__typeof__(lval)) _res; \
1775 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1778 volatile OrigFn _orig = (orig); \
1779 volatile unsigned long _argvec[9]; \
1780 volatile unsigned long _res; \
1781 _argvec[0] = (unsigned long)_orig.nraddr; \
1782 _argvec[1] = (unsigned long)arg1; \
1783 _argvec[2] = (unsigned long)arg2; \
1784 _argvec[3] = (unsigned long)arg3; \
1785 _argvec[4] = (unsigned long)arg4; \
1786 _argvec[5] = (unsigned long)arg5; \
1787 _argvec[6] = (unsigned long)arg6; \
1788 _argvec[7] = (unsigned long)arg7; \
1789 _argvec[8] = (unsigned long)arg8; \
1792 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1794 "lwz 5,12(11)\n\t" \
1795 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1796 "lwz 7,20(11)\n\t" \
1797 "lwz 8,24(11)\n\t" \
1798 "lwz 9,28(11)\n\t" \
1799 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1800 "lwz 11,0(11)\n\t" /* target->r11 */ \
1801 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1803 : /*out*/ "=r" (_res) \
1804 : /*in*/ "r" (&_argvec[0]) \
1805 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1807 lval = (__typeof__(lval)) _res; \
1810 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1813 volatile OrigFn _orig = (orig); \
1814 volatile unsigned long _argvec[10]; \
1815 volatile unsigned long _res; \
1816 _argvec[0] = (unsigned long)_orig.nraddr; \
1817 _argvec[1] = (unsigned long)arg1; \
1818 _argvec[2] = (unsigned long)arg2; \
1819 _argvec[3] = (unsigned long)arg3; \
1820 _argvec[4] = (unsigned long)arg4; \
1821 _argvec[5] = (unsigned long)arg5; \
1822 _argvec[6] = (unsigned long)arg6; \
1823 _argvec[7] = (unsigned long)arg7; \
1824 _argvec[8] = (unsigned long)arg8; \
1825 _argvec[9] = (unsigned long)arg9; \
1828 "addi 1,1,-16\n\t" \
1830 "lwz 3,36(11)\n\t" \
1833 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1835 "lwz 5,12(11)\n\t" \
1836 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1837 "lwz 7,20(11)\n\t" \
1838 "lwz 8,24(11)\n\t" \
1839 "lwz 9,28(11)\n\t" \
1840 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1841 "lwz 11,0(11)\n\t" /* target->r11 */ \
1842 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1845 : /*out*/ "=r" (_res) \
1846 : /*in*/ "r" (&_argvec[0]) \
1847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1849 lval = (__typeof__(lval)) _res; \
1852 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1853 arg7,arg8,arg9,arg10) \
1855 volatile OrigFn _orig = (orig); \
1856 volatile unsigned long _argvec[11]; \
1857 volatile unsigned long _res; \
1858 _argvec[0] = (unsigned long)_orig.nraddr; \
1859 _argvec[1] = (unsigned long)arg1; \
1860 _argvec[2] = (unsigned long)arg2; \
1861 _argvec[3] = (unsigned long)arg3; \
1862 _argvec[4] = (unsigned long)arg4; \
1863 _argvec[5] = (unsigned long)arg5; \
1864 _argvec[6] = (unsigned long)arg6; \
1865 _argvec[7] = (unsigned long)arg7; \
1866 _argvec[8] = (unsigned long)arg8; \
1867 _argvec[9] = (unsigned long)arg9; \
1868 _argvec[10] = (unsigned long)arg10; \
1871 "addi 1,1,-16\n\t" \
1873 "lwz 3,40(11)\n\t" \
1876 "lwz 3,36(11)\n\t" \
1879 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1881 "lwz 5,12(11)\n\t" \
1882 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1883 "lwz 7,20(11)\n\t" \
1884 "lwz 8,24(11)\n\t" \
1885 "lwz 9,28(11)\n\t" \
1886 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1887 "lwz 11,0(11)\n\t" /* target->r11 */ \
1888 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1891 : /*out*/ "=r" (_res) \
1892 : /*in*/ "r" (&_argvec[0]) \
1893 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1895 lval = (__typeof__(lval)) _res; \
1898 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1899 arg7,arg8,arg9,arg10,arg11) \
1901 volatile OrigFn _orig = (orig); \
1902 volatile unsigned long _argvec[12]; \
1903 volatile unsigned long _res; \
1904 _argvec[0] = (unsigned long)_orig.nraddr; \
1905 _argvec[1] = (unsigned long)arg1; \
1906 _argvec[2] = (unsigned long)arg2; \
1907 _argvec[3] = (unsigned long)arg3; \
1908 _argvec[4] = (unsigned long)arg4; \
1909 _argvec[5] = (unsigned long)arg5; \
1910 _argvec[6] = (unsigned long)arg6; \
1911 _argvec[7] = (unsigned long)arg7; \
1912 _argvec[8] = (unsigned long)arg8; \
1913 _argvec[9] = (unsigned long)arg9; \
1914 _argvec[10] = (unsigned long)arg10; \
1915 _argvec[11] = (unsigned long)arg11; \
1918 "addi 1,1,-32\n\t" \
1920 "lwz 3,44(11)\n\t" \
1923 "lwz 3,40(11)\n\t" \
1926 "lwz 3,36(11)\n\t" \
1929 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1931 "lwz 5,12(11)\n\t" \
1932 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1933 "lwz 7,20(11)\n\t" \
1934 "lwz 8,24(11)\n\t" \
1935 "lwz 9,28(11)\n\t" \
1936 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1937 "lwz 11,0(11)\n\t" /* target->r11 */ \
1938 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1941 : /*out*/ "=r" (_res) \
1942 : /*in*/ "r" (&_argvec[0]) \
1943 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1945 lval = (__typeof__(lval)) _res; \
1948 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1949 arg7,arg8,arg9,arg10,arg11,arg12) \
1951 volatile OrigFn _orig = (orig); \
1952 volatile unsigned long _argvec[13]; \
1953 volatile unsigned long _res; \
1954 _argvec[0] = (unsigned long)_orig.nraddr; \
1955 _argvec[1] = (unsigned long)arg1; \
1956 _argvec[2] = (unsigned long)arg2; \
1957 _argvec[3] = (unsigned long)arg3; \
1958 _argvec[4] = (unsigned long)arg4; \
1959 _argvec[5] = (unsigned long)arg5; \
1960 _argvec[6] = (unsigned long)arg6; \
1961 _argvec[7] = (unsigned long)arg7; \
1962 _argvec[8] = (unsigned long)arg8; \
1963 _argvec[9] = (unsigned long)arg9; \
1964 _argvec[10] = (unsigned long)arg10; \
1965 _argvec[11] = (unsigned long)arg11; \
1966 _argvec[12] = (unsigned long)arg12; \
1969 "addi 1,1,-32\n\t" \
1971 "lwz 3,48(11)\n\t" \
1974 "lwz 3,44(11)\n\t" \
1977 "lwz 3,40(11)\n\t" \
1980 "lwz 3,36(11)\n\t" \
1983 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1985 "lwz 5,12(11)\n\t" \
1986 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1987 "lwz 7,20(11)\n\t" \
1988 "lwz 8,24(11)\n\t" \
1989 "lwz 9,28(11)\n\t" \
1990 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1991 "lwz 11,0(11)\n\t" /* target->r11 */ \
1992 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1995 : /*out*/ "=r" (_res) \
1996 : /*in*/ "r" (&_argvec[0]) \
1997 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1999 lval = (__typeof__(lval)) _res; \
2002 #endif /* PLAT_ppc32_linux */
2004 /* ------------------------ ppc64-linux ------------------------ */
2006 #if defined(PLAT_ppc64_linux)
2008 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2010 /* These regs are trashed by the hidden call. */
2011 #define __CALLER_SAVED_REGS \
2012 "lr", "ctr", "xer", \
2013 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2014 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2017 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2020 #define CALL_FN_W_v(lval, orig) \
2022 volatile OrigFn _orig = (orig); \
2023 volatile unsigned long _argvec[3+0]; \
2024 volatile unsigned long _res; \
2025 /* _argvec[0] holds current r2 across the call */ \
2026 _argvec[1] = (unsigned long)_orig.r2; \
2027 _argvec[2] = (unsigned long)_orig.nraddr; \
2030 "std 2,-16(11)\n\t" /* save tocptr */ \
2031 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2032 "ld 11, 0(11)\n\t" /* target->r11 */ \
2033 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2036 "ld 2,-16(11)" /* restore tocptr */ \
2037 : /*out*/ "=r" (_res) \
2038 : /*in*/ "r" (&_argvec[2]) \
2039 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2041 lval = (__typeof__(lval)) _res; \
2044 #define CALL_FN_W_W(lval, orig, arg1) \
2046 volatile OrigFn _orig = (orig); \
2047 volatile unsigned long _argvec[3+1]; \
2048 volatile unsigned long _res; \
2049 /* _argvec[0] holds current r2 across the call */ \
2050 _argvec[1] = (unsigned long)_orig.r2; \
2051 _argvec[2] = (unsigned long)_orig.nraddr; \
2052 _argvec[2+1] = (unsigned long)arg1; \
2055 "std 2,-16(11)\n\t" /* save tocptr */ \
2056 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2057 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2058 "ld 11, 0(11)\n\t" /* target->r11 */ \
2059 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2062 "ld 2,-16(11)" /* restore tocptr */ \
2063 : /*out*/ "=r" (_res) \
2064 : /*in*/ "r" (&_argvec[2]) \
2065 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2067 lval = (__typeof__(lval)) _res; \
2070 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2072 volatile OrigFn _orig = (orig); \
2073 volatile unsigned long _argvec[3+2]; \
2074 volatile unsigned long _res; \
2075 /* _argvec[0] holds current r2 across the call */ \
2076 _argvec[1] = (unsigned long)_orig.r2; \
2077 _argvec[2] = (unsigned long)_orig.nraddr; \
2078 _argvec[2+1] = (unsigned long)arg1; \
2079 _argvec[2+2] = (unsigned long)arg2; \
2082 "std 2,-16(11)\n\t" /* save tocptr */ \
2083 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2084 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2085 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2086 "ld 11, 0(11)\n\t" /* target->r11 */ \
2087 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2090 "ld 2,-16(11)" /* restore tocptr */ \
2091 : /*out*/ "=r" (_res) \
2092 : /*in*/ "r" (&_argvec[2]) \
2093 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2095 lval = (__typeof__(lval)) _res; \
2098 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2100 volatile OrigFn _orig = (orig); \
2101 volatile unsigned long _argvec[3+3]; \
2102 volatile unsigned long _res; \
2103 /* _argvec[0] holds current r2 across the call */ \
2104 _argvec[1] = (unsigned long)_orig.r2; \
2105 _argvec[2] = (unsigned long)_orig.nraddr; \
2106 _argvec[2+1] = (unsigned long)arg1; \
2107 _argvec[2+2] = (unsigned long)arg2; \
2108 _argvec[2+3] = (unsigned long)arg3; \
2111 "std 2,-16(11)\n\t" /* save tocptr */ \
2112 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2113 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2114 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2115 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2116 "ld 11, 0(11)\n\t" /* target->r11 */ \
2117 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2120 "ld 2,-16(11)" /* restore tocptr */ \
2121 : /*out*/ "=r" (_res) \
2122 : /*in*/ "r" (&_argvec[2]) \
2123 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2125 lval = (__typeof__(lval)) _res; \
2128 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2130 volatile OrigFn _orig = (orig); \
2131 volatile unsigned long _argvec[3+4]; \
2132 volatile unsigned long _res; \
2133 /* _argvec[0] holds current r2 across the call */ \
2134 _argvec[1] = (unsigned long)_orig.r2; \
2135 _argvec[2] = (unsigned long)_orig.nraddr; \
2136 _argvec[2+1] = (unsigned long)arg1; \
2137 _argvec[2+2] = (unsigned long)arg2; \
2138 _argvec[2+3] = (unsigned long)arg3; \
2139 _argvec[2+4] = (unsigned long)arg4; \
2142 "std 2,-16(11)\n\t" /* save tocptr */ \
2143 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2144 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2145 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2146 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2147 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2148 "ld 11, 0(11)\n\t" /* target->r11 */ \
2149 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2152 "ld 2,-16(11)" /* restore tocptr */ \
2153 : /*out*/ "=r" (_res) \
2154 : /*in*/ "r" (&_argvec[2]) \
2155 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2157 lval = (__typeof__(lval)) _res; \
2160 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2162 volatile OrigFn _orig = (orig); \
2163 volatile unsigned long _argvec[3+5]; \
2164 volatile unsigned long _res; \
2165 /* _argvec[0] holds current r2 across the call */ \
2166 _argvec[1] = (unsigned long)_orig.r2; \
2167 _argvec[2] = (unsigned long)_orig.nraddr; \
2168 _argvec[2+1] = (unsigned long)arg1; \
2169 _argvec[2+2] = (unsigned long)arg2; \
2170 _argvec[2+3] = (unsigned long)arg3; \
2171 _argvec[2+4] = (unsigned long)arg4; \
2172 _argvec[2+5] = (unsigned long)arg5; \
2175 "std 2,-16(11)\n\t" /* save tocptr */ \
2176 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2177 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2178 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2179 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2180 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2181 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2182 "ld 11, 0(11)\n\t" /* target->r11 */ \
2183 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2186 "ld 2,-16(11)" /* restore tocptr */ \
2187 : /*out*/ "=r" (_res) \
2188 : /*in*/ "r" (&_argvec[2]) \
2189 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2191 lval = (__typeof__(lval)) _res; \
2194 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2196 volatile OrigFn _orig = (orig); \
2197 volatile unsigned long _argvec[3+6]; \
2198 volatile unsigned long _res; \
2199 /* _argvec[0] holds current r2 across the call */ \
2200 _argvec[1] = (unsigned long)_orig.r2; \
2201 _argvec[2] = (unsigned long)_orig.nraddr; \
2202 _argvec[2+1] = (unsigned long)arg1; \
2203 _argvec[2+2] = (unsigned long)arg2; \
2204 _argvec[2+3] = (unsigned long)arg3; \
2205 _argvec[2+4] = (unsigned long)arg4; \
2206 _argvec[2+5] = (unsigned long)arg5; \
2207 _argvec[2+6] = (unsigned long)arg6; \
2210 "std 2,-16(11)\n\t" /* save tocptr */ \
2211 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2212 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2213 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2214 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2215 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2216 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2217 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2218 "ld 11, 0(11)\n\t" /* target->r11 */ \
2219 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2222 "ld 2,-16(11)" /* restore tocptr */ \
2223 : /*out*/ "=r" (_res) \
2224 : /*in*/ "r" (&_argvec[2]) \
2225 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2227 lval = (__typeof__(lval)) _res; \
2230 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2233 volatile OrigFn _orig = (orig); \
2234 volatile unsigned long _argvec[3+7]; \
2235 volatile unsigned long _res; \
2236 /* _argvec[0] holds current r2 across the call */ \
2237 _argvec[1] = (unsigned long)_orig.r2; \
2238 _argvec[2] = (unsigned long)_orig.nraddr; \
2239 _argvec[2+1] = (unsigned long)arg1; \
2240 _argvec[2+2] = (unsigned long)arg2; \
2241 _argvec[2+3] = (unsigned long)arg3; \
2242 _argvec[2+4] = (unsigned long)arg4; \
2243 _argvec[2+5] = (unsigned long)arg5; \
2244 _argvec[2+6] = (unsigned long)arg6; \
2245 _argvec[2+7] = (unsigned long)arg7; \
2248 "std 2,-16(11)\n\t" /* save tocptr */ \
2249 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2250 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2251 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2252 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2253 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2254 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2255 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2256 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2257 "ld 11, 0(11)\n\t" /* target->r11 */ \
2258 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2261 "ld 2,-16(11)" /* restore tocptr */ \
2262 : /*out*/ "=r" (_res) \
2263 : /*in*/ "r" (&_argvec[2]) \
2264 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2266 lval = (__typeof__(lval)) _res; \
2269 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2272 volatile OrigFn _orig = (orig); \
2273 volatile unsigned long _argvec[3+8]; \
2274 volatile unsigned long _res; \
2275 /* _argvec[0] holds current r2 across the call */ \
2276 _argvec[1] = (unsigned long)_orig.r2; \
2277 _argvec[2] = (unsigned long)_orig.nraddr; \
2278 _argvec[2+1] = (unsigned long)arg1; \
2279 _argvec[2+2] = (unsigned long)arg2; \
2280 _argvec[2+3] = (unsigned long)arg3; \
2281 _argvec[2+4] = (unsigned long)arg4; \
2282 _argvec[2+5] = (unsigned long)arg5; \
2283 _argvec[2+6] = (unsigned long)arg6; \
2284 _argvec[2+7] = (unsigned long)arg7; \
2285 _argvec[2+8] = (unsigned long)arg8; \
2288 "std 2,-16(11)\n\t" /* save tocptr */ \
2289 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2290 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2291 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2292 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2293 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2294 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2295 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2296 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2297 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2298 "ld 11, 0(11)\n\t" /* target->r11 */ \
2299 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2302 "ld 2,-16(11)" /* restore tocptr */ \
2303 : /*out*/ "=r" (_res) \
2304 : /*in*/ "r" (&_argvec[2]) \
2305 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2307 lval = (__typeof__(lval)) _res; \
2310 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2313 volatile OrigFn _orig = (orig); \
2314 volatile unsigned long _argvec[3+9]; \
2315 volatile unsigned long _res; \
2316 /* _argvec[0] holds current r2 across the call */ \
2317 _argvec[1] = (unsigned long)_orig.r2; \
2318 _argvec[2] = (unsigned long)_orig.nraddr; \
2319 _argvec[2+1] = (unsigned long)arg1; \
2320 _argvec[2+2] = (unsigned long)arg2; \
2321 _argvec[2+3] = (unsigned long)arg3; \
2322 _argvec[2+4] = (unsigned long)arg4; \
2323 _argvec[2+5] = (unsigned long)arg5; \
2324 _argvec[2+6] = (unsigned long)arg6; \
2325 _argvec[2+7] = (unsigned long)arg7; \
2326 _argvec[2+8] = (unsigned long)arg8; \
2327 _argvec[2+9] = (unsigned long)arg9; \
2330 "std 2,-16(11)\n\t" /* save tocptr */ \
2331 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2332 "addi 1,1,-128\n\t" /* expand stack frame */ \
2335 "std 3,112(1)\n\t" \
2337 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2338 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2339 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2340 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2341 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2342 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2343 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2344 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2345 "ld 11, 0(11)\n\t" /* target->r11 */ \
2346 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2349 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2350 "addi 1,1,128" /* restore frame */ \
2351 : /*out*/ "=r" (_res) \
2352 : /*in*/ "r" (&_argvec[2]) \
2353 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2355 lval = (__typeof__(lval)) _res; \
2358 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2359 arg7,arg8,arg9,arg10) \
2361 volatile OrigFn _orig = (orig); \
2362 volatile unsigned long _argvec[3+10]; \
2363 volatile unsigned long _res; \
2364 /* _argvec[0] holds current r2 across the call */ \
2365 _argvec[1] = (unsigned long)_orig.r2; \
2366 _argvec[2] = (unsigned long)_orig.nraddr; \
2367 _argvec[2+1] = (unsigned long)arg1; \
2368 _argvec[2+2] = (unsigned long)arg2; \
2369 _argvec[2+3] = (unsigned long)arg3; \
2370 _argvec[2+4] = (unsigned long)arg4; \
2371 _argvec[2+5] = (unsigned long)arg5; \
2372 _argvec[2+6] = (unsigned long)arg6; \
2373 _argvec[2+7] = (unsigned long)arg7; \
2374 _argvec[2+8] = (unsigned long)arg8; \
2375 _argvec[2+9] = (unsigned long)arg9; \
2376 _argvec[2+10] = (unsigned long)arg10; \
2379 "std 2,-16(11)\n\t" /* save tocptr */ \
2380 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2381 "addi 1,1,-128\n\t" /* expand stack frame */ \
2384 "std 3,120(1)\n\t" \
2387 "std 3,112(1)\n\t" \
2389 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2390 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2391 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2392 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2393 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2394 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2395 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2396 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2397 "ld 11, 0(11)\n\t" /* target->r11 */ \
2398 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2401 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2402 "addi 1,1,128" /* restore frame */ \
2403 : /*out*/ "=r" (_res) \
2404 : /*in*/ "r" (&_argvec[2]) \
2405 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2407 lval = (__typeof__(lval)) _res; \
2410 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2411 arg7,arg8,arg9,arg10,arg11) \
2413 volatile OrigFn _orig = (orig); \
2414 volatile unsigned long _argvec[3+11]; \
2415 volatile unsigned long _res; \
2416 /* _argvec[0] holds current r2 across the call */ \
2417 _argvec[1] = (unsigned long)_orig.r2; \
2418 _argvec[2] = (unsigned long)_orig.nraddr; \
2419 _argvec[2+1] = (unsigned long)arg1; \
2420 _argvec[2+2] = (unsigned long)arg2; \
2421 _argvec[2+3] = (unsigned long)arg3; \
2422 _argvec[2+4] = (unsigned long)arg4; \
2423 _argvec[2+5] = (unsigned long)arg5; \
2424 _argvec[2+6] = (unsigned long)arg6; \
2425 _argvec[2+7] = (unsigned long)arg7; \
2426 _argvec[2+8] = (unsigned long)arg8; \
2427 _argvec[2+9] = (unsigned long)arg9; \
2428 _argvec[2+10] = (unsigned long)arg10; \
2429 _argvec[2+11] = (unsigned long)arg11; \
2432 "std 2,-16(11)\n\t" /* save tocptr */ \
2433 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2434 "addi 1,1,-144\n\t" /* expand stack frame */ \
2437 "std 3,128(1)\n\t" \
2440 "std 3,120(1)\n\t" \
2443 "std 3,112(1)\n\t" \
2445 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2446 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2447 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2448 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2449 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2450 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2451 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2452 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2453 "ld 11, 0(11)\n\t" /* target->r11 */ \
2454 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2457 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2458 "addi 1,1,144" /* restore frame */ \
2459 : /*out*/ "=r" (_res) \
2460 : /*in*/ "r" (&_argvec[2]) \
2461 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2463 lval = (__typeof__(lval)) _res; \
2466 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2467 arg7,arg8,arg9,arg10,arg11,arg12) \
2469 volatile OrigFn _orig = (orig); \
2470 volatile unsigned long _argvec[3+12]; \
2471 volatile unsigned long _res; \
2472 /* _argvec[0] holds current r2 across the call */ \
2473 _argvec[1] = (unsigned long)_orig.r2; \
2474 _argvec[2] = (unsigned long)_orig.nraddr; \
2475 _argvec[2+1] = (unsigned long)arg1; \
2476 _argvec[2+2] = (unsigned long)arg2; \
2477 _argvec[2+3] = (unsigned long)arg3; \
2478 _argvec[2+4] = (unsigned long)arg4; \
2479 _argvec[2+5] = (unsigned long)arg5; \
2480 _argvec[2+6] = (unsigned long)arg6; \
2481 _argvec[2+7] = (unsigned long)arg7; \
2482 _argvec[2+8] = (unsigned long)arg8; \
2483 _argvec[2+9] = (unsigned long)arg9; \
2484 _argvec[2+10] = (unsigned long)arg10; \
2485 _argvec[2+11] = (unsigned long)arg11; \
2486 _argvec[2+12] = (unsigned long)arg12; \
2489 "std 2,-16(11)\n\t" /* save tocptr */ \
2490 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2491 "addi 1,1,-144\n\t" /* expand stack frame */ \
2494 "std 3,136(1)\n\t" \
2497 "std 3,128(1)\n\t" \
2500 "std 3,120(1)\n\t" \
2503 "std 3,112(1)\n\t" \
2505 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2506 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2507 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2508 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2509 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2510 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2511 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2512 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2513 "ld 11, 0(11)\n\t" /* target->r11 */ \
2514 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2517 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2518 "addi 1,1,144" /* restore frame */ \
2519 : /*out*/ "=r" (_res) \
2520 : /*in*/ "r" (&_argvec[2]) \
2521 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2523 lval = (__typeof__(lval)) _res; \
2526 #endif /* PLAT_ppc64_linux */
2528 /* ------------------------- arm-linux ------------------------- */
2530 #if defined(PLAT_arm_linux)
2532 /* These regs are trashed by the hidden call. */
2533 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2535 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2538 #define CALL_FN_W_v(lval, orig) \
2540 volatile OrigFn _orig = (orig); \
2541 volatile unsigned long _argvec[1]; \
2542 volatile unsigned long _res; \
2543 _argvec[0] = (unsigned long)_orig.nraddr; \
2545 "ldr r4, [%1] \n\t" /* target->r4 */ \
2546 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2548 : /*out*/ "=r" (_res) \
2549 : /*in*/ "0" (&_argvec[0]) \
2550 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2552 lval = (__typeof__(lval)) _res; \
2555 #define CALL_FN_W_W(lval, orig, arg1) \
2557 volatile OrigFn _orig = (orig); \
2558 volatile unsigned long _argvec[2]; \
2559 volatile unsigned long _res; \
2560 _argvec[0] = (unsigned long)_orig.nraddr; \
2561 _argvec[1] = (unsigned long)(arg1); \
2563 "ldr r0, [%1, #4] \n\t" \
2564 "ldr r4, [%1] \n\t" /* target->r4 */ \
2565 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2567 : /*out*/ "=r" (_res) \
2568 : /*in*/ "0" (&_argvec[0]) \
2569 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2571 lval = (__typeof__(lval)) _res; \
2574 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2576 volatile OrigFn _orig = (orig); \
2577 volatile unsigned long _argvec[3]; \
2578 volatile unsigned long _res; \
2579 _argvec[0] = (unsigned long)_orig.nraddr; \
2580 _argvec[1] = (unsigned long)(arg1); \
2581 _argvec[2] = (unsigned long)(arg2); \
2583 "ldr r0, [%1, #4] \n\t" \
2584 "ldr r1, [%1, #8] \n\t" \
2585 "ldr r4, [%1] \n\t" /* target->r4 */ \
2586 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2588 : /*out*/ "=r" (_res) \
2589 : /*in*/ "0" (&_argvec[0]) \
2590 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2592 lval = (__typeof__(lval)) _res; \
2595 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2597 volatile OrigFn _orig = (orig); \
2598 volatile unsigned long _argvec[4]; \
2599 volatile unsigned long _res; \
2600 _argvec[0] = (unsigned long)_orig.nraddr; \
2601 _argvec[1] = (unsigned long)(arg1); \
2602 _argvec[2] = (unsigned long)(arg2); \
2603 _argvec[3] = (unsigned long)(arg3); \
2605 "ldr r0, [%1, #4] \n\t" \
2606 "ldr r1, [%1, #8] \n\t" \
2607 "ldr r2, [%1, #12] \n\t" \
2608 "ldr r4, [%1] \n\t" /* target->r4 */ \
2609 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2611 : /*out*/ "=r" (_res) \
2612 : /*in*/ "0" (&_argvec[0]) \
2613 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2615 lval = (__typeof__(lval)) _res; \
2618 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2620 volatile OrigFn _orig = (orig); \
2621 volatile unsigned long _argvec[5]; \
2622 volatile unsigned long _res; \
2623 _argvec[0] = (unsigned long)_orig.nraddr; \
2624 _argvec[1] = (unsigned long)(arg1); \
2625 _argvec[2] = (unsigned long)(arg2); \
2626 _argvec[3] = (unsigned long)(arg3); \
2627 _argvec[4] = (unsigned long)(arg4); \
2629 "ldr r0, [%1, #4] \n\t" \
2630 "ldr r1, [%1, #8] \n\t" \
2631 "ldr r2, [%1, #12] \n\t" \
2632 "ldr r3, [%1, #16] \n\t" \
2633 "ldr r4, [%1] \n\t" /* target->r4 */ \
2634 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2636 : /*out*/ "=r" (_res) \
2637 : /*in*/ "0" (&_argvec[0]) \
2638 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2640 lval = (__typeof__(lval)) _res; \
2643 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2645 volatile OrigFn _orig = (orig); \
2646 volatile unsigned long _argvec[6]; \
2647 volatile unsigned long _res; \
2648 _argvec[0] = (unsigned long)_orig.nraddr; \
2649 _argvec[1] = (unsigned long)(arg1); \
2650 _argvec[2] = (unsigned long)(arg2); \
2651 _argvec[3] = (unsigned long)(arg3); \
2652 _argvec[4] = (unsigned long)(arg4); \
2653 _argvec[5] = (unsigned long)(arg5); \
2655 "ldr r0, [%1, #20] \n\t" \
2657 "ldr r0, [%1, #4] \n\t" \
2658 "ldr r1, [%1, #8] \n\t" \
2659 "ldr r2, [%1, #12] \n\t" \
2660 "ldr r3, [%1, #16] \n\t" \
2661 "ldr r4, [%1] \n\t" /* target->r4 */ \
2662 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2663 "add sp, sp, #4 \n\t" \
2665 : /*out*/ "=r" (_res) \
2666 : /*in*/ "0" (&_argvec[0]) \
2667 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2669 lval = (__typeof__(lval)) _res; \
2672 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2674 volatile OrigFn _orig = (orig); \
2675 volatile unsigned long _argvec[7]; \
2676 volatile unsigned long _res; \
2677 _argvec[0] = (unsigned long)_orig.nraddr; \
2678 _argvec[1] = (unsigned long)(arg1); \
2679 _argvec[2] = (unsigned long)(arg2); \
2680 _argvec[3] = (unsigned long)(arg3); \
2681 _argvec[4] = (unsigned long)(arg4); \
2682 _argvec[5] = (unsigned long)(arg5); \
2683 _argvec[6] = (unsigned long)(arg6); \
2685 "ldr r0, [%1, #20] \n\t" \
2686 "ldr r1, [%1, #24] \n\t" \
2687 "push {r0, r1} \n\t" \
2688 "ldr r0, [%1, #4] \n\t" \
2689 "ldr r1, [%1, #8] \n\t" \
2690 "ldr r2, [%1, #12] \n\t" \
2691 "ldr r3, [%1, #16] \n\t" \
2692 "ldr r4, [%1] \n\t" /* target->r4 */ \
2693 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2694 "add sp, sp, #8 \n\t" \
2696 : /*out*/ "=r" (_res) \
2697 : /*in*/ "0" (&_argvec[0]) \
2698 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2700 lval = (__typeof__(lval)) _res; \
2703 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2706 volatile OrigFn _orig = (orig); \
2707 volatile unsigned long _argvec[8]; \
2708 volatile unsigned long _res; \
2709 _argvec[0] = (unsigned long)_orig.nraddr; \
2710 _argvec[1] = (unsigned long)(arg1); \
2711 _argvec[2] = (unsigned long)(arg2); \
2712 _argvec[3] = (unsigned long)(arg3); \
2713 _argvec[4] = (unsigned long)(arg4); \
2714 _argvec[5] = (unsigned long)(arg5); \
2715 _argvec[6] = (unsigned long)(arg6); \
2716 _argvec[7] = (unsigned long)(arg7); \
2718 "ldr r0, [%1, #20] \n\t" \
2719 "ldr r1, [%1, #24] \n\t" \
2720 "ldr r2, [%1, #28] \n\t" \
2721 "push {r0, r1, r2} \n\t" \
2722 "ldr r0, [%1, #4] \n\t" \
2723 "ldr r1, [%1, #8] \n\t" \
2724 "ldr r2, [%1, #12] \n\t" \
2725 "ldr r3, [%1, #16] \n\t" \
2726 "ldr r4, [%1] \n\t" /* target->r4 */ \
2727 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2728 "add sp, sp, #12 \n\t" \
2730 : /*out*/ "=r" (_res) \
2731 : /*in*/ "0" (&_argvec[0]) \
2732 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2734 lval = (__typeof__(lval)) _res; \
2737 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2740 volatile OrigFn _orig = (orig); \
2741 volatile unsigned long _argvec[9]; \
2742 volatile unsigned long _res; \
2743 _argvec[0] = (unsigned long)_orig.nraddr; \
2744 _argvec[1] = (unsigned long)(arg1); \
2745 _argvec[2] = (unsigned long)(arg2); \
2746 _argvec[3] = (unsigned long)(arg3); \
2747 _argvec[4] = (unsigned long)(arg4); \
2748 _argvec[5] = (unsigned long)(arg5); \
2749 _argvec[6] = (unsigned long)(arg6); \
2750 _argvec[7] = (unsigned long)(arg7); \
2751 _argvec[8] = (unsigned long)(arg8); \
2753 "ldr r0, [%1, #20] \n\t" \
2754 "ldr r1, [%1, #24] \n\t" \
2755 "ldr r2, [%1, #28] \n\t" \
2756 "ldr r3, [%1, #32] \n\t" \
2757 "push {r0, r1, r2, r3} \n\t" \
2758 "ldr r0, [%1, #4] \n\t" \
2759 "ldr r1, [%1, #8] \n\t" \
2760 "ldr r2, [%1, #12] \n\t" \
2761 "ldr r3, [%1, #16] \n\t" \
2762 "ldr r4, [%1] \n\t" /* target->r4 */ \
2763 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2764 "add sp, sp, #16 \n\t" \
2766 : /*out*/ "=r" (_res) \
2767 : /*in*/ "0" (&_argvec[0]) \
2768 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2770 lval = (__typeof__(lval)) _res; \
2773 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2776 volatile OrigFn _orig = (orig); \
2777 volatile unsigned long _argvec[10]; \
2778 volatile unsigned long _res; \
2779 _argvec[0] = (unsigned long)_orig.nraddr; \
2780 _argvec[1] = (unsigned long)(arg1); \
2781 _argvec[2] = (unsigned long)(arg2); \
2782 _argvec[3] = (unsigned long)(arg3); \
2783 _argvec[4] = (unsigned long)(arg4); \
2784 _argvec[5] = (unsigned long)(arg5); \
2785 _argvec[6] = (unsigned long)(arg6); \
2786 _argvec[7] = (unsigned long)(arg7); \
2787 _argvec[8] = (unsigned long)(arg8); \
2788 _argvec[9] = (unsigned long)(arg9); \
2790 "ldr r0, [%1, #20] \n\t" \
2791 "ldr r1, [%1, #24] \n\t" \
2792 "ldr r2, [%1, #28] \n\t" \
2793 "ldr r3, [%1, #32] \n\t" \
2794 "ldr r4, [%1, #36] \n\t" \
2795 "push {r0, r1, r2, r3, r4} \n\t" \
2796 "ldr r0, [%1, #4] \n\t" \
2797 "ldr r1, [%1, #8] \n\t" \
2798 "ldr r2, [%1, #12] \n\t" \
2799 "ldr r3, [%1, #16] \n\t" \
2800 "ldr r4, [%1] \n\t" /* target->r4 */ \
2801 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2802 "add sp, sp, #20 \n\t" \
2804 : /*out*/ "=r" (_res) \
2805 : /*in*/ "0" (&_argvec[0]) \
2806 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2808 lval = (__typeof__(lval)) _res; \
2811 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2812 arg7,arg8,arg9,arg10) \
2814 volatile OrigFn _orig = (orig); \
2815 volatile unsigned long _argvec[11]; \
2816 volatile unsigned long _res; \
2817 _argvec[0] = (unsigned long)_orig.nraddr; \
2818 _argvec[1] = (unsigned long)(arg1); \
2819 _argvec[2] = (unsigned long)(arg2); \
2820 _argvec[3] = (unsigned long)(arg3); \
2821 _argvec[4] = (unsigned long)(arg4); \
2822 _argvec[5] = (unsigned long)(arg5); \
2823 _argvec[6] = (unsigned long)(arg6); \
2824 _argvec[7] = (unsigned long)(arg7); \
2825 _argvec[8] = (unsigned long)(arg8); \
2826 _argvec[9] = (unsigned long)(arg9); \
2827 _argvec[10] = (unsigned long)(arg10); \
2829 "ldr r0, [%1, #40] \n\t" \
2831 "ldr r0, [%1, #20] \n\t" \
2832 "ldr r1, [%1, #24] \n\t" \
2833 "ldr r2, [%1, #28] \n\t" \
2834 "ldr r3, [%1, #32] \n\t" \
2835 "ldr r4, [%1, #36] \n\t" \
2836 "push {r0, r1, r2, r3, r4} \n\t" \
2837 "ldr r0, [%1, #4] \n\t" \
2838 "ldr r1, [%1, #8] \n\t" \
2839 "ldr r2, [%1, #12] \n\t" \
2840 "ldr r3, [%1, #16] \n\t" \
2841 "ldr r4, [%1] \n\t" /* target->r4 */ \
2842 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2843 "add sp, sp, #24 \n\t" \
2845 : /*out*/ "=r" (_res) \
2846 : /*in*/ "0" (&_argvec[0]) \
2847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2849 lval = (__typeof__(lval)) _res; \
2852 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2853 arg6,arg7,arg8,arg9,arg10, \
2856 volatile OrigFn _orig = (orig); \
2857 volatile unsigned long _argvec[12]; \
2858 volatile unsigned long _res; \
2859 _argvec[0] = (unsigned long)_orig.nraddr; \
2860 _argvec[1] = (unsigned long)(arg1); \
2861 _argvec[2] = (unsigned long)(arg2); \
2862 _argvec[3] = (unsigned long)(arg3); \
2863 _argvec[4] = (unsigned long)(arg4); \
2864 _argvec[5] = (unsigned long)(arg5); \
2865 _argvec[6] = (unsigned long)(arg6); \
2866 _argvec[7] = (unsigned long)(arg7); \
2867 _argvec[8] = (unsigned long)(arg8); \
2868 _argvec[9] = (unsigned long)(arg9); \
2869 _argvec[10] = (unsigned long)(arg10); \
2870 _argvec[11] = (unsigned long)(arg11); \
2872 "ldr r0, [%1, #40] \n\t" \
2873 "ldr r1, [%1, #44] \n\t" \
2874 "push {r0, r1} \n\t" \
2875 "ldr r0, [%1, #20] \n\t" \
2876 "ldr r1, [%1, #24] \n\t" \
2877 "ldr r2, [%1, #28] \n\t" \
2878 "ldr r3, [%1, #32] \n\t" \
2879 "ldr r4, [%1, #36] \n\t" \
2880 "push {r0, r1, r2, r3, r4} \n\t" \
2881 "ldr r0, [%1, #4] \n\t" \
2882 "ldr r1, [%1, #8] \n\t" \
2883 "ldr r2, [%1, #12] \n\t" \
2884 "ldr r3, [%1, #16] \n\t" \
2885 "ldr r4, [%1] \n\t" /* target->r4 */ \
2886 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2887 "add sp, sp, #28 \n\t" \
2889 : /*out*/ "=r" (_res) \
2890 : /*in*/ "0" (&_argvec[0]) \
2891 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
2893 lval = (__typeof__(lval)) _res; \
2896 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2897 arg6,arg7,arg8,arg9,arg10, \
2900 volatile OrigFn _orig = (orig); \
2901 volatile unsigned long _argvec[13]; \
2902 volatile unsigned long _res; \
2903 _argvec[0] = (unsigned long)_orig.nraddr; \
2904 _argvec[1] = (unsigned long)(arg1); \
2905 _argvec[2] = (unsigned long)(arg2); \
2906 _argvec[3] = (unsigned long)(arg3); \
2907 _argvec[4] = (unsigned long)(arg4); \
2908 _argvec[5] = (unsigned long)(arg5); \
2909 _argvec[6] = (unsigned long)(arg6); \
2910 _argvec[7] = (unsigned long)(arg7); \
2911 _argvec[8] = (unsigned long)(arg8); \
2912 _argvec[9] = (unsigned long)(arg9); \
2913 _argvec[10] = (unsigned long)(arg10); \
2914 _argvec[11] = (unsigned long)(arg11); \
2915 _argvec[12] = (unsigned long)(arg12); \
2917 "ldr r0, [%1, #40] \n\t" \
2918 "ldr r1, [%1, #44] \n\t" \
2919 "ldr r2, [%1, #48] \n\t" \
2920 "push {r0, r1, r2} \n\t" \
2921 "ldr r0, [%1, #20] \n\t" \
2922 "ldr r1, [%1, #24] \n\t" \
2923 "ldr r2, [%1, #28] \n\t" \
2924 "ldr r3, [%1, #32] \n\t" \
2925 "ldr r4, [%1, #36] \n\t" \
2926 "push {r0, r1, r2, r3, r4} \n\t" \
2927 "ldr r0, [%1, #4] \n\t" \
2928 "ldr r1, [%1, #8] \n\t" \
2929 "ldr r2, [%1, #12] \n\t" \
2930 "ldr r3, [%1, #16] \n\t" \
2931 "ldr r4, [%1] \n\t" /* target->r4 */ \
2932 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2933 "add sp, sp, #32 \n\t" \
2935 : /*out*/ "=r" (_res) \
2936 : /*in*/ "0" (&_argvec[0]) \
2937 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2939 lval = (__typeof__(lval)) _res; \
2942 #endif /* PLAT_arm_linux */
2944 /* ------------------------ ppc32-aix5 ------------------------- */
2946 #if defined(PLAT_ppc32_aix5)
2948 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2950 /* These regs are trashed by the hidden call. */
2951 #define __CALLER_SAVED_REGS \
2952 "lr", "ctr", "xer", \
2953 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2954 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2957 /* Expand the stack frame, copying enough info that unwinding
2958 still works. Trashes r3. */
2960 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2961 "addi 1,1,-" #_n_fr "\n\t" \
2962 "lwz 3," #_n_fr "(1)\n\t" \
2965 #define VG_CONTRACT_FRAME_BY(_n_fr) \
2966 "addi 1,1," #_n_fr "\n\t"
2968 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2971 #define CALL_FN_W_v(lval, orig) \
2973 volatile OrigFn _orig = (orig); \
2974 volatile unsigned long _argvec[3+0]; \
2975 volatile unsigned long _res; \
2976 /* _argvec[0] holds current r2 across the call */ \
2977 _argvec[1] = (unsigned long)_orig.r2; \
2978 _argvec[2] = (unsigned long)_orig.nraddr; \
2981 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2982 "stw 2,-8(11)\n\t" /* save tocptr */ \
2983 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2984 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2985 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2988 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2989 VG_CONTRACT_FRAME_BY(512) \
2990 : /*out*/ "=r" (_res) \
2991 : /*in*/ "r" (&_argvec[2]) \
2992 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2994 lval = (__typeof__(lval)) _res; \
2997 #define CALL_FN_W_W(lval, orig, arg1) \
2999 volatile OrigFn _orig = (orig); \
3000 volatile unsigned long _argvec[3+1]; \
3001 volatile unsigned long _res; \
3002 /* _argvec[0] holds current r2 across the call */ \
3003 _argvec[1] = (unsigned long)_orig.r2; \
3004 _argvec[2] = (unsigned long)_orig.nraddr; \
3005 _argvec[2+1] = (unsigned long)arg1; \
3008 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3009 "stw 2,-8(11)\n\t" /* save tocptr */ \
3010 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3011 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3012 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3013 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3016 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3017 VG_CONTRACT_FRAME_BY(512) \
3018 : /*out*/ "=r" (_res) \
3019 : /*in*/ "r" (&_argvec[2]) \
3020 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3022 lval = (__typeof__(lval)) _res; \
3025 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3027 volatile OrigFn _orig = (orig); \
3028 volatile unsigned long _argvec[3+2]; \
3029 volatile unsigned long _res; \
3030 /* _argvec[0] holds current r2 across the call */ \
3031 _argvec[1] = (unsigned long)_orig.r2; \
3032 _argvec[2] = (unsigned long)_orig.nraddr; \
3033 _argvec[2+1] = (unsigned long)arg1; \
3034 _argvec[2+2] = (unsigned long)arg2; \
3037 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3038 "stw 2,-8(11)\n\t" /* save tocptr */ \
3039 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3040 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3041 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3042 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3043 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3046 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3047 VG_CONTRACT_FRAME_BY(512) \
3048 : /*out*/ "=r" (_res) \
3049 : /*in*/ "r" (&_argvec[2]) \
3050 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3052 lval = (__typeof__(lval)) _res; \
3055 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3057 volatile OrigFn _orig = (orig); \
3058 volatile unsigned long _argvec[3+3]; \
3059 volatile unsigned long _res; \
3060 /* _argvec[0] holds current r2 across the call */ \
3061 _argvec[1] = (unsigned long)_orig.r2; \
3062 _argvec[2] = (unsigned long)_orig.nraddr; \
3063 _argvec[2+1] = (unsigned long)arg1; \
3064 _argvec[2+2] = (unsigned long)arg2; \
3065 _argvec[2+3] = (unsigned long)arg3; \
3068 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3069 "stw 2,-8(11)\n\t" /* save tocptr */ \
3070 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3071 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3072 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3073 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3074 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3075 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3078 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3079 VG_CONTRACT_FRAME_BY(512) \
3080 : /*out*/ "=r" (_res) \
3081 : /*in*/ "r" (&_argvec[2]) \
3082 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3084 lval = (__typeof__(lval)) _res; \
3087 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3089 volatile OrigFn _orig = (orig); \
3090 volatile unsigned long _argvec[3+4]; \
3091 volatile unsigned long _res; \
3092 /* _argvec[0] holds current r2 across the call */ \
3093 _argvec[1] = (unsigned long)_orig.r2; \
3094 _argvec[2] = (unsigned long)_orig.nraddr; \
3095 _argvec[2+1] = (unsigned long)arg1; \
3096 _argvec[2+2] = (unsigned long)arg2; \
3097 _argvec[2+3] = (unsigned long)arg3; \
3098 _argvec[2+4] = (unsigned long)arg4; \
3101 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3102 "stw 2,-8(11)\n\t" /* save tocptr */ \
3103 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3104 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3105 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3106 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3107 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3108 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3109 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3112 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3113 VG_CONTRACT_FRAME_BY(512) \
3114 : /*out*/ "=r" (_res) \
3115 : /*in*/ "r" (&_argvec[2]) \
3116 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3118 lval = (__typeof__(lval)) _res; \
3121 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3123 volatile OrigFn _orig = (orig); \
3124 volatile unsigned long _argvec[3+5]; \
3125 volatile unsigned long _res; \
3126 /* _argvec[0] holds current r2 across the call */ \
3127 _argvec[1] = (unsigned long)_orig.r2; \
3128 _argvec[2] = (unsigned long)_orig.nraddr; \
3129 _argvec[2+1] = (unsigned long)arg1; \
3130 _argvec[2+2] = (unsigned long)arg2; \
3131 _argvec[2+3] = (unsigned long)arg3; \
3132 _argvec[2+4] = (unsigned long)arg4; \
3133 _argvec[2+5] = (unsigned long)arg5; \
3136 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3137 "stw 2,-8(11)\n\t" /* save tocptr */ \
3138 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3139 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3140 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3141 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3142 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3143 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3144 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3145 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3148 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3149 VG_CONTRACT_FRAME_BY(512) \
3150 : /*out*/ "=r" (_res) \
3151 : /*in*/ "r" (&_argvec[2]) \
3152 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3154 lval = (__typeof__(lval)) _res; \
3157 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3159 volatile OrigFn _orig = (orig); \
3160 volatile unsigned long _argvec[3+6]; \
3161 volatile unsigned long _res; \
3162 /* _argvec[0] holds current r2 across the call */ \
3163 _argvec[1] = (unsigned long)_orig.r2; \
3164 _argvec[2] = (unsigned long)_orig.nraddr; \
3165 _argvec[2+1] = (unsigned long)arg1; \
3166 _argvec[2+2] = (unsigned long)arg2; \
3167 _argvec[2+3] = (unsigned long)arg3; \
3168 _argvec[2+4] = (unsigned long)arg4; \
3169 _argvec[2+5] = (unsigned long)arg5; \
3170 _argvec[2+6] = (unsigned long)arg6; \
3173 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3174 "stw 2,-8(11)\n\t" /* save tocptr */ \
3175 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3176 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3177 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3178 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3179 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3180 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3181 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3182 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3183 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3186 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3187 VG_CONTRACT_FRAME_BY(512) \
3188 : /*out*/ "=r" (_res) \
3189 : /*in*/ "r" (&_argvec[2]) \
3190 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3192 lval = (__typeof__(lval)) _res; \
3195 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3198 volatile OrigFn _orig = (orig); \
3199 volatile unsigned long _argvec[3+7]; \
3200 volatile unsigned long _res; \
3201 /* _argvec[0] holds current r2 across the call */ \
3202 _argvec[1] = (unsigned long)_orig.r2; \
3203 _argvec[2] = (unsigned long)_orig.nraddr; \
3204 _argvec[2+1] = (unsigned long)arg1; \
3205 _argvec[2+2] = (unsigned long)arg2; \
3206 _argvec[2+3] = (unsigned long)arg3; \
3207 _argvec[2+4] = (unsigned long)arg4; \
3208 _argvec[2+5] = (unsigned long)arg5; \
3209 _argvec[2+6] = (unsigned long)arg6; \
3210 _argvec[2+7] = (unsigned long)arg7; \
3213 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3214 "stw 2,-8(11)\n\t" /* save tocptr */ \
3215 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3216 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3217 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3218 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3219 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3220 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3221 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3222 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3223 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3224 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3227 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3228 VG_CONTRACT_FRAME_BY(512) \
3229 : /*out*/ "=r" (_res) \
3230 : /*in*/ "r" (&_argvec[2]) \
3231 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3233 lval = (__typeof__(lval)) _res; \
3236 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3239 volatile OrigFn _orig = (orig); \
3240 volatile unsigned long _argvec[3+8]; \
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; \
3251 _argvec[2+7] = (unsigned long)arg7; \
3252 _argvec[2+8] = (unsigned long)arg8; \
3255 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3256 "stw 2,-8(11)\n\t" /* save tocptr */ \
3257 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3258 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3259 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3260 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3261 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3262 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3263 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3264 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3265 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3266 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3267 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3270 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3271 VG_CONTRACT_FRAME_BY(512) \
3272 : /*out*/ "=r" (_res) \
3273 : /*in*/ "r" (&_argvec[2]) \
3274 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3276 lval = (__typeof__(lval)) _res; \
3279 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3282 volatile OrigFn _orig = (orig); \
3283 volatile unsigned long _argvec[3+9]; \
3284 volatile unsigned long _res; \
3285 /* _argvec[0] holds current r2 across the call */ \
3286 _argvec[1] = (unsigned long)_orig.r2; \
3287 _argvec[2] = (unsigned long)_orig.nraddr; \
3288 _argvec[2+1] = (unsigned long)arg1; \
3289 _argvec[2+2] = (unsigned long)arg2; \
3290 _argvec[2+3] = (unsigned long)arg3; \
3291 _argvec[2+4] = (unsigned long)arg4; \
3292 _argvec[2+5] = (unsigned long)arg5; \
3293 _argvec[2+6] = (unsigned long)arg6; \
3294 _argvec[2+7] = (unsigned long)arg7; \
3295 _argvec[2+8] = (unsigned long)arg8; \
3296 _argvec[2+9] = (unsigned long)arg9; \
3299 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3300 "stw 2,-8(11)\n\t" /* save tocptr */ \
3301 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3302 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3304 "lwz 3,36(11)\n\t" \
3307 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3308 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3309 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3310 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3311 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3312 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3313 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3314 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3315 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3316 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3319 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3320 VG_CONTRACT_FRAME_BY(64) \
3321 VG_CONTRACT_FRAME_BY(512) \
3322 : /*out*/ "=r" (_res) \
3323 : /*in*/ "r" (&_argvec[2]) \
3324 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3326 lval = (__typeof__(lval)) _res; \
3329 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3330 arg7,arg8,arg9,arg10) \
3332 volatile OrigFn _orig = (orig); \
3333 volatile unsigned long _argvec[3+10]; \
3334 volatile unsigned long _res; \
3335 /* _argvec[0] holds current r2 across the call */ \
3336 _argvec[1] = (unsigned long)_orig.r2; \
3337 _argvec[2] = (unsigned long)_orig.nraddr; \
3338 _argvec[2+1] = (unsigned long)arg1; \
3339 _argvec[2+2] = (unsigned long)arg2; \
3340 _argvec[2+3] = (unsigned long)arg3; \
3341 _argvec[2+4] = (unsigned long)arg4; \
3342 _argvec[2+5] = (unsigned long)arg5; \
3343 _argvec[2+6] = (unsigned long)arg6; \
3344 _argvec[2+7] = (unsigned long)arg7; \
3345 _argvec[2+8] = (unsigned long)arg8; \
3346 _argvec[2+9] = (unsigned long)arg9; \
3347 _argvec[2+10] = (unsigned long)arg10; \
3350 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3351 "stw 2,-8(11)\n\t" /* save tocptr */ \
3352 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3353 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3355 "lwz 3,40(11)\n\t" \
3358 "lwz 3,36(11)\n\t" \
3361 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3362 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3363 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3364 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3365 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3366 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3367 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3368 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3369 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3370 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3373 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3374 VG_CONTRACT_FRAME_BY(64) \
3375 VG_CONTRACT_FRAME_BY(512) \
3376 : /*out*/ "=r" (_res) \
3377 : /*in*/ "r" (&_argvec[2]) \
3378 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3380 lval = (__typeof__(lval)) _res; \
3383 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3384 arg7,arg8,arg9,arg10,arg11) \
3386 volatile OrigFn _orig = (orig); \
3387 volatile unsigned long _argvec[3+11]; \
3388 volatile unsigned long _res; \
3389 /* _argvec[0] holds current r2 across the call */ \
3390 _argvec[1] = (unsigned long)_orig.r2; \
3391 _argvec[2] = (unsigned long)_orig.nraddr; \
3392 _argvec[2+1] = (unsigned long)arg1; \
3393 _argvec[2+2] = (unsigned long)arg2; \
3394 _argvec[2+3] = (unsigned long)arg3; \
3395 _argvec[2+4] = (unsigned long)arg4; \
3396 _argvec[2+5] = (unsigned long)arg5; \
3397 _argvec[2+6] = (unsigned long)arg6; \
3398 _argvec[2+7] = (unsigned long)arg7; \
3399 _argvec[2+8] = (unsigned long)arg8; \
3400 _argvec[2+9] = (unsigned long)arg9; \
3401 _argvec[2+10] = (unsigned long)arg10; \
3402 _argvec[2+11] = (unsigned long)arg11; \
3405 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3406 "stw 2,-8(11)\n\t" /* save tocptr */ \
3407 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3408 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3410 "lwz 3,44(11)\n\t" \
3413 "lwz 3,40(11)\n\t" \
3416 "lwz 3,36(11)\n\t" \
3419 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3420 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3421 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3422 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3423 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3424 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3425 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3426 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3427 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3428 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3431 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3432 VG_CONTRACT_FRAME_BY(72) \
3433 VG_CONTRACT_FRAME_BY(512) \
3434 : /*out*/ "=r" (_res) \
3435 : /*in*/ "r" (&_argvec[2]) \
3436 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3438 lval = (__typeof__(lval)) _res; \
3441 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3442 arg7,arg8,arg9,arg10,arg11,arg12) \
3444 volatile OrigFn _orig = (orig); \
3445 volatile unsigned long _argvec[3+12]; \
3446 volatile unsigned long _res; \
3447 /* _argvec[0] holds current r2 across the call */ \
3448 _argvec[1] = (unsigned long)_orig.r2; \
3449 _argvec[2] = (unsigned long)_orig.nraddr; \
3450 _argvec[2+1] = (unsigned long)arg1; \
3451 _argvec[2+2] = (unsigned long)arg2; \
3452 _argvec[2+3] = (unsigned long)arg3; \
3453 _argvec[2+4] = (unsigned long)arg4; \
3454 _argvec[2+5] = (unsigned long)arg5; \
3455 _argvec[2+6] = (unsigned long)arg6; \
3456 _argvec[2+7] = (unsigned long)arg7; \
3457 _argvec[2+8] = (unsigned long)arg8; \
3458 _argvec[2+9] = (unsigned long)arg9; \
3459 _argvec[2+10] = (unsigned long)arg10; \
3460 _argvec[2+11] = (unsigned long)arg11; \
3461 _argvec[2+12] = (unsigned long)arg12; \
3464 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3465 "stw 2,-8(11)\n\t" /* save tocptr */ \
3466 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3467 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3469 "lwz 3,48(11)\n\t" \
3472 "lwz 3,44(11)\n\t" \
3475 "lwz 3,40(11)\n\t" \
3478 "lwz 3,36(11)\n\t" \
3481 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3482 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3483 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3484 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3485 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3486 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3487 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3488 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3489 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3490 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3493 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3494 VG_CONTRACT_FRAME_BY(72) \
3495 VG_CONTRACT_FRAME_BY(512) \
3496 : /*out*/ "=r" (_res) \
3497 : /*in*/ "r" (&_argvec[2]) \
3498 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3500 lval = (__typeof__(lval)) _res; \
3503 #endif /* PLAT_ppc32_aix5 */
3505 /* ------------------------ ppc64-aix5 ------------------------- */
3507 #if defined(PLAT_ppc64_aix5)
3509 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3511 /* These regs are trashed by the hidden call. */
3512 #define __CALLER_SAVED_REGS \
3513 "lr", "ctr", "xer", \
3514 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3515 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3518 /* Expand the stack frame, copying enough info that unwinding
3519 still works. Trashes r3. */
3521 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3522 "addi 1,1,-" #_n_fr "\n\t" \
3523 "ld 3," #_n_fr "(1)\n\t" \
3526 #define VG_CONTRACT_FRAME_BY(_n_fr) \
3527 "addi 1,1," #_n_fr "\n\t"
3529 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3532 #define CALL_FN_W_v(lval, orig) \
3534 volatile OrigFn _orig = (orig); \
3535 volatile unsigned long _argvec[3+0]; \
3536 volatile unsigned long _res; \
3537 /* _argvec[0] holds current r2 across the call */ \
3538 _argvec[1] = (unsigned long)_orig.r2; \
3539 _argvec[2] = (unsigned long)_orig.nraddr; \
3542 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3543 "std 2,-16(11)\n\t" /* save tocptr */ \
3544 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3545 "ld 11, 0(11)\n\t" /* target->r11 */ \
3546 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3549 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3550 VG_CONTRACT_FRAME_BY(512) \
3551 : /*out*/ "=r" (_res) \
3552 : /*in*/ "r" (&_argvec[2]) \
3553 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3555 lval = (__typeof__(lval)) _res; \
3558 #define CALL_FN_W_W(lval, orig, arg1) \
3560 volatile OrigFn _orig = (orig); \
3561 volatile unsigned long _argvec[3+1]; \
3562 volatile unsigned long _res; \
3563 /* _argvec[0] holds current r2 across the call */ \
3564 _argvec[1] = (unsigned long)_orig.r2; \
3565 _argvec[2] = (unsigned long)_orig.nraddr; \
3566 _argvec[2+1] = (unsigned long)arg1; \
3569 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3570 "std 2,-16(11)\n\t" /* save tocptr */ \
3571 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3572 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3573 "ld 11, 0(11)\n\t" /* target->r11 */ \
3574 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3577 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3578 VG_CONTRACT_FRAME_BY(512) \
3579 : /*out*/ "=r" (_res) \
3580 : /*in*/ "r" (&_argvec[2]) \
3581 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3583 lval = (__typeof__(lval)) _res; \
3586 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3588 volatile OrigFn _orig = (orig); \
3589 volatile unsigned long _argvec[3+2]; \
3590 volatile unsigned long _res; \
3591 /* _argvec[0] holds current r2 across the call */ \
3592 _argvec[1] = (unsigned long)_orig.r2; \
3593 _argvec[2] = (unsigned long)_orig.nraddr; \
3594 _argvec[2+1] = (unsigned long)arg1; \
3595 _argvec[2+2] = (unsigned long)arg2; \
3598 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3599 "std 2,-16(11)\n\t" /* save tocptr */ \
3600 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3601 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3602 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3603 "ld 11, 0(11)\n\t" /* target->r11 */ \
3604 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3607 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3608 VG_CONTRACT_FRAME_BY(512) \
3609 : /*out*/ "=r" (_res) \
3610 : /*in*/ "r" (&_argvec[2]) \
3611 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3613 lval = (__typeof__(lval)) _res; \
3616 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3618 volatile OrigFn _orig = (orig); \
3619 volatile unsigned long _argvec[3+3]; \
3620 volatile unsigned long _res; \
3621 /* _argvec[0] holds current r2 across the call */ \
3622 _argvec[1] = (unsigned long)_orig.r2; \
3623 _argvec[2] = (unsigned long)_orig.nraddr; \
3624 _argvec[2+1] = (unsigned long)arg1; \
3625 _argvec[2+2] = (unsigned long)arg2; \
3626 _argvec[2+3] = (unsigned long)arg3; \
3629 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3630 "std 2,-16(11)\n\t" /* save tocptr */ \
3631 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3632 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3633 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3634 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3635 "ld 11, 0(11)\n\t" /* target->r11 */ \
3636 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3639 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3640 VG_CONTRACT_FRAME_BY(512) \
3641 : /*out*/ "=r" (_res) \
3642 : /*in*/ "r" (&_argvec[2]) \
3643 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3645 lval = (__typeof__(lval)) _res; \
3648 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3650 volatile OrigFn _orig = (orig); \
3651 volatile unsigned long _argvec[3+4]; \
3652 volatile unsigned long _res; \
3653 /* _argvec[0] holds current r2 across the call */ \
3654 _argvec[1] = (unsigned long)_orig.r2; \
3655 _argvec[2] = (unsigned long)_orig.nraddr; \
3656 _argvec[2+1] = (unsigned long)arg1; \
3657 _argvec[2+2] = (unsigned long)arg2; \
3658 _argvec[2+3] = (unsigned long)arg3; \
3659 _argvec[2+4] = (unsigned long)arg4; \
3662 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3663 "std 2,-16(11)\n\t" /* save tocptr */ \
3664 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3665 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3666 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3667 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3668 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3669 "ld 11, 0(11)\n\t" /* target->r11 */ \
3670 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3673 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3674 VG_CONTRACT_FRAME_BY(512) \
3675 : /*out*/ "=r" (_res) \
3676 : /*in*/ "r" (&_argvec[2]) \
3677 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3679 lval = (__typeof__(lval)) _res; \
3682 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3684 volatile OrigFn _orig = (orig); \
3685 volatile unsigned long _argvec[3+5]; \
3686 volatile unsigned long _res; \
3687 /* _argvec[0] holds current r2 across the call */ \
3688 _argvec[1] = (unsigned long)_orig.r2; \
3689 _argvec[2] = (unsigned long)_orig.nraddr; \
3690 _argvec[2+1] = (unsigned long)arg1; \
3691 _argvec[2+2] = (unsigned long)arg2; \
3692 _argvec[2+3] = (unsigned long)arg3; \
3693 _argvec[2+4] = (unsigned long)arg4; \
3694 _argvec[2+5] = (unsigned long)arg5; \
3697 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3698 "std 2,-16(11)\n\t" /* save tocptr */ \
3699 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3700 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3701 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3702 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3703 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3704 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3705 "ld 11, 0(11)\n\t" /* target->r11 */ \
3706 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3709 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3710 VG_CONTRACT_FRAME_BY(512) \
3711 : /*out*/ "=r" (_res) \
3712 : /*in*/ "r" (&_argvec[2]) \
3713 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3715 lval = (__typeof__(lval)) _res; \
3718 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3720 volatile OrigFn _orig = (orig); \
3721 volatile unsigned long _argvec[3+6]; \
3722 volatile unsigned long _res; \
3723 /* _argvec[0] holds current r2 across the call */ \
3724 _argvec[1] = (unsigned long)_orig.r2; \
3725 _argvec[2] = (unsigned long)_orig.nraddr; \
3726 _argvec[2+1] = (unsigned long)arg1; \
3727 _argvec[2+2] = (unsigned long)arg2; \
3728 _argvec[2+3] = (unsigned long)arg3; \
3729 _argvec[2+4] = (unsigned long)arg4; \
3730 _argvec[2+5] = (unsigned long)arg5; \
3731 _argvec[2+6] = (unsigned long)arg6; \
3734 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3735 "std 2,-16(11)\n\t" /* save tocptr */ \
3736 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3737 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3738 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3739 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3740 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3741 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3742 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3743 "ld 11, 0(11)\n\t" /* target->r11 */ \
3744 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3747 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3748 VG_CONTRACT_FRAME_BY(512) \
3749 : /*out*/ "=r" (_res) \
3750 : /*in*/ "r" (&_argvec[2]) \
3751 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3753 lval = (__typeof__(lval)) _res; \
3756 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3759 volatile OrigFn _orig = (orig); \
3760 volatile unsigned long _argvec[3+7]; \
3761 volatile unsigned long _res; \
3762 /* _argvec[0] holds current r2 across the call */ \
3763 _argvec[1] = (unsigned long)_orig.r2; \
3764 _argvec[2] = (unsigned long)_orig.nraddr; \
3765 _argvec[2+1] = (unsigned long)arg1; \
3766 _argvec[2+2] = (unsigned long)arg2; \
3767 _argvec[2+3] = (unsigned long)arg3; \
3768 _argvec[2+4] = (unsigned long)arg4; \
3769 _argvec[2+5] = (unsigned long)arg5; \
3770 _argvec[2+6] = (unsigned long)arg6; \
3771 _argvec[2+7] = (unsigned long)arg7; \
3774 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3775 "std 2,-16(11)\n\t" /* save tocptr */ \
3776 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3777 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3778 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3779 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3780 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3781 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3782 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3783 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3784 "ld 11, 0(11)\n\t" /* target->r11 */ \
3785 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3788 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3789 VG_CONTRACT_FRAME_BY(512) \
3790 : /*out*/ "=r" (_res) \
3791 : /*in*/ "r" (&_argvec[2]) \
3792 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3794 lval = (__typeof__(lval)) _res; \
3797 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3800 volatile OrigFn _orig = (orig); \
3801 volatile unsigned long _argvec[3+8]; \
3802 volatile unsigned long _res; \
3803 /* _argvec[0] holds current r2 across the call */ \
3804 _argvec[1] = (unsigned long)_orig.r2; \
3805 _argvec[2] = (unsigned long)_orig.nraddr; \
3806 _argvec[2+1] = (unsigned long)arg1; \
3807 _argvec[2+2] = (unsigned long)arg2; \
3808 _argvec[2+3] = (unsigned long)arg3; \
3809 _argvec[2+4] = (unsigned long)arg4; \
3810 _argvec[2+5] = (unsigned long)arg5; \
3811 _argvec[2+6] = (unsigned long)arg6; \
3812 _argvec[2+7] = (unsigned long)arg7; \
3813 _argvec[2+8] = (unsigned long)arg8; \
3816 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3817 "std 2,-16(11)\n\t" /* save tocptr */ \
3818 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3819 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3820 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3821 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3822 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3823 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3824 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3825 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3826 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3827 "ld 11, 0(11)\n\t" /* target->r11 */ \
3828 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3831 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3832 VG_CONTRACT_FRAME_BY(512) \
3833 : /*out*/ "=r" (_res) \
3834 : /*in*/ "r" (&_argvec[2]) \
3835 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3837 lval = (__typeof__(lval)) _res; \
3840 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3843 volatile OrigFn _orig = (orig); \
3844 volatile unsigned long _argvec[3+9]; \
3845 volatile unsigned long _res; \
3846 /* _argvec[0] holds current r2 across the call */ \
3847 _argvec[1] = (unsigned long)_orig.r2; \
3848 _argvec[2] = (unsigned long)_orig.nraddr; \
3849 _argvec[2+1] = (unsigned long)arg1; \
3850 _argvec[2+2] = (unsigned long)arg2; \
3851 _argvec[2+3] = (unsigned long)arg3; \
3852 _argvec[2+4] = (unsigned long)arg4; \
3853 _argvec[2+5] = (unsigned long)arg5; \
3854 _argvec[2+6] = (unsigned long)arg6; \
3855 _argvec[2+7] = (unsigned long)arg7; \
3856 _argvec[2+8] = (unsigned long)arg8; \
3857 _argvec[2+9] = (unsigned long)arg9; \
3860 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3861 "std 2,-16(11)\n\t" /* save tocptr */ \
3862 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3863 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3866 "std 3,112(1)\n\t" \
3868 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3869 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3870 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3871 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3872 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3873 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3874 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3875 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3876 "ld 11, 0(11)\n\t" /* target->r11 */ \
3877 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3880 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3881 VG_CONTRACT_FRAME_BY(128) \
3882 VG_CONTRACT_FRAME_BY(512) \
3883 : /*out*/ "=r" (_res) \
3884 : /*in*/ "r" (&_argvec[2]) \
3885 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3887 lval = (__typeof__(lval)) _res; \
3890 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3891 arg7,arg8,arg9,arg10) \
3893 volatile OrigFn _orig = (orig); \
3894 volatile unsigned long _argvec[3+10]; \
3895 volatile unsigned long _res; \
3896 /* _argvec[0] holds current r2 across the call */ \
3897 _argvec[1] = (unsigned long)_orig.r2; \
3898 _argvec[2] = (unsigned long)_orig.nraddr; \
3899 _argvec[2+1] = (unsigned long)arg1; \
3900 _argvec[2+2] = (unsigned long)arg2; \
3901 _argvec[2+3] = (unsigned long)arg3; \
3902 _argvec[2+4] = (unsigned long)arg4; \
3903 _argvec[2+5] = (unsigned long)arg5; \
3904 _argvec[2+6] = (unsigned long)arg6; \
3905 _argvec[2+7] = (unsigned long)arg7; \
3906 _argvec[2+8] = (unsigned long)arg8; \
3907 _argvec[2+9] = (unsigned long)arg9; \
3908 _argvec[2+10] = (unsigned long)arg10; \
3911 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3912 "std 2,-16(11)\n\t" /* save tocptr */ \
3913 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3914 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3917 "std 3,120(1)\n\t" \
3920 "std 3,112(1)\n\t" \
3922 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3923 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3924 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3925 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3926 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3927 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3928 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3929 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3930 "ld 11, 0(11)\n\t" /* target->r11 */ \
3931 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3934 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3935 VG_CONTRACT_FRAME_BY(128) \
3936 VG_CONTRACT_FRAME_BY(512) \
3937 : /*out*/ "=r" (_res) \
3938 : /*in*/ "r" (&_argvec[2]) \
3939 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3941 lval = (__typeof__(lval)) _res; \
3944 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3945 arg7,arg8,arg9,arg10,arg11) \
3947 volatile OrigFn _orig = (orig); \
3948 volatile unsigned long _argvec[3+11]; \
3949 volatile unsigned long _res; \
3950 /* _argvec[0] holds current r2 across the call */ \
3951 _argvec[1] = (unsigned long)_orig.r2; \
3952 _argvec[2] = (unsigned long)_orig.nraddr; \
3953 _argvec[2+1] = (unsigned long)arg1; \
3954 _argvec[2+2] = (unsigned long)arg2; \
3955 _argvec[2+3] = (unsigned long)arg3; \
3956 _argvec[2+4] = (unsigned long)arg4; \
3957 _argvec[2+5] = (unsigned long)arg5; \
3958 _argvec[2+6] = (unsigned long)arg6; \
3959 _argvec[2+7] = (unsigned long)arg7; \
3960 _argvec[2+8] = (unsigned long)arg8; \
3961 _argvec[2+9] = (unsigned long)arg9; \
3962 _argvec[2+10] = (unsigned long)arg10; \
3963 _argvec[2+11] = (unsigned long)arg11; \
3966 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3967 "std 2,-16(11)\n\t" /* save tocptr */ \
3968 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3969 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3972 "std 3,128(1)\n\t" \
3975 "std 3,120(1)\n\t" \
3978 "std 3,112(1)\n\t" \
3980 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3981 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3982 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3983 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3984 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3985 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3986 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3987 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3988 "ld 11, 0(11)\n\t" /* target->r11 */ \
3989 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3992 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3993 VG_CONTRACT_FRAME_BY(144) \
3994 VG_CONTRACT_FRAME_BY(512) \
3995 : /*out*/ "=r" (_res) \
3996 : /*in*/ "r" (&_argvec[2]) \
3997 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3999 lval = (__typeof__(lval)) _res; \
4002 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4003 arg7,arg8,arg9,arg10,arg11,arg12) \
4005 volatile OrigFn _orig = (orig); \
4006 volatile unsigned long _argvec[3+12]; \
4007 volatile unsigned long _res; \
4008 /* _argvec[0] holds current r2 across the call */ \
4009 _argvec[1] = (unsigned long)_orig.r2; \
4010 _argvec[2] = (unsigned long)_orig.nraddr; \
4011 _argvec[2+1] = (unsigned long)arg1; \
4012 _argvec[2+2] = (unsigned long)arg2; \
4013 _argvec[2+3] = (unsigned long)arg3; \
4014 _argvec[2+4] = (unsigned long)arg4; \
4015 _argvec[2+5] = (unsigned long)arg5; \
4016 _argvec[2+6] = (unsigned long)arg6; \
4017 _argvec[2+7] = (unsigned long)arg7; \
4018 _argvec[2+8] = (unsigned long)arg8; \
4019 _argvec[2+9] = (unsigned long)arg9; \
4020 _argvec[2+10] = (unsigned long)arg10; \
4021 _argvec[2+11] = (unsigned long)arg11; \
4022 _argvec[2+12] = (unsigned long)arg12; \
4025 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4026 "std 2,-16(11)\n\t" /* save tocptr */ \
4027 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4028 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4031 "std 3,136(1)\n\t" \
4034 "std 3,128(1)\n\t" \
4037 "std 3,120(1)\n\t" \
4040 "std 3,112(1)\n\t" \
4042 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4043 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4044 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4045 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4046 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4047 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4048 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4049 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4050 "ld 11, 0(11)\n\t" /* target->r11 */ \
4051 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4054 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4055 VG_CONTRACT_FRAME_BY(144) \
4056 VG_CONTRACT_FRAME_BY(512) \
4057 : /*out*/ "=r" (_res) \
4058 : /*in*/ "r" (&_argvec[2]) \
4059 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4061 lval = (__typeof__(lval)) _res; \
4064 #endif /* PLAT_ppc64_aix5 */
4068 /* ------------------------------------------------------------------ */
4069 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4071 /* ------------------------------------------------------------------ */
4073 /* Some request codes. There are many more of these, but most are not
4074 exposed to end-user view. These are the public ones, all of the
4075 form 0x1000 + small_number.
4077 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4078 ones start at 0x2000.
4081 /* These macros are used by tools -- they must be public, but don't
4082 embed them into other programs. */
4083 #define VG_USERREQ_TOOL_BASE(a,b) \
4084 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
4085 #define VG_IS_TOOL_USERREQ(a, b, v) \
4086 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
4088 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4089 This enum comprises an ABI exported by Valgrind to programs
4090 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4091 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
4093 enum { VG_USERREQ__RUNNING_ON_VALGRIND
= 0x1001,
4094 VG_USERREQ__DISCARD_TRANSLATIONS
= 0x1002,
4096 /* These allow any function to be called from the simulated
4097 CPU but run on the real CPU. Nb: the first arg passed to
4098 the function is always the ThreadId of the running
4099 thread! So CLIENT_CALL0 actually requires a 1 arg
4101 VG_USERREQ__CLIENT_CALL0
= 0x1101,
4102 VG_USERREQ__CLIENT_CALL1
= 0x1102,
4103 VG_USERREQ__CLIENT_CALL2
= 0x1103,
4104 VG_USERREQ__CLIENT_CALL3
= 0x1104,
4106 /* Can be useful in regression testing suites -- eg. can
4107 send Valgrind's output to /dev/null and still count
4109 VG_USERREQ__COUNT_ERRORS
= 0x1201,
4111 /* These are useful and can be interpreted by any tool that
4112 tracks malloc() et al, by using vg_replace_malloc.c. */
4113 VG_USERREQ__MALLOCLIKE_BLOCK
= 0x1301,
4114 VG_USERREQ__FREELIKE_BLOCK
= 0x1302,
4115 /* Memory pool support. */
4116 VG_USERREQ__CREATE_MEMPOOL
= 0x1303,
4117 VG_USERREQ__DESTROY_MEMPOOL
= 0x1304,
4118 VG_USERREQ__MEMPOOL_ALLOC
= 0x1305,
4119 VG_USERREQ__MEMPOOL_FREE
= 0x1306,
4120 VG_USERREQ__MEMPOOL_TRIM
= 0x1307,
4121 VG_USERREQ__MOVE_MEMPOOL
= 0x1308,
4122 VG_USERREQ__MEMPOOL_CHANGE
= 0x1309,
4123 VG_USERREQ__MEMPOOL_EXISTS
= 0x130a,
4125 /* Allow printfs to valgrind log. */
4126 /* The first two pass the va_list argument by value, which
4127 assumes it is the same size as or smaller than a UWord,
4128 which generally isn't the case. Hence are deprecated.
4129 The second two pass the vargs by reference and so are
4130 immune to this problem. */
4131 /* both :: char* fmt, va_list vargs (DEPRECATED) */
4132 VG_USERREQ__PRINTF
= 0x1401,
4133 VG_USERREQ__PRINTF_BACKTRACE
= 0x1402,
4134 /* both :: char* fmt, va_list* vargs */
4135 VG_USERREQ__PRINTF_VALIST_BY_REF
= 0x1403,
4136 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF
= 0x1404,
4138 /* Stack support. */
4139 VG_USERREQ__STACK_REGISTER
= 0x1501,
4140 VG_USERREQ__STACK_DEREGISTER
= 0x1502,
4141 VG_USERREQ__STACK_CHANGE
= 0x1503,
4144 VG_USERREQ__LOAD_PDB_DEBUGINFO
= 0x1601
4147 #if !defined(__GNUC__)
4148 # define __extension__ /* */
4151 /* Returns the number of Valgrinds this code is running under. That
4152 is, 0 if running natively, 1 if running under Valgrind, 2 if
4153 running under Valgrind which is running under another Valgrind,
4155 #define RUNNING_ON_VALGRIND __extension__ \
4156 ({unsigned int _qzz_res; \
4157 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
4158 VG_USERREQ__RUNNING_ON_VALGRIND, \
4164 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4165 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4166 since it provides a way to make sure valgrind will retranslate the
4167 invalidated area. Returns no value. */
4168 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4169 {unsigned int _qzz_res; \
4170 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4171 VG_USERREQ__DISCARD_TRANSLATIONS, \
4172 _qzz_addr, _qzz_len, 0, 0, 0); \
4176 /* These requests are for getting Valgrind itself to print something.
4177 Possibly with a backtrace. This is a really ugly hack. The return value
4178 is the number of characters printed, excluding the "**<pid>** " part at the
4179 start and the backtrace (if present). */
4181 #if defined(NVALGRIND)
4183 # define VALGRIND_PRINTF(...)
4184 # define VALGRIND_PRINTF_BACKTRACE(...)
4186 #else /* NVALGRIND */
4188 /* Modern GCC will optimize the static routine out if unused,
4189 and unused attribute will shut down warnings about it. */
4190 static int VALGRIND_PRINTF(const char *format
, ...)
4191 __attribute__((format(__printf__
, 1, 2), __unused__
));
4193 VALGRIND_PRINTF(const char *format
, ...)
4195 unsigned long _qzz_res
;
4197 va_start(vargs
, format
);
4198 VALGRIND_DO_CLIENT_REQUEST(_qzz_res
, 0,
4199 VG_USERREQ__PRINTF_VALIST_BY_REF
,
4200 (unsigned long)format
,
4201 (unsigned long)&vargs
,
4204 return (int)_qzz_res
;
4207 static int VALGRIND_PRINTF_BACKTRACE(const char *format
, ...)
4208 __attribute__((format(__printf__
, 1, 2), __unused__
));
4210 VALGRIND_PRINTF_BACKTRACE(const char *format
, ...)
4212 unsigned long _qzz_res
;
4214 va_start(vargs
, format
);
4215 VALGRIND_DO_CLIENT_REQUEST(_qzz_res
, 0,
4216 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF
,
4217 (unsigned long)format
,
4218 (unsigned long)&vargs
,
4221 return (int)_qzz_res
;
4224 #endif /* NVALGRIND */
4227 /* These requests allow control to move from the simulated CPU to the
4228 real CPU, calling an arbitary function.
4230 Note that the current ThreadId is inserted as the first argument.
4233 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4235 requires f to have this signature:
4237 Word f(Word tid, Word arg1, Word arg2)
4239 where "Word" is a word-sized type.
4241 Note that these client requests are not entirely reliable. For example,
4242 if you call a function with them that subsequently calls printf(),
4243 there's a high chance Valgrind will crash. Generally, your prospects of
4244 these working are made higher if the called function does not refer to
4245 any global variables, and does not refer to any libc or other functions
4246 (printf et al). Any kind of entanglement with libc or dynamic linking is
4247 likely to have a bad outcome, for tricky reasons which we've grappled
4248 with a lot in the past.
4250 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
4252 ({unsigned long _qyy_res; \
4253 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4254 VG_USERREQ__CLIENT_CALL0, \
4260 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
4262 ({unsigned long _qyy_res; \
4263 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4264 VG_USERREQ__CLIENT_CALL1, \
4266 _qyy_arg1, 0, 0, 0); \
4270 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
4272 ({unsigned long _qyy_res; \
4273 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4274 VG_USERREQ__CLIENT_CALL2, \
4276 _qyy_arg1, _qyy_arg2, 0, 0); \
4280 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
4282 ({unsigned long _qyy_res; \
4283 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4284 VG_USERREQ__CLIENT_CALL3, \
4286 _qyy_arg1, _qyy_arg2, \
4292 /* Counts the number of errors that have been recorded by a tool. Nb:
4293 the tool must record the errors with VG_(maybe_record_error)() or
4294 VG_(unique_error)() for them to be counted. */
4295 #define VALGRIND_COUNT_ERRORS \
4297 ({unsigned int _qyy_res; \
4298 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4299 VG_USERREQ__COUNT_ERRORS, \
4304 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4305 when heap blocks are allocated in order to give accurate results. This
4306 happens automatically for the standard allocator functions such as
4307 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4310 But if your program uses a custom allocator, this doesn't automatically
4311 happen, and Valgrind will not do as well. For example, if you allocate
4312 superblocks with mmap() and then allocates chunks of the superblocks, all
4313 Valgrind's observations will be at the mmap() level and it won't know that
4314 the chunks should be considered separate entities. In Memcheck's case,
4315 that means you probably won't get heap block overrun detection (because
4316 there won't be redzones marked as unaddressable) and you definitely won't
4317 get any leak detection.
4319 The following client requests allow a custom allocator to be annotated so
4320 that it can be handled accurately by Valgrind.
4322 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4323 by a malloc()-like function. For Memcheck (an illustrative case), this
4326 - It records that the block has been allocated. This means any addresses
4327 within the block mentioned in error messages will be
4328 identified as belonging to the block. It also means that if the block
4329 isn't freed it will be detected by the leak checker.
4331 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4332 not set), or addressable and defined (if 'is_zeroed' is set). This
4333 controls how accesses to the block by the program are handled.
4335 'addr' is the start of the usable block (ie. after any
4336 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4337 can apply redzones -- these are blocks of padding at the start and end of
4338 each block. Adding redzones is recommended as it makes it much more likely
4339 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4340 zeroed (or filled with another predictable value), as is the case for
4343 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4344 heap block -- that will be used by the client program -- is allocated.
4345 It's best to put it at the outermost level of the allocator if possible;
4346 for example, if you have a function my_alloc() which calls
4347 internal_alloc(), and the client request is put inside internal_alloc(),
4348 stack traces relating to the heap block will contain entries for both
4349 my_alloc() and internal_alloc(), which is probably not what you want.
4351 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4352 custom blocks from within a heap block, B, that has been allocated with
4353 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4354 -- the custom blocks will take precedence.
4356 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4357 Memcheck, it does two things:
4359 - It records that the block has been deallocated. This assumes that the
4360 block was annotated as having been allocated via
4361 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4363 - It marks the block as being unaddressable.
4365 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4366 heap block is deallocated.
4368 In many cases, these two client requests will not be enough to get your
4369 allocator working well with Memcheck. More specifically, if your allocator
4370 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4371 will be necessary to mark the memory as addressable just before the zeroing
4372 occurs, otherwise you'll get a lot of invalid write errors. For example,
4373 you'll need to do this if your allocator recycles freed blocks, but it
4374 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4375 Alternatively, if your allocator reuses freed blocks for allocator-internal
4376 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4378 Really, what's happening is a blurring of the lines between the client
4379 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4380 memory should be considered unaddressable to the client program, but the
4381 allocator knows more than the rest of the client program and so may be able
4382 to safely access it. Extra client requests are necessary for Valgrind to
4383 understand the distinction between the allocator and the rest of the
4386 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4387 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4389 Ignored if addr == 0.
4391 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4392 {unsigned int _qzz_res; \
4393 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4394 VG_USERREQ__MALLOCLIKE_BLOCK, \
4395 addr, sizeB, rzB, is_zeroed, 0); \
4398 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4399 Ignored if addr == 0.
4401 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4402 {unsigned int _qzz_res; \
4403 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4404 VG_USERREQ__FREELIKE_BLOCK, \
4405 addr, rzB, 0, 0, 0); \
4408 /* Create a memory pool. */
4409 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4410 {unsigned int _qzz_res; \
4411 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4412 VG_USERREQ__CREATE_MEMPOOL, \
4413 pool, rzB, is_zeroed, 0, 0); \
4416 /* Destroy a memory pool. */
4417 #define VALGRIND_DESTROY_MEMPOOL(pool) \
4418 {unsigned int _qzz_res; \
4419 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4420 VG_USERREQ__DESTROY_MEMPOOL, \
4421 pool, 0, 0, 0, 0); \
4424 /* Associate a piece of memory with a memory pool. */
4425 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4426 {unsigned int _qzz_res; \
4427 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4428 VG_USERREQ__MEMPOOL_ALLOC, \
4429 pool, addr, size, 0, 0); \
4432 /* Disassociate a piece of memory from a memory pool. */
4433 #define VALGRIND_MEMPOOL_FREE(pool, addr) \
4434 {unsigned int _qzz_res; \
4435 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4436 VG_USERREQ__MEMPOOL_FREE, \
4437 pool, addr, 0, 0, 0); \
4440 /* Disassociate any pieces outside a particular range. */
4441 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4442 {unsigned int _qzz_res; \
4443 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4444 VG_USERREQ__MEMPOOL_TRIM, \
4445 pool, addr, size, 0, 0); \
4448 /* Resize and/or move a piece associated with a memory pool. */
4449 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4450 {unsigned int _qzz_res; \
4451 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4452 VG_USERREQ__MOVE_MEMPOOL, \
4453 poolA, poolB, 0, 0, 0); \
4456 /* Resize and/or move a piece associated with a memory pool. */
4457 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4458 {unsigned int _qzz_res; \
4459 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4460 VG_USERREQ__MEMPOOL_CHANGE, \
4461 pool, addrA, addrB, size, 0); \
4464 /* Return 1 if a mempool exists, else 0. */
4465 #define VALGRIND_MEMPOOL_EXISTS(pool) \
4467 ({unsigned int _qzz_res; \
4468 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4469 VG_USERREQ__MEMPOOL_EXISTS, \
4470 pool, 0, 0, 0, 0); \
4474 /* Mark a piece of memory as being a stack. Returns a stack id. */
4475 #define VALGRIND_STACK_REGISTER(start, end) \
4477 ({unsigned int _qzz_res; \
4478 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4479 VG_USERREQ__STACK_REGISTER, \
4480 start, end, 0, 0, 0); \
4484 /* Unmark the piece of memory associated with a stack id as being a
4486 #define VALGRIND_STACK_DEREGISTER(id) \
4487 {unsigned int _qzz_res; \
4488 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4489 VG_USERREQ__STACK_DEREGISTER, \
4493 /* Change the start and end address of the stack id. */
4494 #define VALGRIND_STACK_CHANGE(id, start, end) \
4495 {unsigned int _qzz_res; \
4496 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4497 VG_USERREQ__STACK_CHANGE, \
4498 id, start, end, 0, 0); \
4501 /* Load PDB debug info for Wine PE image_map. */
4502 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4503 {unsigned int _qzz_res; \
4504 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4505 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4506 fd, ptr, total_size, delta, 0); \
4510 #undef PLAT_x86_linux
4511 #undef PLAT_amd64_linux
4512 #undef PLAT_ppc32_linux
4513 #undef PLAT_ppc64_linux
4514 #undef PLAT_arm_linux
4515 #undef PLAT_ppc32_aix5
4516 #undef PLAT_ppc64_aix5
4518 #endif /* __VALGRIND_H */