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-2010 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. */
76 FILE_LICENCE ( BSD3 );
79 /* ------------------------------------------------------------------ */
80 /* VERSION NUMBER OF VALGRIND */
81 /* ------------------------------------------------------------------ */
83 /* Specify Valgrind's version number, so that user code can
84 conditionally compile based on our version number. Note that these
85 were introduced at version 3.6 and so do not exist in version 3.5
86 or earlier. The recommended way to use them to check for "version
89 #if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
90 && (__VALGRIND_MAJOR__ > 3 \
91 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
93 #define __VALGRIND_MAJOR__ 3
94 #define __VALGRIND_MINOR__ 6
99 /* Nb: this file might be included in a file compiled with -ansi. So
100 we can't use C++ style "//" comments nor the "asm" keyword (instead
103 /* Derive some tags indicating what the target platform is. Note
104 that in this file we're using the compiler's CPP symbols for
105 identifying architectures, which are different to the ones we use
106 within the rest of Valgrind. Note, __powerpc__ is active for both
107 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
108 latter (on Linux, that is).
110 Misc note: how to find out what's predefined in gcc by default:
111 gcc -Wp,-dM somefile.c
113 #undef PLAT_ppc64_aix5
114 #undef PLAT_ppc32_aix5
115 #undef PLAT_x86_darwin
116 #undef PLAT_amd64_darwin
117 #undef PLAT_x86_linux
118 #undef PLAT_amd64_linux
119 #undef PLAT_ppc32_linux
120 #undef PLAT_ppc64_linux
121 #undef PLAT_arm_linux
123 #if defined(_AIX) && defined(__64BIT__)
124 # define PLAT_ppc64_aix5 1
125 #elif defined(_AIX) && !defined(__64BIT__)
126 # define PLAT_ppc32_aix5 1
127 #elif defined(__APPLE__) && defined(__i386__)
128 # define PLAT_x86_darwin 1
129 #elif defined(__APPLE__) && defined(__x86_64__)
130 # define PLAT_amd64_darwin 1
131 #elif defined(__linux__) && defined(__i386__)
132 # define PLAT_x86_linux 1
133 #elif defined(__linux__) && defined(__x86_64__)
134 # define PLAT_amd64_linux 1
135 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
136 # define PLAT_ppc32_linux 1
137 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
138 # define PLAT_ppc64_linux 1
139 #elif defined(__linux__) && defined(__arm__)
140 # define PLAT_arm_linux 1
142 /* If we're not compiling for our target platform, don't generate
144 # if !defined(NVALGRIND)
150 /* ------------------------------------------------------------------ */
151 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
152 /* in here of use to end-users -- skip to the next section. */
153 /* ------------------------------------------------------------------ */
155 #if defined(NVALGRIND)
157 /* Define NVALGRIND to completely remove the Valgrind magic sequence
158 from the compiled code (analogous to NDEBUG's effects on
160 #define VALGRIND_DO_CLIENT_REQUEST( \
161 _zzq_rlval, _zzq_default, _zzq_request, \
162 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
164 (_zzq_rlval) = (_zzq_default); \
167 #else /* ! NVALGRIND */
169 /* The following defines the magic code sequences which the JITter
170 spots and handles magically. Don't look too closely at them as
171 they will rot your brain.
173 The assembly code sequences for all architectures is in this one
174 file. This is because this file must be stand-alone, and we don't
175 want to have multiple files.
177 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
178 value gets put in the return slot, so that everything works when
179 this is executed not under Valgrind. Args are passed in a memory
180 block, and so there's no intrinsic limit to the number that could
181 be passed, but it's currently five.
184 _zzq_rlval result lvalue
185 _zzq_default default value (result returned when running on real CPU)
186 _zzq_request request code
187 _zzq_arg1..5 request params
189 The other two macros are used to support function wrapping, and are
190 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
191 guest's NRADDR pseudo-register and whatever other information is
192 needed to safely run the call original from the wrapper: on
193 ppc64-linux, the R2 value at the divert point is also needed. This
194 information is abstracted into a user-visible type, OrigFn.
196 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
197 guest, but guarantees that the branch instruction will not be
198 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
199 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
200 complete inline asm, since it needs to be combined with more magic
201 inline asm stuff to be useful.
204 /* ------------------------- x86-{linux,darwin} ---------------- */
206 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
210 unsigned int nraddr; /* where's the code? */
214 #define __SPECIAL_INSTRUCTION_PREAMBLE \
215 "roll $3, %%edi ; roll $13, %%edi\n\t" \
216 "roll $29, %%edi ; roll $19, %%edi\n\t"
218 #define VALGRIND_DO_CLIENT_REQUEST( \
219 _zzq_rlval, _zzq_default, _zzq_request, \
220 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
221 { volatile unsigned int _zzq_args[6]; \
222 volatile unsigned int _zzq_result; \
223 _zzq_args[0] = (unsigned int)(_zzq_request); \
224 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
225 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
226 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
227 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
228 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
229 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
230 /* %EDX = client_request ( %EAX ) */ \
231 "xchgl %%ebx,%%ebx" \
232 : "=d" (_zzq_result) \
233 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
236 _zzq_rlval = _zzq_result; \
239 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
240 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
241 volatile unsigned int __addr; \
242 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
243 /* %EAX = guest_NRADDR */ \
244 "xchgl %%ecx,%%ecx" \
249 _zzq_orig->nraddr = __addr; \
252 #define VALGRIND_CALL_NOREDIR_EAX \
253 __SPECIAL_INSTRUCTION_PREAMBLE \
254 /* call-noredir *%EAX */ \
255 "xchgl %%edx,%%edx\n\t"
256 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
258 /* ------------------------ amd64-{linux,darwin} --------------- */
260 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
264 unsigned long long int nraddr; /* where's the code? */
268 #define __SPECIAL_INSTRUCTION_PREAMBLE \
269 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
270 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
272 #define VALGRIND_DO_CLIENT_REQUEST( \
273 _zzq_rlval, _zzq_default, _zzq_request, \
274 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
275 { volatile unsigned long long int _zzq_args[6]; \
276 volatile unsigned long long int _zzq_result; \
277 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
278 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
279 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
280 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
281 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
282 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
283 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
284 /* %RDX = client_request ( %RAX ) */ \
285 "xchgq %%rbx,%%rbx" \
286 : "=d" (_zzq_result) \
287 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
290 _zzq_rlval = _zzq_result; \
293 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
294 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
295 volatile unsigned long long int __addr; \
296 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
297 /* %RAX = guest_NRADDR */ \
298 "xchgq %%rcx,%%rcx" \
303 _zzq_orig->nraddr = __addr; \
306 #define VALGRIND_CALL_NOREDIR_RAX \
307 __SPECIAL_INSTRUCTION_PREAMBLE \
308 /* call-noredir *%RAX */ \
309 "xchgq %%rdx,%%rdx\n\t"
310 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
312 /* ------------------------ ppc32-linux ------------------------ */
314 #if defined(PLAT_ppc32_linux)
318 unsigned int nraddr; /* where's the code? */
322 #define __SPECIAL_INSTRUCTION_PREAMBLE \
323 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
324 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
326 #define VALGRIND_DO_CLIENT_REQUEST( \
327 _zzq_rlval, _zzq_default, _zzq_request, \
328 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
330 { unsigned int _zzq_args[6]; \
331 unsigned int _zzq_result; \
332 unsigned int* _zzq_ptr; \
333 _zzq_args[0] = (unsigned int)(_zzq_request); \
334 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
335 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
336 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
337 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
338 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
339 _zzq_ptr = _zzq_args; \
340 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
341 "mr 4,%2\n\t" /*ptr*/ \
342 __SPECIAL_INSTRUCTION_PREAMBLE \
343 /* %R3 = client_request ( %R4 ) */ \
345 "mr %0,3" /*result*/ \
346 : "=b" (_zzq_result) \
347 : "b" (_zzq_default), "b" (_zzq_ptr) \
348 : "cc", "memory", "r3", "r4"); \
349 _zzq_rlval = _zzq_result; \
352 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
353 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
354 unsigned int __addr; \
355 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
356 /* %R3 = guest_NRADDR */ \
361 : "cc", "memory", "r3" \
363 _zzq_orig->nraddr = __addr; \
366 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
367 __SPECIAL_INSTRUCTION_PREAMBLE \
368 /* branch-and-link-to-noredir *%R11 */ \
370 #endif /* PLAT_ppc32_linux */
372 /* ------------------------ ppc64-linux ------------------------ */
374 #if defined(PLAT_ppc64_linux)
378 unsigned long long int nraddr; /* where's the code? */
379 unsigned long long int r2; /* what tocptr do we need? */
383 #define __SPECIAL_INSTRUCTION_PREAMBLE \
384 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
385 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
387 #define VALGRIND_DO_CLIENT_REQUEST( \
388 _zzq_rlval, _zzq_default, _zzq_request, \
389 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
391 { unsigned long long int _zzq_args[6]; \
392 register unsigned long long int _zzq_result __asm__("r3"); \
393 register unsigned long long int* _zzq_ptr __asm__("r4"); \
394 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
395 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
396 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
397 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
398 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
399 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
400 _zzq_ptr = _zzq_args; \
401 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
402 /* %R3 = client_request ( %R4 ) */ \
404 : "=r" (_zzq_result) \
405 : "0" (_zzq_default), "r" (_zzq_ptr) \
407 _zzq_rlval = _zzq_result; \
410 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
411 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
412 register unsigned long long int __addr __asm__("r3"); \
413 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
414 /* %R3 = guest_NRADDR */ \
420 _zzq_orig->nraddr = __addr; \
421 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
422 /* %R3 = guest_NRADDR_GPR2 */ \
428 _zzq_orig->r2 = __addr; \
431 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
432 __SPECIAL_INSTRUCTION_PREAMBLE \
433 /* branch-and-link-to-noredir *%R11 */ \
436 #endif /* PLAT_ppc64_linux */
438 /* ------------------------- arm-linux ------------------------- */
440 #if defined(PLAT_arm_linux)
444 unsigned int nraddr; /* where's the code? */
448 #define __SPECIAL_INSTRUCTION_PREAMBLE \
449 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
450 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
452 #define VALGRIND_DO_CLIENT_REQUEST( \
453 _zzq_rlval, _zzq_default, _zzq_request, \
454 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
456 { volatile unsigned int _zzq_args[6]; \
457 volatile unsigned int _zzq_result; \
458 _zzq_args[0] = (unsigned int)(_zzq_request); \
459 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
460 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
461 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
462 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
463 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
464 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
465 "mov r4, %2\n\t" /*ptr*/ \
466 __SPECIAL_INSTRUCTION_PREAMBLE \
467 /* R3 = client_request ( R4 ) */ \
468 "orr r10, r10, r10\n\t" \
469 "mov %0, r3" /*result*/ \
470 : "=r" (_zzq_result) \
471 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
472 : "cc","memory", "r3", "r4"); \
473 _zzq_rlval = _zzq_result; \
476 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
477 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
478 unsigned int __addr; \
479 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
480 /* R3 = guest_NRADDR */ \
481 "orr r11, r11, r11\n\t" \
485 : "cc", "memory", "r3" \
487 _zzq_orig->nraddr = __addr; \
490 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
491 __SPECIAL_INSTRUCTION_PREAMBLE \
492 /* branch-and-link-to-noredir *%R4 */ \
493 "orr r12, r12, r12\n\t"
495 #endif /* PLAT_arm_linux */
497 /* ------------------------ ppc32-aix5 ------------------------- */
499 #if defined(PLAT_ppc32_aix5)
503 unsigned int nraddr; /* where's the code? */
504 unsigned int r2; /* what tocptr do we need? */
508 #define __SPECIAL_INSTRUCTION_PREAMBLE \
509 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
510 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
512 #define VALGRIND_DO_CLIENT_REQUEST( \
513 _zzq_rlval, _zzq_default, _zzq_request, \
514 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
516 { unsigned int _zzq_args[7]; \
517 register unsigned int _zzq_result; \
518 register unsigned int* _zzq_ptr; \
519 _zzq_args[0] = (unsigned int)(_zzq_request); \
520 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
521 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
522 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
523 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
524 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
525 _zzq_args[6] = (unsigned int)(_zzq_default); \
526 _zzq_ptr = _zzq_args; \
527 __asm__ volatile("mr 4,%1\n\t" \
529 __SPECIAL_INSTRUCTION_PREAMBLE \
530 /* %R3 = client_request ( %R4 ) */ \
533 : "=b" (_zzq_result) \
535 : "r3", "r4", "cc", "memory"); \
536 _zzq_rlval = _zzq_result; \
539 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
540 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
541 register unsigned int __addr; \
542 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
543 /* %R3 = guest_NRADDR */ \
548 : "r3", "cc", "memory" \
550 _zzq_orig->nraddr = __addr; \
551 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
552 /* %R3 = guest_NRADDR_GPR2 */ \
557 : "r3", "cc", "memory" \
559 _zzq_orig->r2 = __addr; \
562 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
563 __SPECIAL_INSTRUCTION_PREAMBLE \
564 /* branch-and-link-to-noredir *%R11 */ \
567 #endif /* PLAT_ppc32_aix5 */
569 /* ------------------------ ppc64-aix5 ------------------------- */
571 #if defined(PLAT_ppc64_aix5)
575 unsigned long long int nraddr; /* where's the code? */
576 unsigned long long int r2; /* what tocptr do we need? */
580 #define __SPECIAL_INSTRUCTION_PREAMBLE \
581 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
582 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
584 #define VALGRIND_DO_CLIENT_REQUEST( \
585 _zzq_rlval, _zzq_default, _zzq_request, \
586 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
588 { unsigned long long int _zzq_args[7]; \
589 register unsigned long long int _zzq_result; \
590 register unsigned long long int* _zzq_ptr; \
591 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
592 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
593 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
594 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
595 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
596 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
597 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
598 _zzq_ptr = _zzq_args; \
599 __asm__ volatile("mr 4,%1\n\t" \
601 __SPECIAL_INSTRUCTION_PREAMBLE \
602 /* %R3 = client_request ( %R4 ) */ \
605 : "=b" (_zzq_result) \
607 : "r3", "r4", "cc", "memory"); \
608 _zzq_rlval = _zzq_result; \
611 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
612 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
613 register unsigned long long int __addr; \
614 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
615 /* %R3 = guest_NRADDR */ \
620 : "r3", "cc", "memory" \
622 _zzq_orig->nraddr = __addr; \
623 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
624 /* %R3 = guest_NRADDR_GPR2 */ \
629 : "r3", "cc", "memory" \
631 _zzq_orig->r2 = __addr; \
634 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
635 __SPECIAL_INSTRUCTION_PREAMBLE \
636 /* branch-and-link-to-noredir *%R11 */ \
639 #endif /* PLAT_ppc64_aix5 */
641 /* Insert assembly code for other platforms here... */
643 #endif /* NVALGRIND */
646 /* ------------------------------------------------------------------ */
647 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
648 /* ugly. It's the least-worst tradeoff I can think of. */
649 /* ------------------------------------------------------------------ */
651 /* This section defines magic (a.k.a appalling-hack) macros for doing
652 guaranteed-no-redirection macros, so as to get from function
653 wrappers to the functions they are wrapping. The whole point is to
654 construct standard call sequences, but to do the call itself with a
655 special no-redirect call pseudo-instruction that the JIT
656 understands and handles specially. This section is long and
657 repetitious, and I can't see a way to make it shorter.
659 The naming scheme is as follows:
661 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
663 'W' stands for "word" and 'v' for "void". Hence there are
664 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
665 and for each, the possibility of returning a word-typed result, or
669 /* Use these to write the name of your wrapper. NOTE: duplicates
670 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
672 /* Use an extra level of macroisation so as to ensure the soname/fnname
673 args are fully macro-expanded before pasting them together. */
674 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
676 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
677 VG_CONCAT4(_vgwZU_,soname,_,fnname)
679 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
680 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
682 /* Use this macro from within a wrapper function to collect the
683 context (address and possibly other info) of the original function.
684 Once you have that you can then use it in one of the CALL_FN_
685 macros. The type of the argument _lval is OrigFn. */
686 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
688 /* Derivatives of the main macros below, for calling functions
691 #define CALL_FN_v_v(fnptr) \
692 do { volatile unsigned long _junk; \
693 CALL_FN_W_v(_junk,fnptr); } while (0)
695 #define CALL_FN_v_W(fnptr, arg1) \
696 do { volatile unsigned long _junk; \
697 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
699 #define CALL_FN_v_WW(fnptr, arg1,arg2) \
700 do { volatile unsigned long _junk; \
701 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
703 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
704 do { volatile unsigned long _junk; \
705 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
707 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
708 do { volatile unsigned long _junk; \
709 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
711 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
712 do { volatile unsigned long _junk; \
713 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
715 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
716 do { volatile unsigned long _junk; \
717 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
719 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
720 do { volatile unsigned long _junk; \
721 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
723 /* ------------------------- x86-{linux,darwin} ---------------- */
725 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
727 /* These regs are trashed by the hidden call. No need to mention eax
728 as gcc can already see that, plus causes gcc to bomb. */
729 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
731 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
734 #define CALL_FN_W_v(lval, orig) \
736 volatile OrigFn _orig = (orig); \
737 volatile unsigned long _argvec[1]; \
738 volatile unsigned long _res; \
739 _argvec[0] = (unsigned long)_orig.nraddr; \
741 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
742 VALGRIND_CALL_NOREDIR_EAX \
743 : /*out*/ "=a" (_res) \
744 : /*in*/ "a" (&_argvec[0]) \
745 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
747 lval = (__typeof__(lval)) _res; \
750 #define CALL_FN_W_W(lval, orig, arg1) \
752 volatile OrigFn _orig = (orig); \
753 volatile unsigned long _argvec[2]; \
754 volatile unsigned long _res; \
755 _argvec[0] = (unsigned long)_orig.nraddr; \
756 _argvec[1] = (unsigned long)(arg1); \
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_WW(lval, orig, arg1,arg2) \
771 volatile OrigFn _orig = (orig); \
772 volatile unsigned long _argvec[3]; \
773 volatile unsigned long _res; \
774 _argvec[0] = (unsigned long)_orig.nraddr; \
775 _argvec[1] = (unsigned long)(arg1); \
776 _argvec[2] = (unsigned long)(arg2); \
778 "pushl 8(%%eax)\n\t" \
779 "pushl 4(%%eax)\n\t" \
780 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
781 VALGRIND_CALL_NOREDIR_EAX \
783 : /*out*/ "=a" (_res) \
784 : /*in*/ "a" (&_argvec[0]) \
785 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
787 lval = (__typeof__(lval)) _res; \
790 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
792 volatile OrigFn _orig = (orig); \
793 volatile unsigned long _argvec[4]; \
794 volatile unsigned long _res; \
795 _argvec[0] = (unsigned long)_orig.nraddr; \
796 _argvec[1] = (unsigned long)(arg1); \
797 _argvec[2] = (unsigned long)(arg2); \
798 _argvec[3] = (unsigned long)(arg3); \
800 "pushl 12(%%eax)\n\t" \
801 "pushl 8(%%eax)\n\t" \
802 "pushl 4(%%eax)\n\t" \
803 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
804 VALGRIND_CALL_NOREDIR_EAX \
805 "addl $12, %%esp\n" \
806 : /*out*/ "=a" (_res) \
807 : /*in*/ "a" (&_argvec[0]) \
808 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
810 lval = (__typeof__(lval)) _res; \
813 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
815 volatile OrigFn _orig = (orig); \
816 volatile unsigned long _argvec[5]; \
817 volatile unsigned long _res; \
818 _argvec[0] = (unsigned long)_orig.nraddr; \
819 _argvec[1] = (unsigned long)(arg1); \
820 _argvec[2] = (unsigned long)(arg2); \
821 _argvec[3] = (unsigned long)(arg3); \
822 _argvec[4] = (unsigned long)(arg4); \
824 "pushl 16(%%eax)\n\t" \
825 "pushl 12(%%eax)\n\t" \
826 "pushl 8(%%eax)\n\t" \
827 "pushl 4(%%eax)\n\t" \
828 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
829 VALGRIND_CALL_NOREDIR_EAX \
830 "addl $16, %%esp\n" \
831 : /*out*/ "=a" (_res) \
832 : /*in*/ "a" (&_argvec[0]) \
833 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
835 lval = (__typeof__(lval)) _res; \
838 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
840 volatile OrigFn _orig = (orig); \
841 volatile unsigned long _argvec[6]; \
842 volatile unsigned long _res; \
843 _argvec[0] = (unsigned long)_orig.nraddr; \
844 _argvec[1] = (unsigned long)(arg1); \
845 _argvec[2] = (unsigned long)(arg2); \
846 _argvec[3] = (unsigned long)(arg3); \
847 _argvec[4] = (unsigned long)(arg4); \
848 _argvec[5] = (unsigned long)(arg5); \
850 "pushl 20(%%eax)\n\t" \
851 "pushl 16(%%eax)\n\t" \
852 "pushl 12(%%eax)\n\t" \
853 "pushl 8(%%eax)\n\t" \
854 "pushl 4(%%eax)\n\t" \
855 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
856 VALGRIND_CALL_NOREDIR_EAX \
857 "addl $20, %%esp\n" \
858 : /*out*/ "=a" (_res) \
859 : /*in*/ "a" (&_argvec[0]) \
860 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
862 lval = (__typeof__(lval)) _res; \
865 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
867 volatile OrigFn _orig = (orig); \
868 volatile unsigned long _argvec[7]; \
869 volatile unsigned long _res; \
870 _argvec[0] = (unsigned long)_orig.nraddr; \
871 _argvec[1] = (unsigned long)(arg1); \
872 _argvec[2] = (unsigned long)(arg2); \
873 _argvec[3] = (unsigned long)(arg3); \
874 _argvec[4] = (unsigned long)(arg4); \
875 _argvec[5] = (unsigned long)(arg5); \
876 _argvec[6] = (unsigned long)(arg6); \
878 "pushl 24(%%eax)\n\t" \
879 "pushl 20(%%eax)\n\t" \
880 "pushl 16(%%eax)\n\t" \
881 "pushl 12(%%eax)\n\t" \
882 "pushl 8(%%eax)\n\t" \
883 "pushl 4(%%eax)\n\t" \
884 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
885 VALGRIND_CALL_NOREDIR_EAX \
886 "addl $24, %%esp\n" \
887 : /*out*/ "=a" (_res) \
888 : /*in*/ "a" (&_argvec[0]) \
889 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
891 lval = (__typeof__(lval)) _res; \
894 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
897 volatile OrigFn _orig = (orig); \
898 volatile unsigned long _argvec[8]; \
899 volatile unsigned long _res; \
900 _argvec[0] = (unsigned long)_orig.nraddr; \
901 _argvec[1] = (unsigned long)(arg1); \
902 _argvec[2] = (unsigned long)(arg2); \
903 _argvec[3] = (unsigned long)(arg3); \
904 _argvec[4] = (unsigned long)(arg4); \
905 _argvec[5] = (unsigned long)(arg5); \
906 _argvec[6] = (unsigned long)(arg6); \
907 _argvec[7] = (unsigned long)(arg7); \
909 "pushl 28(%%eax)\n\t" \
910 "pushl 24(%%eax)\n\t" \
911 "pushl 20(%%eax)\n\t" \
912 "pushl 16(%%eax)\n\t" \
913 "pushl 12(%%eax)\n\t" \
914 "pushl 8(%%eax)\n\t" \
915 "pushl 4(%%eax)\n\t" \
916 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
917 VALGRIND_CALL_NOREDIR_EAX \
918 "addl $28, %%esp\n" \
919 : /*out*/ "=a" (_res) \
920 : /*in*/ "a" (&_argvec[0]) \
921 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
923 lval = (__typeof__(lval)) _res; \
926 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
929 volatile OrigFn _orig = (orig); \
930 volatile unsigned long _argvec[9]; \
931 volatile unsigned long _res; \
932 _argvec[0] = (unsigned long)_orig.nraddr; \
933 _argvec[1] = (unsigned long)(arg1); \
934 _argvec[2] = (unsigned long)(arg2); \
935 _argvec[3] = (unsigned long)(arg3); \
936 _argvec[4] = (unsigned long)(arg4); \
937 _argvec[5] = (unsigned long)(arg5); \
938 _argvec[6] = (unsigned long)(arg6); \
939 _argvec[7] = (unsigned long)(arg7); \
940 _argvec[8] = (unsigned long)(arg8); \
942 "pushl 32(%%eax)\n\t" \
943 "pushl 28(%%eax)\n\t" \
944 "pushl 24(%%eax)\n\t" \
945 "pushl 20(%%eax)\n\t" \
946 "pushl 16(%%eax)\n\t" \
947 "pushl 12(%%eax)\n\t" \
948 "pushl 8(%%eax)\n\t" \
949 "pushl 4(%%eax)\n\t" \
950 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
951 VALGRIND_CALL_NOREDIR_EAX \
952 "addl $32, %%esp\n" \
953 : /*out*/ "=a" (_res) \
954 : /*in*/ "a" (&_argvec[0]) \
955 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
957 lval = (__typeof__(lval)) _res; \
960 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
963 volatile OrigFn _orig = (orig); \
964 volatile unsigned long _argvec[10]; \
965 volatile unsigned long _res; \
966 _argvec[0] = (unsigned long)_orig.nraddr; \
967 _argvec[1] = (unsigned long)(arg1); \
968 _argvec[2] = (unsigned long)(arg2); \
969 _argvec[3] = (unsigned long)(arg3); \
970 _argvec[4] = (unsigned long)(arg4); \
971 _argvec[5] = (unsigned long)(arg5); \
972 _argvec[6] = (unsigned long)(arg6); \
973 _argvec[7] = (unsigned long)(arg7); \
974 _argvec[8] = (unsigned long)(arg8); \
975 _argvec[9] = (unsigned long)(arg9); \
977 "pushl 36(%%eax)\n\t" \
978 "pushl 32(%%eax)\n\t" \
979 "pushl 28(%%eax)\n\t" \
980 "pushl 24(%%eax)\n\t" \
981 "pushl 20(%%eax)\n\t" \
982 "pushl 16(%%eax)\n\t" \
983 "pushl 12(%%eax)\n\t" \
984 "pushl 8(%%eax)\n\t" \
985 "pushl 4(%%eax)\n\t" \
986 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
987 VALGRIND_CALL_NOREDIR_EAX \
988 "addl $36, %%esp\n" \
989 : /*out*/ "=a" (_res) \
990 : /*in*/ "a" (&_argvec[0]) \
991 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
993 lval = (__typeof__(lval)) _res; \
996 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
997 arg7,arg8,arg9,arg10) \
999 volatile OrigFn _orig = (orig); \
1000 volatile unsigned long _argvec[11]; \
1001 volatile unsigned long _res; \
1002 _argvec[0] = (unsigned long)_orig.nraddr; \
1003 _argvec[1] = (unsigned long)(arg1); \
1004 _argvec[2] = (unsigned long)(arg2); \
1005 _argvec[3] = (unsigned long)(arg3); \
1006 _argvec[4] = (unsigned long)(arg4); \
1007 _argvec[5] = (unsigned long)(arg5); \
1008 _argvec[6] = (unsigned long)(arg6); \
1009 _argvec[7] = (unsigned long)(arg7); \
1010 _argvec[8] = (unsigned long)(arg8); \
1011 _argvec[9] = (unsigned long)(arg9); \
1012 _argvec[10] = (unsigned long)(arg10); \
1014 "pushl 40(%%eax)\n\t" \
1015 "pushl 36(%%eax)\n\t" \
1016 "pushl 32(%%eax)\n\t" \
1017 "pushl 28(%%eax)\n\t" \
1018 "pushl 24(%%eax)\n\t" \
1019 "pushl 20(%%eax)\n\t" \
1020 "pushl 16(%%eax)\n\t" \
1021 "pushl 12(%%eax)\n\t" \
1022 "pushl 8(%%eax)\n\t" \
1023 "pushl 4(%%eax)\n\t" \
1024 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1025 VALGRIND_CALL_NOREDIR_EAX \
1026 "addl $40, %%esp\n" \
1027 : /*out*/ "=a" (_res) \
1028 : /*in*/ "a" (&_argvec[0]) \
1029 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1031 lval = (__typeof__(lval)) _res; \
1034 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1035 arg6,arg7,arg8,arg9,arg10, \
1038 volatile OrigFn _orig = (orig); \
1039 volatile unsigned long _argvec[12]; \
1040 volatile unsigned long _res; \
1041 _argvec[0] = (unsigned long)_orig.nraddr; \
1042 _argvec[1] = (unsigned long)(arg1); \
1043 _argvec[2] = (unsigned long)(arg2); \
1044 _argvec[3] = (unsigned long)(arg3); \
1045 _argvec[4] = (unsigned long)(arg4); \
1046 _argvec[5] = (unsigned long)(arg5); \
1047 _argvec[6] = (unsigned long)(arg6); \
1048 _argvec[7] = (unsigned long)(arg7); \
1049 _argvec[8] = (unsigned long)(arg8); \
1050 _argvec[9] = (unsigned long)(arg9); \
1051 _argvec[10] = (unsigned long)(arg10); \
1052 _argvec[11] = (unsigned long)(arg11); \
1054 "pushl 44(%%eax)\n\t" \
1055 "pushl 40(%%eax)\n\t" \
1056 "pushl 36(%%eax)\n\t" \
1057 "pushl 32(%%eax)\n\t" \
1058 "pushl 28(%%eax)\n\t" \
1059 "pushl 24(%%eax)\n\t" \
1060 "pushl 20(%%eax)\n\t" \
1061 "pushl 16(%%eax)\n\t" \
1062 "pushl 12(%%eax)\n\t" \
1063 "pushl 8(%%eax)\n\t" \
1064 "pushl 4(%%eax)\n\t" \
1065 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1066 VALGRIND_CALL_NOREDIR_EAX \
1067 "addl $44, %%esp\n" \
1068 : /*out*/ "=a" (_res) \
1069 : /*in*/ "a" (&_argvec[0]) \
1070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1072 lval = (__typeof__(lval)) _res; \
1075 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1076 arg6,arg7,arg8,arg9,arg10, \
1079 volatile OrigFn _orig = (orig); \
1080 volatile unsigned long _argvec[13]; \
1081 volatile unsigned long _res; \
1082 _argvec[0] = (unsigned long)_orig.nraddr; \
1083 _argvec[1] = (unsigned long)(arg1); \
1084 _argvec[2] = (unsigned long)(arg2); \
1085 _argvec[3] = (unsigned long)(arg3); \
1086 _argvec[4] = (unsigned long)(arg4); \
1087 _argvec[5] = (unsigned long)(arg5); \
1088 _argvec[6] = (unsigned long)(arg6); \
1089 _argvec[7] = (unsigned long)(arg7); \
1090 _argvec[8] = (unsigned long)(arg8); \
1091 _argvec[9] = (unsigned long)(arg9); \
1092 _argvec[10] = (unsigned long)(arg10); \
1093 _argvec[11] = (unsigned long)(arg11); \
1094 _argvec[12] = (unsigned long)(arg12); \
1096 "pushl 48(%%eax)\n\t" \
1097 "pushl 44(%%eax)\n\t" \
1098 "pushl 40(%%eax)\n\t" \
1099 "pushl 36(%%eax)\n\t" \
1100 "pushl 32(%%eax)\n\t" \
1101 "pushl 28(%%eax)\n\t" \
1102 "pushl 24(%%eax)\n\t" \
1103 "pushl 20(%%eax)\n\t" \
1104 "pushl 16(%%eax)\n\t" \
1105 "pushl 12(%%eax)\n\t" \
1106 "pushl 8(%%eax)\n\t" \
1107 "pushl 4(%%eax)\n\t" \
1108 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1109 VALGRIND_CALL_NOREDIR_EAX \
1110 "addl $48, %%esp\n" \
1111 : /*out*/ "=a" (_res) \
1112 : /*in*/ "a" (&_argvec[0]) \
1113 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1115 lval = (__typeof__(lval)) _res; \
1118 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
1120 /* ------------------------ amd64-{linux,darwin} --------------- */
1122 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
1124 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1126 /* These regs are trashed by the hidden call. */
1127 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1128 "rdi", "r8", "r9", "r10", "r11"
1130 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1133 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1134 macros. In order not to trash the stack redzone, we need to drop
1135 %rsp by 128 before the hidden call, and restore afterwards. The
1136 nastyness is that it is only by luck that the stack still appears
1137 to be unwindable during the hidden call - since then the behaviour
1138 of any routine using this macro does not match what the CFI data
1141 Why is this important? Imagine that a wrapper has a stack
1142 allocated local, and passes to the hidden call, a pointer to it.
1143 Because gcc does not know about the hidden call, it may allocate
1144 that local in the redzone. Unfortunately the hidden call may then
1145 trash it before it comes to use it. So we must step clear of the
1146 redzone, for the duration of the hidden call, to make it safe.
1148 Probably the same problem afflicts the other redzone-style ABIs too
1149 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1150 self describing (none of this CFI nonsense) so at least messing
1151 with the stack pointer doesn't give a danger of non-unwindable
1154 #define CALL_FN_W_v(lval, orig) \
1156 volatile OrigFn _orig = (orig); \
1157 volatile unsigned long _argvec[1]; \
1158 volatile unsigned long _res; \
1159 _argvec[0] = (unsigned long)_orig.nraddr; \
1161 "subq $128,%%rsp\n\t" \
1162 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1163 VALGRIND_CALL_NOREDIR_RAX \
1164 "addq $128,%%rsp\n\t" \
1165 : /*out*/ "=a" (_res) \
1166 : /*in*/ "a" (&_argvec[0]) \
1167 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1169 lval = (__typeof__(lval)) _res; \
1172 #define CALL_FN_W_W(lval, orig, arg1) \
1174 volatile OrigFn _orig = (orig); \
1175 volatile unsigned long _argvec[2]; \
1176 volatile unsigned long _res; \
1177 _argvec[0] = (unsigned long)_orig.nraddr; \
1178 _argvec[1] = (unsigned long)(arg1); \
1180 "subq $128,%%rsp\n\t" \
1181 "movq 8(%%rax), %%rdi\n\t" \
1182 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1183 VALGRIND_CALL_NOREDIR_RAX \
1184 "addq $128,%%rsp\n\t" \
1185 : /*out*/ "=a" (_res) \
1186 : /*in*/ "a" (&_argvec[0]) \
1187 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1189 lval = (__typeof__(lval)) _res; \
1192 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1194 volatile OrigFn _orig = (orig); \
1195 volatile unsigned long _argvec[3]; \
1196 volatile unsigned long _res; \
1197 _argvec[0] = (unsigned long)_orig.nraddr; \
1198 _argvec[1] = (unsigned long)(arg1); \
1199 _argvec[2] = (unsigned long)(arg2); \
1201 "subq $128,%%rsp\n\t" \
1202 "movq 16(%%rax), %%rsi\n\t" \
1203 "movq 8(%%rax), %%rdi\n\t" \
1204 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1205 VALGRIND_CALL_NOREDIR_RAX \
1206 "addq $128,%%rsp\n\t" \
1207 : /*out*/ "=a" (_res) \
1208 : /*in*/ "a" (&_argvec[0]) \
1209 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1211 lval = (__typeof__(lval)) _res; \
1214 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1216 volatile OrigFn _orig = (orig); \
1217 volatile unsigned long _argvec[4]; \
1218 volatile unsigned long _res; \
1219 _argvec[0] = (unsigned long)_orig.nraddr; \
1220 _argvec[1] = (unsigned long)(arg1); \
1221 _argvec[2] = (unsigned long)(arg2); \
1222 _argvec[3] = (unsigned long)(arg3); \
1224 "subq $128,%%rsp\n\t" \
1225 "movq 24(%%rax), %%rdx\n\t" \
1226 "movq 16(%%rax), %%rsi\n\t" \
1227 "movq 8(%%rax), %%rdi\n\t" \
1228 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1229 VALGRIND_CALL_NOREDIR_RAX \
1230 "addq $128,%%rsp\n\t" \
1231 : /*out*/ "=a" (_res) \
1232 : /*in*/ "a" (&_argvec[0]) \
1233 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1235 lval = (__typeof__(lval)) _res; \
1238 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1240 volatile OrigFn _orig = (orig); \
1241 volatile unsigned long _argvec[5]; \
1242 volatile unsigned long _res; \
1243 _argvec[0] = (unsigned long)_orig.nraddr; \
1244 _argvec[1] = (unsigned long)(arg1); \
1245 _argvec[2] = (unsigned long)(arg2); \
1246 _argvec[3] = (unsigned long)(arg3); \
1247 _argvec[4] = (unsigned long)(arg4); \
1249 "subq $128,%%rsp\n\t" \
1250 "movq 32(%%rax), %%rcx\n\t" \
1251 "movq 24(%%rax), %%rdx\n\t" \
1252 "movq 16(%%rax), %%rsi\n\t" \
1253 "movq 8(%%rax), %%rdi\n\t" \
1254 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1255 VALGRIND_CALL_NOREDIR_RAX \
1256 "addq $128,%%rsp\n\t" \
1257 : /*out*/ "=a" (_res) \
1258 : /*in*/ "a" (&_argvec[0]) \
1259 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1261 lval = (__typeof__(lval)) _res; \
1264 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1266 volatile OrigFn _orig = (orig); \
1267 volatile unsigned long _argvec[6]; \
1268 volatile unsigned long _res; \
1269 _argvec[0] = (unsigned long)_orig.nraddr; \
1270 _argvec[1] = (unsigned long)(arg1); \
1271 _argvec[2] = (unsigned long)(arg2); \
1272 _argvec[3] = (unsigned long)(arg3); \
1273 _argvec[4] = (unsigned long)(arg4); \
1274 _argvec[5] = (unsigned long)(arg5); \
1276 "subq $128,%%rsp\n\t" \
1277 "movq 40(%%rax), %%r8\n\t" \
1278 "movq 32(%%rax), %%rcx\n\t" \
1279 "movq 24(%%rax), %%rdx\n\t" \
1280 "movq 16(%%rax), %%rsi\n\t" \
1281 "movq 8(%%rax), %%rdi\n\t" \
1282 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1283 VALGRIND_CALL_NOREDIR_RAX \
1284 "addq $128,%%rsp\n\t" \
1285 : /*out*/ "=a" (_res) \
1286 : /*in*/ "a" (&_argvec[0]) \
1287 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1289 lval = (__typeof__(lval)) _res; \
1292 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1294 volatile OrigFn _orig = (orig); \
1295 volatile unsigned long _argvec[7]; \
1296 volatile unsigned long _res; \
1297 _argvec[0] = (unsigned long)_orig.nraddr; \
1298 _argvec[1] = (unsigned long)(arg1); \
1299 _argvec[2] = (unsigned long)(arg2); \
1300 _argvec[3] = (unsigned long)(arg3); \
1301 _argvec[4] = (unsigned long)(arg4); \
1302 _argvec[5] = (unsigned long)(arg5); \
1303 _argvec[6] = (unsigned long)(arg6); \
1305 "subq $128,%%rsp\n\t" \
1306 "movq 48(%%rax), %%r9\n\t" \
1307 "movq 40(%%rax), %%r8\n\t" \
1308 "movq 32(%%rax), %%rcx\n\t" \
1309 "movq 24(%%rax), %%rdx\n\t" \
1310 "movq 16(%%rax), %%rsi\n\t" \
1311 "movq 8(%%rax), %%rdi\n\t" \
1312 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1313 "addq $128,%%rsp\n\t" \
1314 VALGRIND_CALL_NOREDIR_RAX \
1315 : /*out*/ "=a" (_res) \
1316 : /*in*/ "a" (&_argvec[0]) \
1317 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1319 lval = (__typeof__(lval)) _res; \
1322 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1325 volatile OrigFn _orig = (orig); \
1326 volatile unsigned long _argvec[8]; \
1327 volatile unsigned long _res; \
1328 _argvec[0] = (unsigned long)_orig.nraddr; \
1329 _argvec[1] = (unsigned long)(arg1); \
1330 _argvec[2] = (unsigned long)(arg2); \
1331 _argvec[3] = (unsigned long)(arg3); \
1332 _argvec[4] = (unsigned long)(arg4); \
1333 _argvec[5] = (unsigned long)(arg5); \
1334 _argvec[6] = (unsigned long)(arg6); \
1335 _argvec[7] = (unsigned long)(arg7); \
1337 "subq $128,%%rsp\n\t" \
1338 "pushq 56(%%rax)\n\t" \
1339 "movq 48(%%rax), %%r9\n\t" \
1340 "movq 40(%%rax), %%r8\n\t" \
1341 "movq 32(%%rax), %%rcx\n\t" \
1342 "movq 24(%%rax), %%rdx\n\t" \
1343 "movq 16(%%rax), %%rsi\n\t" \
1344 "movq 8(%%rax), %%rdi\n\t" \
1345 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1346 VALGRIND_CALL_NOREDIR_RAX \
1347 "addq $8, %%rsp\n" \
1348 "addq $128,%%rsp\n\t" \
1349 : /*out*/ "=a" (_res) \
1350 : /*in*/ "a" (&_argvec[0]) \
1351 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1353 lval = (__typeof__(lval)) _res; \
1356 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1359 volatile OrigFn _orig = (orig); \
1360 volatile unsigned long _argvec[9]; \
1361 volatile unsigned long _res; \
1362 _argvec[0] = (unsigned long)_orig.nraddr; \
1363 _argvec[1] = (unsigned long)(arg1); \
1364 _argvec[2] = (unsigned long)(arg2); \
1365 _argvec[3] = (unsigned long)(arg3); \
1366 _argvec[4] = (unsigned long)(arg4); \
1367 _argvec[5] = (unsigned long)(arg5); \
1368 _argvec[6] = (unsigned long)(arg6); \
1369 _argvec[7] = (unsigned long)(arg7); \
1370 _argvec[8] = (unsigned long)(arg8); \
1372 "subq $128,%%rsp\n\t" \
1373 "pushq 64(%%rax)\n\t" \
1374 "pushq 56(%%rax)\n\t" \
1375 "movq 48(%%rax), %%r9\n\t" \
1376 "movq 40(%%rax), %%r8\n\t" \
1377 "movq 32(%%rax), %%rcx\n\t" \
1378 "movq 24(%%rax), %%rdx\n\t" \
1379 "movq 16(%%rax), %%rsi\n\t" \
1380 "movq 8(%%rax), %%rdi\n\t" \
1381 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1382 VALGRIND_CALL_NOREDIR_RAX \
1383 "addq $16, %%rsp\n" \
1384 "addq $128,%%rsp\n\t" \
1385 : /*out*/ "=a" (_res) \
1386 : /*in*/ "a" (&_argvec[0]) \
1387 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1389 lval = (__typeof__(lval)) _res; \
1392 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1395 volatile OrigFn _orig = (orig); \
1396 volatile unsigned long _argvec[10]; \
1397 volatile unsigned long _res; \
1398 _argvec[0] = (unsigned long)_orig.nraddr; \
1399 _argvec[1] = (unsigned long)(arg1); \
1400 _argvec[2] = (unsigned long)(arg2); \
1401 _argvec[3] = (unsigned long)(arg3); \
1402 _argvec[4] = (unsigned long)(arg4); \
1403 _argvec[5] = (unsigned long)(arg5); \
1404 _argvec[6] = (unsigned long)(arg6); \
1405 _argvec[7] = (unsigned long)(arg7); \
1406 _argvec[8] = (unsigned long)(arg8); \
1407 _argvec[9] = (unsigned long)(arg9); \
1409 "subq $128,%%rsp\n\t" \
1410 "pushq 72(%%rax)\n\t" \
1411 "pushq 64(%%rax)\n\t" \
1412 "pushq 56(%%rax)\n\t" \
1413 "movq 48(%%rax), %%r9\n\t" \
1414 "movq 40(%%rax), %%r8\n\t" \
1415 "movq 32(%%rax), %%rcx\n\t" \
1416 "movq 24(%%rax), %%rdx\n\t" \
1417 "movq 16(%%rax), %%rsi\n\t" \
1418 "movq 8(%%rax), %%rdi\n\t" \
1419 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1420 VALGRIND_CALL_NOREDIR_RAX \
1421 "addq $24, %%rsp\n" \
1422 "addq $128,%%rsp\n\t" \
1423 : /*out*/ "=a" (_res) \
1424 : /*in*/ "a" (&_argvec[0]) \
1425 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1427 lval = (__typeof__(lval)) _res; \
1430 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1431 arg7,arg8,arg9,arg10) \
1433 volatile OrigFn _orig = (orig); \
1434 volatile unsigned long _argvec[11]; \
1435 volatile unsigned long _res; \
1436 _argvec[0] = (unsigned long)_orig.nraddr; \
1437 _argvec[1] = (unsigned long)(arg1); \
1438 _argvec[2] = (unsigned long)(arg2); \
1439 _argvec[3] = (unsigned long)(arg3); \
1440 _argvec[4] = (unsigned long)(arg4); \
1441 _argvec[5] = (unsigned long)(arg5); \
1442 _argvec[6] = (unsigned long)(arg6); \
1443 _argvec[7] = (unsigned long)(arg7); \
1444 _argvec[8] = (unsigned long)(arg8); \
1445 _argvec[9] = (unsigned long)(arg9); \
1446 _argvec[10] = (unsigned long)(arg10); \
1448 "subq $128,%%rsp\n\t" \
1449 "pushq 80(%%rax)\n\t" \
1450 "pushq 72(%%rax)\n\t" \
1451 "pushq 64(%%rax)\n\t" \
1452 "pushq 56(%%rax)\n\t" \
1453 "movq 48(%%rax), %%r9\n\t" \
1454 "movq 40(%%rax), %%r8\n\t" \
1455 "movq 32(%%rax), %%rcx\n\t" \
1456 "movq 24(%%rax), %%rdx\n\t" \
1457 "movq 16(%%rax), %%rsi\n\t" \
1458 "movq 8(%%rax), %%rdi\n\t" \
1459 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1460 VALGRIND_CALL_NOREDIR_RAX \
1461 "addq $32, %%rsp\n" \
1462 "addq $128,%%rsp\n\t" \
1463 : /*out*/ "=a" (_res) \
1464 : /*in*/ "a" (&_argvec[0]) \
1465 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1467 lval = (__typeof__(lval)) _res; \
1470 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1471 arg7,arg8,arg9,arg10,arg11) \
1473 volatile OrigFn _orig = (orig); \
1474 volatile unsigned long _argvec[12]; \
1475 volatile unsigned long _res; \
1476 _argvec[0] = (unsigned long)_orig.nraddr; \
1477 _argvec[1] = (unsigned long)(arg1); \
1478 _argvec[2] = (unsigned long)(arg2); \
1479 _argvec[3] = (unsigned long)(arg3); \
1480 _argvec[4] = (unsigned long)(arg4); \
1481 _argvec[5] = (unsigned long)(arg5); \
1482 _argvec[6] = (unsigned long)(arg6); \
1483 _argvec[7] = (unsigned long)(arg7); \
1484 _argvec[8] = (unsigned long)(arg8); \
1485 _argvec[9] = (unsigned long)(arg9); \
1486 _argvec[10] = (unsigned long)(arg10); \
1487 _argvec[11] = (unsigned long)(arg11); \
1489 "subq $128,%%rsp\n\t" \
1490 "pushq 88(%%rax)\n\t" \
1491 "pushq 80(%%rax)\n\t" \
1492 "pushq 72(%%rax)\n\t" \
1493 "pushq 64(%%rax)\n\t" \
1494 "pushq 56(%%rax)\n\t" \
1495 "movq 48(%%rax), %%r9\n\t" \
1496 "movq 40(%%rax), %%r8\n\t" \
1497 "movq 32(%%rax), %%rcx\n\t" \
1498 "movq 24(%%rax), %%rdx\n\t" \
1499 "movq 16(%%rax), %%rsi\n\t" \
1500 "movq 8(%%rax), %%rdi\n\t" \
1501 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1502 VALGRIND_CALL_NOREDIR_RAX \
1503 "addq $40, %%rsp\n" \
1504 "addq $128,%%rsp\n\t" \
1505 : /*out*/ "=a" (_res) \
1506 : /*in*/ "a" (&_argvec[0]) \
1507 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1509 lval = (__typeof__(lval)) _res; \
1512 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1513 arg7,arg8,arg9,arg10,arg11,arg12) \
1515 volatile OrigFn _orig = (orig); \
1516 volatile unsigned long _argvec[13]; \
1517 volatile unsigned long _res; \
1518 _argvec[0] = (unsigned long)_orig.nraddr; \
1519 _argvec[1] = (unsigned long)(arg1); \
1520 _argvec[2] = (unsigned long)(arg2); \
1521 _argvec[3] = (unsigned long)(arg3); \
1522 _argvec[4] = (unsigned long)(arg4); \
1523 _argvec[5] = (unsigned long)(arg5); \
1524 _argvec[6] = (unsigned long)(arg6); \
1525 _argvec[7] = (unsigned long)(arg7); \
1526 _argvec[8] = (unsigned long)(arg8); \
1527 _argvec[9] = (unsigned long)(arg9); \
1528 _argvec[10] = (unsigned long)(arg10); \
1529 _argvec[11] = (unsigned long)(arg11); \
1530 _argvec[12] = (unsigned long)(arg12); \
1532 "subq $128,%%rsp\n\t" \
1533 "pushq 96(%%rax)\n\t" \
1534 "pushq 88(%%rax)\n\t" \
1535 "pushq 80(%%rax)\n\t" \
1536 "pushq 72(%%rax)\n\t" \
1537 "pushq 64(%%rax)\n\t" \
1538 "pushq 56(%%rax)\n\t" \
1539 "movq 48(%%rax), %%r9\n\t" \
1540 "movq 40(%%rax), %%r8\n\t" \
1541 "movq 32(%%rax), %%rcx\n\t" \
1542 "movq 24(%%rax), %%rdx\n\t" \
1543 "movq 16(%%rax), %%rsi\n\t" \
1544 "movq 8(%%rax), %%rdi\n\t" \
1545 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1546 VALGRIND_CALL_NOREDIR_RAX \
1547 "addq $48, %%rsp\n" \
1548 "addq $128,%%rsp\n\t" \
1549 : /*out*/ "=a" (_res) \
1550 : /*in*/ "a" (&_argvec[0]) \
1551 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1553 lval = (__typeof__(lval)) _res; \
1556 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
1558 /* ------------------------ ppc32-linux ------------------------ */
1560 #if defined(PLAT_ppc32_linux)
1562 /* This is useful for finding out about the on-stack stuff:
1564 extern int f9 ( int,int,int,int,int,int,int,int,int );
1565 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1566 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1567 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1570 return f9(11,22,33,44,55,66,77,88,99);
1573 return f10(11,22,33,44,55,66,77,88,99,110);
1576 return f11(11,22,33,44,55,66,77,88,99,110,121);
1579 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1583 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1585 /* These regs are trashed by the hidden call. */
1586 #define __CALLER_SAVED_REGS \
1587 "lr", "ctr", "xer", \
1588 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1589 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1592 /* These CALL_FN_ macros assume that on ppc32-linux,
1593 sizeof(unsigned long) == 4. */
1595 #define CALL_FN_W_v(lval, orig) \
1597 volatile OrigFn _orig = (orig); \
1598 volatile unsigned long _argvec[1]; \
1599 volatile unsigned long _res; \
1600 _argvec[0] = (unsigned long)_orig.nraddr; \
1603 "lwz 11,0(11)\n\t" /* target->r11 */ \
1604 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1606 : /*out*/ "=r" (_res) \
1607 : /*in*/ "r" (&_argvec[0]) \
1608 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1610 lval = (__typeof__(lval)) _res; \
1613 #define CALL_FN_W_W(lval, orig, arg1) \
1615 volatile OrigFn _orig = (orig); \
1616 volatile unsigned long _argvec[2]; \
1617 volatile unsigned long _res; \
1618 _argvec[0] = (unsigned long)_orig.nraddr; \
1619 _argvec[1] = (unsigned long)arg1; \
1622 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1623 "lwz 11,0(11)\n\t" /* target->r11 */ \
1624 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1626 : /*out*/ "=r" (_res) \
1627 : /*in*/ "r" (&_argvec[0]) \
1628 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1630 lval = (__typeof__(lval)) _res; \
1633 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1635 volatile OrigFn _orig = (orig); \
1636 volatile unsigned long _argvec[3]; \
1637 volatile unsigned long _res; \
1638 _argvec[0] = (unsigned long)_orig.nraddr; \
1639 _argvec[1] = (unsigned long)arg1; \
1640 _argvec[2] = (unsigned long)arg2; \
1643 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1645 "lwz 11,0(11)\n\t" /* target->r11 */ \
1646 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1648 : /*out*/ "=r" (_res) \
1649 : /*in*/ "r" (&_argvec[0]) \
1650 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1652 lval = (__typeof__(lval)) _res; \
1655 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1657 volatile OrigFn _orig = (orig); \
1658 volatile unsigned long _argvec[4]; \
1659 volatile unsigned long _res; \
1660 _argvec[0] = (unsigned long)_orig.nraddr; \
1661 _argvec[1] = (unsigned long)arg1; \
1662 _argvec[2] = (unsigned long)arg2; \
1663 _argvec[3] = (unsigned long)arg3; \
1666 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1668 "lwz 5,12(11)\n\t" \
1669 "lwz 11,0(11)\n\t" /* target->r11 */ \
1670 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1672 : /*out*/ "=r" (_res) \
1673 : /*in*/ "r" (&_argvec[0]) \
1674 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1676 lval = (__typeof__(lval)) _res; \
1679 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1681 volatile OrigFn _orig = (orig); \
1682 volatile unsigned long _argvec[5]; \
1683 volatile unsigned long _res; \
1684 _argvec[0] = (unsigned long)_orig.nraddr; \
1685 _argvec[1] = (unsigned long)arg1; \
1686 _argvec[2] = (unsigned long)arg2; \
1687 _argvec[3] = (unsigned long)arg3; \
1688 _argvec[4] = (unsigned long)arg4; \
1691 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1693 "lwz 5,12(11)\n\t" \
1694 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1695 "lwz 11,0(11)\n\t" /* target->r11 */ \
1696 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1698 : /*out*/ "=r" (_res) \
1699 : /*in*/ "r" (&_argvec[0]) \
1700 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1702 lval = (__typeof__(lval)) _res; \
1705 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1707 volatile OrigFn _orig = (orig); \
1708 volatile unsigned long _argvec[6]; \
1709 volatile unsigned long _res; \
1710 _argvec[0] = (unsigned long)_orig.nraddr; \
1711 _argvec[1] = (unsigned long)arg1; \
1712 _argvec[2] = (unsigned long)arg2; \
1713 _argvec[3] = (unsigned long)arg3; \
1714 _argvec[4] = (unsigned long)arg4; \
1715 _argvec[5] = (unsigned long)arg5; \
1718 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1720 "lwz 5,12(11)\n\t" \
1721 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1722 "lwz 7,20(11)\n\t" \
1723 "lwz 11,0(11)\n\t" /* target->r11 */ \
1724 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1726 : /*out*/ "=r" (_res) \
1727 : /*in*/ "r" (&_argvec[0]) \
1728 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1730 lval = (__typeof__(lval)) _res; \
1733 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1735 volatile OrigFn _orig = (orig); \
1736 volatile unsigned long _argvec[7]; \
1737 volatile unsigned long _res; \
1738 _argvec[0] = (unsigned long)_orig.nraddr; \
1739 _argvec[1] = (unsigned long)arg1; \
1740 _argvec[2] = (unsigned long)arg2; \
1741 _argvec[3] = (unsigned long)arg3; \
1742 _argvec[4] = (unsigned long)arg4; \
1743 _argvec[5] = (unsigned long)arg5; \
1744 _argvec[6] = (unsigned long)arg6; \
1747 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1749 "lwz 5,12(11)\n\t" \
1750 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1751 "lwz 7,20(11)\n\t" \
1752 "lwz 8,24(11)\n\t" \
1753 "lwz 11,0(11)\n\t" /* target->r11 */ \
1754 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1756 : /*out*/ "=r" (_res) \
1757 : /*in*/ "r" (&_argvec[0]) \
1758 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1760 lval = (__typeof__(lval)) _res; \
1763 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1766 volatile OrigFn _orig = (orig); \
1767 volatile unsigned long _argvec[8]; \
1768 volatile unsigned long _res; \
1769 _argvec[0] = (unsigned long)_orig.nraddr; \
1770 _argvec[1] = (unsigned long)arg1; \
1771 _argvec[2] = (unsigned long)arg2; \
1772 _argvec[3] = (unsigned long)arg3; \
1773 _argvec[4] = (unsigned long)arg4; \
1774 _argvec[5] = (unsigned long)arg5; \
1775 _argvec[6] = (unsigned long)arg6; \
1776 _argvec[7] = (unsigned long)arg7; \
1779 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1781 "lwz 5,12(11)\n\t" \
1782 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1783 "lwz 7,20(11)\n\t" \
1784 "lwz 8,24(11)\n\t" \
1785 "lwz 9,28(11)\n\t" \
1786 "lwz 11,0(11)\n\t" /* target->r11 */ \
1787 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1789 : /*out*/ "=r" (_res) \
1790 : /*in*/ "r" (&_argvec[0]) \
1791 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1793 lval = (__typeof__(lval)) _res; \
1796 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1799 volatile OrigFn _orig = (orig); \
1800 volatile unsigned long _argvec[9]; \
1801 volatile unsigned long _res; \
1802 _argvec[0] = (unsigned long)_orig.nraddr; \
1803 _argvec[1] = (unsigned long)arg1; \
1804 _argvec[2] = (unsigned long)arg2; \
1805 _argvec[3] = (unsigned long)arg3; \
1806 _argvec[4] = (unsigned long)arg4; \
1807 _argvec[5] = (unsigned long)arg5; \
1808 _argvec[6] = (unsigned long)arg6; \
1809 _argvec[7] = (unsigned long)arg7; \
1810 _argvec[8] = (unsigned long)arg8; \
1813 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1815 "lwz 5,12(11)\n\t" \
1816 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1817 "lwz 7,20(11)\n\t" \
1818 "lwz 8,24(11)\n\t" \
1819 "lwz 9,28(11)\n\t" \
1820 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1821 "lwz 11,0(11)\n\t" /* target->r11 */ \
1822 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1824 : /*out*/ "=r" (_res) \
1825 : /*in*/ "r" (&_argvec[0]) \
1826 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1828 lval = (__typeof__(lval)) _res; \
1831 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1834 volatile OrigFn _orig = (orig); \
1835 volatile unsigned long _argvec[10]; \
1836 volatile unsigned long _res; \
1837 _argvec[0] = (unsigned long)_orig.nraddr; \
1838 _argvec[1] = (unsigned long)arg1; \
1839 _argvec[2] = (unsigned long)arg2; \
1840 _argvec[3] = (unsigned long)arg3; \
1841 _argvec[4] = (unsigned long)arg4; \
1842 _argvec[5] = (unsigned long)arg5; \
1843 _argvec[6] = (unsigned long)arg6; \
1844 _argvec[7] = (unsigned long)arg7; \
1845 _argvec[8] = (unsigned long)arg8; \
1846 _argvec[9] = (unsigned long)arg9; \
1849 "addi 1,1,-16\n\t" \
1851 "lwz 3,36(11)\n\t" \
1854 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1856 "lwz 5,12(11)\n\t" \
1857 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1858 "lwz 7,20(11)\n\t" \
1859 "lwz 8,24(11)\n\t" \
1860 "lwz 9,28(11)\n\t" \
1861 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1862 "lwz 11,0(11)\n\t" /* target->r11 */ \
1863 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1866 : /*out*/ "=r" (_res) \
1867 : /*in*/ "r" (&_argvec[0]) \
1868 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1870 lval = (__typeof__(lval)) _res; \
1873 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1874 arg7,arg8,arg9,arg10) \
1876 volatile OrigFn _orig = (orig); \
1877 volatile unsigned long _argvec[11]; \
1878 volatile unsigned long _res; \
1879 _argvec[0] = (unsigned long)_orig.nraddr; \
1880 _argvec[1] = (unsigned long)arg1; \
1881 _argvec[2] = (unsigned long)arg2; \
1882 _argvec[3] = (unsigned long)arg3; \
1883 _argvec[4] = (unsigned long)arg4; \
1884 _argvec[5] = (unsigned long)arg5; \
1885 _argvec[6] = (unsigned long)arg6; \
1886 _argvec[7] = (unsigned long)arg7; \
1887 _argvec[8] = (unsigned long)arg8; \
1888 _argvec[9] = (unsigned long)arg9; \
1889 _argvec[10] = (unsigned long)arg10; \
1892 "addi 1,1,-16\n\t" \
1894 "lwz 3,40(11)\n\t" \
1897 "lwz 3,36(11)\n\t" \
1900 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1902 "lwz 5,12(11)\n\t" \
1903 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1904 "lwz 7,20(11)\n\t" \
1905 "lwz 8,24(11)\n\t" \
1906 "lwz 9,28(11)\n\t" \
1907 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1908 "lwz 11,0(11)\n\t" /* target->r11 */ \
1909 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1912 : /*out*/ "=r" (_res) \
1913 : /*in*/ "r" (&_argvec[0]) \
1914 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1916 lval = (__typeof__(lval)) _res; \
1919 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1920 arg7,arg8,arg9,arg10,arg11) \
1922 volatile OrigFn _orig = (orig); \
1923 volatile unsigned long _argvec[12]; \
1924 volatile unsigned long _res; \
1925 _argvec[0] = (unsigned long)_orig.nraddr; \
1926 _argvec[1] = (unsigned long)arg1; \
1927 _argvec[2] = (unsigned long)arg2; \
1928 _argvec[3] = (unsigned long)arg3; \
1929 _argvec[4] = (unsigned long)arg4; \
1930 _argvec[5] = (unsigned long)arg5; \
1931 _argvec[6] = (unsigned long)arg6; \
1932 _argvec[7] = (unsigned long)arg7; \
1933 _argvec[8] = (unsigned long)arg8; \
1934 _argvec[9] = (unsigned long)arg9; \
1935 _argvec[10] = (unsigned long)arg10; \
1936 _argvec[11] = (unsigned long)arg11; \
1939 "addi 1,1,-32\n\t" \
1941 "lwz 3,44(11)\n\t" \
1944 "lwz 3,40(11)\n\t" \
1947 "lwz 3,36(11)\n\t" \
1950 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1952 "lwz 5,12(11)\n\t" \
1953 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1954 "lwz 7,20(11)\n\t" \
1955 "lwz 8,24(11)\n\t" \
1956 "lwz 9,28(11)\n\t" \
1957 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1958 "lwz 11,0(11)\n\t" /* target->r11 */ \
1959 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1962 : /*out*/ "=r" (_res) \
1963 : /*in*/ "r" (&_argvec[0]) \
1964 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1966 lval = (__typeof__(lval)) _res; \
1969 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1970 arg7,arg8,arg9,arg10,arg11,arg12) \
1972 volatile OrigFn _orig = (orig); \
1973 volatile unsigned long _argvec[13]; \
1974 volatile unsigned long _res; \
1975 _argvec[0] = (unsigned long)_orig.nraddr; \
1976 _argvec[1] = (unsigned long)arg1; \
1977 _argvec[2] = (unsigned long)arg2; \
1978 _argvec[3] = (unsigned long)arg3; \
1979 _argvec[4] = (unsigned long)arg4; \
1980 _argvec[5] = (unsigned long)arg5; \
1981 _argvec[6] = (unsigned long)arg6; \
1982 _argvec[7] = (unsigned long)arg7; \
1983 _argvec[8] = (unsigned long)arg8; \
1984 _argvec[9] = (unsigned long)arg9; \
1985 _argvec[10] = (unsigned long)arg10; \
1986 _argvec[11] = (unsigned long)arg11; \
1987 _argvec[12] = (unsigned long)arg12; \
1990 "addi 1,1,-32\n\t" \
1992 "lwz 3,48(11)\n\t" \
1995 "lwz 3,44(11)\n\t" \
1998 "lwz 3,40(11)\n\t" \
2001 "lwz 3,36(11)\n\t" \
2004 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2006 "lwz 5,12(11)\n\t" \
2007 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2008 "lwz 7,20(11)\n\t" \
2009 "lwz 8,24(11)\n\t" \
2010 "lwz 9,28(11)\n\t" \
2011 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2012 "lwz 11,0(11)\n\t" /* target->r11 */ \
2013 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2016 : /*out*/ "=r" (_res) \
2017 : /*in*/ "r" (&_argvec[0]) \
2018 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2020 lval = (__typeof__(lval)) _res; \
2023 #endif /* PLAT_ppc32_linux */
2025 /* ------------------------ ppc64-linux ------------------------ */
2027 #if defined(PLAT_ppc64_linux)
2029 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2031 /* These regs are trashed by the hidden call. */
2032 #define __CALLER_SAVED_REGS \
2033 "lr", "ctr", "xer", \
2034 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2035 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2038 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2041 #define CALL_FN_W_v(lval, orig) \
2043 volatile OrigFn _orig = (orig); \
2044 volatile unsigned long _argvec[3+0]; \
2045 volatile unsigned long _res; \
2046 /* _argvec[0] holds current r2 across the call */ \
2047 _argvec[1] = (unsigned long)_orig.r2; \
2048 _argvec[2] = (unsigned long)_orig.nraddr; \
2051 "std 2,-16(11)\n\t" /* save tocptr */ \
2052 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2053 "ld 11, 0(11)\n\t" /* target->r11 */ \
2054 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2057 "ld 2,-16(11)" /* restore tocptr */ \
2058 : /*out*/ "=r" (_res) \
2059 : /*in*/ "r" (&_argvec[2]) \
2060 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2062 lval = (__typeof__(lval)) _res; \
2065 #define CALL_FN_W_W(lval, orig, arg1) \
2067 volatile OrigFn _orig = (orig); \
2068 volatile unsigned long _argvec[3+1]; \
2069 volatile unsigned long _res; \
2070 /* _argvec[0] holds current r2 across the call */ \
2071 _argvec[1] = (unsigned long)_orig.r2; \
2072 _argvec[2] = (unsigned long)_orig.nraddr; \
2073 _argvec[2+1] = (unsigned long)arg1; \
2076 "std 2,-16(11)\n\t" /* save tocptr */ \
2077 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2078 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2079 "ld 11, 0(11)\n\t" /* target->r11 */ \
2080 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2083 "ld 2,-16(11)" /* restore tocptr */ \
2084 : /*out*/ "=r" (_res) \
2085 : /*in*/ "r" (&_argvec[2]) \
2086 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2088 lval = (__typeof__(lval)) _res; \
2091 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2093 volatile OrigFn _orig = (orig); \
2094 volatile unsigned long _argvec[3+2]; \
2095 volatile unsigned long _res; \
2096 /* _argvec[0] holds current r2 across the call */ \
2097 _argvec[1] = (unsigned long)_orig.r2; \
2098 _argvec[2] = (unsigned long)_orig.nraddr; \
2099 _argvec[2+1] = (unsigned long)arg1; \
2100 _argvec[2+2] = (unsigned long)arg2; \
2103 "std 2,-16(11)\n\t" /* save tocptr */ \
2104 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2105 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2106 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2107 "ld 11, 0(11)\n\t" /* target->r11 */ \
2108 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2111 "ld 2,-16(11)" /* restore tocptr */ \
2112 : /*out*/ "=r" (_res) \
2113 : /*in*/ "r" (&_argvec[2]) \
2114 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2116 lval = (__typeof__(lval)) _res; \
2119 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2121 volatile OrigFn _orig = (orig); \
2122 volatile unsigned long _argvec[3+3]; \
2123 volatile unsigned long _res; \
2124 /* _argvec[0] holds current r2 across the call */ \
2125 _argvec[1] = (unsigned long)_orig.r2; \
2126 _argvec[2] = (unsigned long)_orig.nraddr; \
2127 _argvec[2+1] = (unsigned long)arg1; \
2128 _argvec[2+2] = (unsigned long)arg2; \
2129 _argvec[2+3] = (unsigned long)arg3; \
2132 "std 2,-16(11)\n\t" /* save tocptr */ \
2133 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2134 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2135 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2136 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2137 "ld 11, 0(11)\n\t" /* target->r11 */ \
2138 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2141 "ld 2,-16(11)" /* restore tocptr */ \
2142 : /*out*/ "=r" (_res) \
2143 : /*in*/ "r" (&_argvec[2]) \
2144 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2146 lval = (__typeof__(lval)) _res; \
2149 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2151 volatile OrigFn _orig = (orig); \
2152 volatile unsigned long _argvec[3+4]; \
2153 volatile unsigned long _res; \
2154 /* _argvec[0] holds current r2 across the call */ \
2155 _argvec[1] = (unsigned long)_orig.r2; \
2156 _argvec[2] = (unsigned long)_orig.nraddr; \
2157 _argvec[2+1] = (unsigned long)arg1; \
2158 _argvec[2+2] = (unsigned long)arg2; \
2159 _argvec[2+3] = (unsigned long)arg3; \
2160 _argvec[2+4] = (unsigned long)arg4; \
2163 "std 2,-16(11)\n\t" /* save tocptr */ \
2164 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2165 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2166 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2167 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2168 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2169 "ld 11, 0(11)\n\t" /* target->r11 */ \
2170 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2173 "ld 2,-16(11)" /* restore tocptr */ \
2174 : /*out*/ "=r" (_res) \
2175 : /*in*/ "r" (&_argvec[2]) \
2176 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2178 lval = (__typeof__(lval)) _res; \
2181 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2183 volatile OrigFn _orig = (orig); \
2184 volatile unsigned long _argvec[3+5]; \
2185 volatile unsigned long _res; \
2186 /* _argvec[0] holds current r2 across the call */ \
2187 _argvec[1] = (unsigned long)_orig.r2; \
2188 _argvec[2] = (unsigned long)_orig.nraddr; \
2189 _argvec[2+1] = (unsigned long)arg1; \
2190 _argvec[2+2] = (unsigned long)arg2; \
2191 _argvec[2+3] = (unsigned long)arg3; \
2192 _argvec[2+4] = (unsigned long)arg4; \
2193 _argvec[2+5] = (unsigned long)arg5; \
2196 "std 2,-16(11)\n\t" /* save tocptr */ \
2197 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2198 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2199 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2200 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2201 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2202 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2203 "ld 11, 0(11)\n\t" /* target->r11 */ \
2204 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2207 "ld 2,-16(11)" /* restore tocptr */ \
2208 : /*out*/ "=r" (_res) \
2209 : /*in*/ "r" (&_argvec[2]) \
2210 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2212 lval = (__typeof__(lval)) _res; \
2215 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2217 volatile OrigFn _orig = (orig); \
2218 volatile unsigned long _argvec[3+6]; \
2219 volatile unsigned long _res; \
2220 /* _argvec[0] holds current r2 across the call */ \
2221 _argvec[1] = (unsigned long)_orig.r2; \
2222 _argvec[2] = (unsigned long)_orig.nraddr; \
2223 _argvec[2+1] = (unsigned long)arg1; \
2224 _argvec[2+2] = (unsigned long)arg2; \
2225 _argvec[2+3] = (unsigned long)arg3; \
2226 _argvec[2+4] = (unsigned long)arg4; \
2227 _argvec[2+5] = (unsigned long)arg5; \
2228 _argvec[2+6] = (unsigned long)arg6; \
2231 "std 2,-16(11)\n\t" /* save tocptr */ \
2232 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2233 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2234 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2235 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2236 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2237 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2238 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2239 "ld 11, 0(11)\n\t" /* target->r11 */ \
2240 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2243 "ld 2,-16(11)" /* restore tocptr */ \
2244 : /*out*/ "=r" (_res) \
2245 : /*in*/ "r" (&_argvec[2]) \
2246 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2248 lval = (__typeof__(lval)) _res; \
2251 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2254 volatile OrigFn _orig = (orig); \
2255 volatile unsigned long _argvec[3+7]; \
2256 volatile unsigned long _res; \
2257 /* _argvec[0] holds current r2 across the call */ \
2258 _argvec[1] = (unsigned long)_orig.r2; \
2259 _argvec[2] = (unsigned long)_orig.nraddr; \
2260 _argvec[2+1] = (unsigned long)arg1; \
2261 _argvec[2+2] = (unsigned long)arg2; \
2262 _argvec[2+3] = (unsigned long)arg3; \
2263 _argvec[2+4] = (unsigned long)arg4; \
2264 _argvec[2+5] = (unsigned long)arg5; \
2265 _argvec[2+6] = (unsigned long)arg6; \
2266 _argvec[2+7] = (unsigned long)arg7; \
2269 "std 2,-16(11)\n\t" /* save tocptr */ \
2270 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2271 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2272 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2273 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2274 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2275 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2276 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2277 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2278 "ld 11, 0(11)\n\t" /* target->r11 */ \
2279 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2282 "ld 2,-16(11)" /* restore tocptr */ \
2283 : /*out*/ "=r" (_res) \
2284 : /*in*/ "r" (&_argvec[2]) \
2285 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2287 lval = (__typeof__(lval)) _res; \
2290 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2293 volatile OrigFn _orig = (orig); \
2294 volatile unsigned long _argvec[3+8]; \
2295 volatile unsigned long _res; \
2296 /* _argvec[0] holds current r2 across the call */ \
2297 _argvec[1] = (unsigned long)_orig.r2; \
2298 _argvec[2] = (unsigned long)_orig.nraddr; \
2299 _argvec[2+1] = (unsigned long)arg1; \
2300 _argvec[2+2] = (unsigned long)arg2; \
2301 _argvec[2+3] = (unsigned long)arg3; \
2302 _argvec[2+4] = (unsigned long)arg4; \
2303 _argvec[2+5] = (unsigned long)arg5; \
2304 _argvec[2+6] = (unsigned long)arg6; \
2305 _argvec[2+7] = (unsigned long)arg7; \
2306 _argvec[2+8] = (unsigned long)arg8; \
2309 "std 2,-16(11)\n\t" /* save tocptr */ \
2310 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2311 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2312 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2313 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2314 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2315 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2316 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2317 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2318 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2319 "ld 11, 0(11)\n\t" /* target->r11 */ \
2320 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2323 "ld 2,-16(11)" /* restore tocptr */ \
2324 : /*out*/ "=r" (_res) \
2325 : /*in*/ "r" (&_argvec[2]) \
2326 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2328 lval = (__typeof__(lval)) _res; \
2331 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2334 volatile OrigFn _orig = (orig); \
2335 volatile unsigned long _argvec[3+9]; \
2336 volatile unsigned long _res; \
2337 /* _argvec[0] holds current r2 across the call */ \
2338 _argvec[1] = (unsigned long)_orig.r2; \
2339 _argvec[2] = (unsigned long)_orig.nraddr; \
2340 _argvec[2+1] = (unsigned long)arg1; \
2341 _argvec[2+2] = (unsigned long)arg2; \
2342 _argvec[2+3] = (unsigned long)arg3; \
2343 _argvec[2+4] = (unsigned long)arg4; \
2344 _argvec[2+5] = (unsigned long)arg5; \
2345 _argvec[2+6] = (unsigned long)arg6; \
2346 _argvec[2+7] = (unsigned long)arg7; \
2347 _argvec[2+8] = (unsigned long)arg8; \
2348 _argvec[2+9] = (unsigned long)arg9; \
2351 "std 2,-16(11)\n\t" /* save tocptr */ \
2352 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2353 "addi 1,1,-128\n\t" /* expand stack frame */ \
2356 "std 3,112(1)\n\t" \
2358 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2359 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2360 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2361 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2362 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2363 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2364 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2365 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2366 "ld 11, 0(11)\n\t" /* target->r11 */ \
2367 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2370 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2371 "addi 1,1,128" /* restore frame */ \
2372 : /*out*/ "=r" (_res) \
2373 : /*in*/ "r" (&_argvec[2]) \
2374 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2376 lval = (__typeof__(lval)) _res; \
2379 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2380 arg7,arg8,arg9,arg10) \
2382 volatile OrigFn _orig = (orig); \
2383 volatile unsigned long _argvec[3+10]; \
2384 volatile unsigned long _res; \
2385 /* _argvec[0] holds current r2 across the call */ \
2386 _argvec[1] = (unsigned long)_orig.r2; \
2387 _argvec[2] = (unsigned long)_orig.nraddr; \
2388 _argvec[2+1] = (unsigned long)arg1; \
2389 _argvec[2+2] = (unsigned long)arg2; \
2390 _argvec[2+3] = (unsigned long)arg3; \
2391 _argvec[2+4] = (unsigned long)arg4; \
2392 _argvec[2+5] = (unsigned long)arg5; \
2393 _argvec[2+6] = (unsigned long)arg6; \
2394 _argvec[2+7] = (unsigned long)arg7; \
2395 _argvec[2+8] = (unsigned long)arg8; \
2396 _argvec[2+9] = (unsigned long)arg9; \
2397 _argvec[2+10] = (unsigned long)arg10; \
2400 "std 2,-16(11)\n\t" /* save tocptr */ \
2401 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2402 "addi 1,1,-128\n\t" /* expand stack frame */ \
2405 "std 3,120(1)\n\t" \
2408 "std 3,112(1)\n\t" \
2410 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2411 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2412 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2413 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2414 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2415 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2416 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2417 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2418 "ld 11, 0(11)\n\t" /* target->r11 */ \
2419 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2422 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2423 "addi 1,1,128" /* restore frame */ \
2424 : /*out*/ "=r" (_res) \
2425 : /*in*/ "r" (&_argvec[2]) \
2426 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2428 lval = (__typeof__(lval)) _res; \
2431 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2432 arg7,arg8,arg9,arg10,arg11) \
2434 volatile OrigFn _orig = (orig); \
2435 volatile unsigned long _argvec[3+11]; \
2436 volatile unsigned long _res; \
2437 /* _argvec[0] holds current r2 across the call */ \
2438 _argvec[1] = (unsigned long)_orig.r2; \
2439 _argvec[2] = (unsigned long)_orig.nraddr; \
2440 _argvec[2+1] = (unsigned long)arg1; \
2441 _argvec[2+2] = (unsigned long)arg2; \
2442 _argvec[2+3] = (unsigned long)arg3; \
2443 _argvec[2+4] = (unsigned long)arg4; \
2444 _argvec[2+5] = (unsigned long)arg5; \
2445 _argvec[2+6] = (unsigned long)arg6; \
2446 _argvec[2+7] = (unsigned long)arg7; \
2447 _argvec[2+8] = (unsigned long)arg8; \
2448 _argvec[2+9] = (unsigned long)arg9; \
2449 _argvec[2+10] = (unsigned long)arg10; \
2450 _argvec[2+11] = (unsigned long)arg11; \
2453 "std 2,-16(11)\n\t" /* save tocptr */ \
2454 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2455 "addi 1,1,-144\n\t" /* expand stack frame */ \
2458 "std 3,128(1)\n\t" \
2461 "std 3,120(1)\n\t" \
2464 "std 3,112(1)\n\t" \
2466 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2467 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2468 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2469 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2470 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2471 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2472 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2473 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2474 "ld 11, 0(11)\n\t" /* target->r11 */ \
2475 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2478 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2479 "addi 1,1,144" /* restore frame */ \
2480 : /*out*/ "=r" (_res) \
2481 : /*in*/ "r" (&_argvec[2]) \
2482 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2484 lval = (__typeof__(lval)) _res; \
2487 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2488 arg7,arg8,arg9,arg10,arg11,arg12) \
2490 volatile OrigFn _orig = (orig); \
2491 volatile unsigned long _argvec[3+12]; \
2492 volatile unsigned long _res; \
2493 /* _argvec[0] holds current r2 across the call */ \
2494 _argvec[1] = (unsigned long)_orig.r2; \
2495 _argvec[2] = (unsigned long)_orig.nraddr; \
2496 _argvec[2+1] = (unsigned long)arg1; \
2497 _argvec[2+2] = (unsigned long)arg2; \
2498 _argvec[2+3] = (unsigned long)arg3; \
2499 _argvec[2+4] = (unsigned long)arg4; \
2500 _argvec[2+5] = (unsigned long)arg5; \
2501 _argvec[2+6] = (unsigned long)arg6; \
2502 _argvec[2+7] = (unsigned long)arg7; \
2503 _argvec[2+8] = (unsigned long)arg8; \
2504 _argvec[2+9] = (unsigned long)arg9; \
2505 _argvec[2+10] = (unsigned long)arg10; \
2506 _argvec[2+11] = (unsigned long)arg11; \
2507 _argvec[2+12] = (unsigned long)arg12; \
2510 "std 2,-16(11)\n\t" /* save tocptr */ \
2511 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2512 "addi 1,1,-144\n\t" /* expand stack frame */ \
2515 "std 3,136(1)\n\t" \
2518 "std 3,128(1)\n\t" \
2521 "std 3,120(1)\n\t" \
2524 "std 3,112(1)\n\t" \
2526 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2527 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2528 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2529 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2530 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2531 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2532 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2533 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2534 "ld 11, 0(11)\n\t" /* target->r11 */ \
2535 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2538 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2539 "addi 1,1,144" /* restore frame */ \
2540 : /*out*/ "=r" (_res) \
2541 : /*in*/ "r" (&_argvec[2]) \
2542 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2544 lval = (__typeof__(lval)) _res; \
2547 #endif /* PLAT_ppc64_linux */
2549 /* ------------------------- arm-linux ------------------------- */
2551 #if defined(PLAT_arm_linux)
2553 /* These regs are trashed by the hidden call. */
2554 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2556 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2559 #define CALL_FN_W_v(lval, orig) \
2561 volatile OrigFn _orig = (orig); \
2562 volatile unsigned long _argvec[1]; \
2563 volatile unsigned long _res; \
2564 _argvec[0] = (unsigned long)_orig.nraddr; \
2566 "ldr r4, [%1] \n\t" /* target->r4 */ \
2567 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2569 : /*out*/ "=r" (_res) \
2570 : /*in*/ "0" (&_argvec[0]) \
2571 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2573 lval = (__typeof__(lval)) _res; \
2576 #define CALL_FN_W_W(lval, orig, arg1) \
2578 volatile OrigFn _orig = (orig); \
2579 volatile unsigned long _argvec[2]; \
2580 volatile unsigned long _res; \
2581 _argvec[0] = (unsigned long)_orig.nraddr; \
2582 _argvec[1] = (unsigned long)(arg1); \
2584 "ldr r0, [%1, #4] \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_WW(lval, orig, arg1,arg2) \
2597 volatile OrigFn _orig = (orig); \
2598 volatile unsigned long _argvec[3]; \
2599 volatile unsigned long _res; \
2600 _argvec[0] = (unsigned long)_orig.nraddr; \
2601 _argvec[1] = (unsigned long)(arg1); \
2602 _argvec[2] = (unsigned long)(arg2); \
2604 "ldr r0, [%1, #4] \n\t" \
2605 "ldr r1, [%1, #8] \n\t" \
2606 "ldr r4, [%1] \n\t" /* target->r4 */ \
2607 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2609 : /*out*/ "=r" (_res) \
2610 : /*in*/ "0" (&_argvec[0]) \
2611 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2613 lval = (__typeof__(lval)) _res; \
2616 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2618 volatile OrigFn _orig = (orig); \
2619 volatile unsigned long _argvec[4]; \
2620 volatile unsigned long _res; \
2621 _argvec[0] = (unsigned long)_orig.nraddr; \
2622 _argvec[1] = (unsigned long)(arg1); \
2623 _argvec[2] = (unsigned long)(arg2); \
2624 _argvec[3] = (unsigned long)(arg3); \
2626 "ldr r0, [%1, #4] \n\t" \
2627 "ldr r1, [%1, #8] \n\t" \
2628 "ldr r2, [%1, #12] \n\t" \
2629 "ldr r4, [%1] \n\t" /* target->r4 */ \
2630 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2632 : /*out*/ "=r" (_res) \
2633 : /*in*/ "0" (&_argvec[0]) \
2634 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2636 lval = (__typeof__(lval)) _res; \
2639 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2641 volatile OrigFn _orig = (orig); \
2642 volatile unsigned long _argvec[5]; \
2643 volatile unsigned long _res; \
2644 _argvec[0] = (unsigned long)_orig.nraddr; \
2645 _argvec[1] = (unsigned long)(arg1); \
2646 _argvec[2] = (unsigned long)(arg2); \
2647 _argvec[3] = (unsigned long)(arg3); \
2648 _argvec[4] = (unsigned long)(arg4); \
2650 "ldr r0, [%1, #4] \n\t" \
2651 "ldr r1, [%1, #8] \n\t" \
2652 "ldr r2, [%1, #12] \n\t" \
2653 "ldr r3, [%1, #16] \n\t" \
2654 "ldr r4, [%1] \n\t" /* target->r4 */ \
2655 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2657 : /*out*/ "=r" (_res) \
2658 : /*in*/ "0" (&_argvec[0]) \
2659 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2661 lval = (__typeof__(lval)) _res; \
2664 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2666 volatile OrigFn _orig = (orig); \
2667 volatile unsigned long _argvec[6]; \
2668 volatile unsigned long _res; \
2669 _argvec[0] = (unsigned long)_orig.nraddr; \
2670 _argvec[1] = (unsigned long)(arg1); \
2671 _argvec[2] = (unsigned long)(arg2); \
2672 _argvec[3] = (unsigned long)(arg3); \
2673 _argvec[4] = (unsigned long)(arg4); \
2674 _argvec[5] = (unsigned long)(arg5); \
2676 "ldr r0, [%1, #20] \n\t" \
2678 "ldr r0, [%1, #4] \n\t" \
2679 "ldr r1, [%1, #8] \n\t" \
2680 "ldr r2, [%1, #12] \n\t" \
2681 "ldr r3, [%1, #16] \n\t" \
2682 "ldr r4, [%1] \n\t" /* target->r4 */ \
2683 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2684 "add sp, sp, #4 \n\t" \
2686 : /*out*/ "=r" (_res) \
2687 : /*in*/ "0" (&_argvec[0]) \
2688 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2690 lval = (__typeof__(lval)) _res; \
2693 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2695 volatile OrigFn _orig = (orig); \
2696 volatile unsigned long _argvec[7]; \
2697 volatile unsigned long _res; \
2698 _argvec[0] = (unsigned long)_orig.nraddr; \
2699 _argvec[1] = (unsigned long)(arg1); \
2700 _argvec[2] = (unsigned long)(arg2); \
2701 _argvec[3] = (unsigned long)(arg3); \
2702 _argvec[4] = (unsigned long)(arg4); \
2703 _argvec[5] = (unsigned long)(arg5); \
2704 _argvec[6] = (unsigned long)(arg6); \
2706 "ldr r0, [%1, #20] \n\t" \
2707 "ldr r1, [%1, #24] \n\t" \
2708 "push {r0, r1} \n\t" \
2709 "ldr r0, [%1, #4] \n\t" \
2710 "ldr r1, [%1, #8] \n\t" \
2711 "ldr r2, [%1, #12] \n\t" \
2712 "ldr r3, [%1, #16] \n\t" \
2713 "ldr r4, [%1] \n\t" /* target->r4 */ \
2714 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2715 "add sp, sp, #8 \n\t" \
2717 : /*out*/ "=r" (_res) \
2718 : /*in*/ "0" (&_argvec[0]) \
2719 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2721 lval = (__typeof__(lval)) _res; \
2724 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2727 volatile OrigFn _orig = (orig); \
2728 volatile unsigned long _argvec[8]; \
2729 volatile unsigned long _res; \
2730 _argvec[0] = (unsigned long)_orig.nraddr; \
2731 _argvec[1] = (unsigned long)(arg1); \
2732 _argvec[2] = (unsigned long)(arg2); \
2733 _argvec[3] = (unsigned long)(arg3); \
2734 _argvec[4] = (unsigned long)(arg4); \
2735 _argvec[5] = (unsigned long)(arg5); \
2736 _argvec[6] = (unsigned long)(arg6); \
2737 _argvec[7] = (unsigned long)(arg7); \
2739 "ldr r0, [%1, #20] \n\t" \
2740 "ldr r1, [%1, #24] \n\t" \
2741 "ldr r2, [%1, #28] \n\t" \
2742 "push {r0, r1, r2} \n\t" \
2743 "ldr r0, [%1, #4] \n\t" \
2744 "ldr r1, [%1, #8] \n\t" \
2745 "ldr r2, [%1, #12] \n\t" \
2746 "ldr r3, [%1, #16] \n\t" \
2747 "ldr r4, [%1] \n\t" /* target->r4 */ \
2748 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2749 "add sp, sp, #12 \n\t" \
2751 : /*out*/ "=r" (_res) \
2752 : /*in*/ "0" (&_argvec[0]) \
2753 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2755 lval = (__typeof__(lval)) _res; \
2758 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2761 volatile OrigFn _orig = (orig); \
2762 volatile unsigned long _argvec[9]; \
2763 volatile unsigned long _res; \
2764 _argvec[0] = (unsigned long)_orig.nraddr; \
2765 _argvec[1] = (unsigned long)(arg1); \
2766 _argvec[2] = (unsigned long)(arg2); \
2767 _argvec[3] = (unsigned long)(arg3); \
2768 _argvec[4] = (unsigned long)(arg4); \
2769 _argvec[5] = (unsigned long)(arg5); \
2770 _argvec[6] = (unsigned long)(arg6); \
2771 _argvec[7] = (unsigned long)(arg7); \
2772 _argvec[8] = (unsigned long)(arg8); \
2774 "ldr r0, [%1, #20] \n\t" \
2775 "ldr r1, [%1, #24] \n\t" \
2776 "ldr r2, [%1, #28] \n\t" \
2777 "ldr r3, [%1, #32] \n\t" \
2778 "push {r0, r1, r2, r3} \n\t" \
2779 "ldr r0, [%1, #4] \n\t" \
2780 "ldr r1, [%1, #8] \n\t" \
2781 "ldr r2, [%1, #12] \n\t" \
2782 "ldr r3, [%1, #16] \n\t" \
2783 "ldr r4, [%1] \n\t" /* target->r4 */ \
2784 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2785 "add sp, sp, #16 \n\t" \
2787 : /*out*/ "=r" (_res) \
2788 : /*in*/ "0" (&_argvec[0]) \
2789 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2791 lval = (__typeof__(lval)) _res; \
2794 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2797 volatile OrigFn _orig = (orig); \
2798 volatile unsigned long _argvec[10]; \
2799 volatile unsigned long _res; \
2800 _argvec[0] = (unsigned long)_orig.nraddr; \
2801 _argvec[1] = (unsigned long)(arg1); \
2802 _argvec[2] = (unsigned long)(arg2); \
2803 _argvec[3] = (unsigned long)(arg3); \
2804 _argvec[4] = (unsigned long)(arg4); \
2805 _argvec[5] = (unsigned long)(arg5); \
2806 _argvec[6] = (unsigned long)(arg6); \
2807 _argvec[7] = (unsigned long)(arg7); \
2808 _argvec[8] = (unsigned long)(arg8); \
2809 _argvec[9] = (unsigned long)(arg9); \
2811 "ldr r0, [%1, #20] \n\t" \
2812 "ldr r1, [%1, #24] \n\t" \
2813 "ldr r2, [%1, #28] \n\t" \
2814 "ldr r3, [%1, #32] \n\t" \
2815 "ldr r4, [%1, #36] \n\t" \
2816 "push {r0, r1, r2, r3, r4} \n\t" \
2817 "ldr r0, [%1, #4] \n\t" \
2818 "ldr r1, [%1, #8] \n\t" \
2819 "ldr r2, [%1, #12] \n\t" \
2820 "ldr r3, [%1, #16] \n\t" \
2821 "ldr r4, [%1] \n\t" /* target->r4 */ \
2822 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2823 "add sp, sp, #20 \n\t" \
2825 : /*out*/ "=r" (_res) \
2826 : /*in*/ "0" (&_argvec[0]) \
2827 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2829 lval = (__typeof__(lval)) _res; \
2832 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2833 arg7,arg8,arg9,arg10) \
2835 volatile OrigFn _orig = (orig); \
2836 volatile unsigned long _argvec[11]; \
2837 volatile unsigned long _res; \
2838 _argvec[0] = (unsigned long)_orig.nraddr; \
2839 _argvec[1] = (unsigned long)(arg1); \
2840 _argvec[2] = (unsigned long)(arg2); \
2841 _argvec[3] = (unsigned long)(arg3); \
2842 _argvec[4] = (unsigned long)(arg4); \
2843 _argvec[5] = (unsigned long)(arg5); \
2844 _argvec[6] = (unsigned long)(arg6); \
2845 _argvec[7] = (unsigned long)(arg7); \
2846 _argvec[8] = (unsigned long)(arg8); \
2847 _argvec[9] = (unsigned long)(arg9); \
2848 _argvec[10] = (unsigned long)(arg10); \
2850 "ldr r0, [%1, #40] \n\t" \
2852 "ldr r0, [%1, #20] \n\t" \
2853 "ldr r1, [%1, #24] \n\t" \
2854 "ldr r2, [%1, #28] \n\t" \
2855 "ldr r3, [%1, #32] \n\t" \
2856 "ldr r4, [%1, #36] \n\t" \
2857 "push {r0, r1, r2, r3, r4} \n\t" \
2858 "ldr r0, [%1, #4] \n\t" \
2859 "ldr r1, [%1, #8] \n\t" \
2860 "ldr r2, [%1, #12] \n\t" \
2861 "ldr r3, [%1, #16] \n\t" \
2862 "ldr r4, [%1] \n\t" /* target->r4 */ \
2863 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2864 "add sp, sp, #24 \n\t" \
2866 : /*out*/ "=r" (_res) \
2867 : /*in*/ "0" (&_argvec[0]) \
2868 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2870 lval = (__typeof__(lval)) _res; \
2873 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2874 arg6,arg7,arg8,arg9,arg10, \
2877 volatile OrigFn _orig = (orig); \
2878 volatile unsigned long _argvec[12]; \
2879 volatile unsigned long _res; \
2880 _argvec[0] = (unsigned long)_orig.nraddr; \
2881 _argvec[1] = (unsigned long)(arg1); \
2882 _argvec[2] = (unsigned long)(arg2); \
2883 _argvec[3] = (unsigned long)(arg3); \
2884 _argvec[4] = (unsigned long)(arg4); \
2885 _argvec[5] = (unsigned long)(arg5); \
2886 _argvec[6] = (unsigned long)(arg6); \
2887 _argvec[7] = (unsigned long)(arg7); \
2888 _argvec[8] = (unsigned long)(arg8); \
2889 _argvec[9] = (unsigned long)(arg9); \
2890 _argvec[10] = (unsigned long)(arg10); \
2891 _argvec[11] = (unsigned long)(arg11); \
2893 "ldr r0, [%1, #40] \n\t" \
2894 "ldr r1, [%1, #44] \n\t" \
2895 "push {r0, r1} \n\t" \
2896 "ldr r0, [%1, #20] \n\t" \
2897 "ldr r1, [%1, #24] \n\t" \
2898 "ldr r2, [%1, #28] \n\t" \
2899 "ldr r3, [%1, #32] \n\t" \
2900 "ldr r4, [%1, #36] \n\t" \
2901 "push {r0, r1, r2, r3, r4} \n\t" \
2902 "ldr r0, [%1, #4] \n\t" \
2903 "ldr r1, [%1, #8] \n\t" \
2904 "ldr r2, [%1, #12] \n\t" \
2905 "ldr r3, [%1, #16] \n\t" \
2906 "ldr r4, [%1] \n\t" /* target->r4 */ \
2907 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2908 "add sp, sp, #28 \n\t" \
2910 : /*out*/ "=r" (_res) \
2911 : /*in*/ "0" (&_argvec[0]) \
2912 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
2914 lval = (__typeof__(lval)) _res; \
2917 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2918 arg6,arg7,arg8,arg9,arg10, \
2921 volatile OrigFn _orig = (orig); \
2922 volatile unsigned long _argvec[13]; \
2923 volatile unsigned long _res; \
2924 _argvec[0] = (unsigned long)_orig.nraddr; \
2925 _argvec[1] = (unsigned long)(arg1); \
2926 _argvec[2] = (unsigned long)(arg2); \
2927 _argvec[3] = (unsigned long)(arg3); \
2928 _argvec[4] = (unsigned long)(arg4); \
2929 _argvec[5] = (unsigned long)(arg5); \
2930 _argvec[6] = (unsigned long)(arg6); \
2931 _argvec[7] = (unsigned long)(arg7); \
2932 _argvec[8] = (unsigned long)(arg8); \
2933 _argvec[9] = (unsigned long)(arg9); \
2934 _argvec[10] = (unsigned long)(arg10); \
2935 _argvec[11] = (unsigned long)(arg11); \
2936 _argvec[12] = (unsigned long)(arg12); \
2938 "ldr r0, [%1, #40] \n\t" \
2939 "ldr r1, [%1, #44] \n\t" \
2940 "ldr r2, [%1, #48] \n\t" \
2941 "push {r0, r1, r2} \n\t" \
2942 "ldr r0, [%1, #20] \n\t" \
2943 "ldr r1, [%1, #24] \n\t" \
2944 "ldr r2, [%1, #28] \n\t" \
2945 "ldr r3, [%1, #32] \n\t" \
2946 "ldr r4, [%1, #36] \n\t" \
2947 "push {r0, r1, r2, r3, r4} \n\t" \
2948 "ldr r0, [%1, #4] \n\t" \
2949 "ldr r1, [%1, #8] \n\t" \
2950 "ldr r2, [%1, #12] \n\t" \
2951 "ldr r3, [%1, #16] \n\t" \
2952 "ldr r4, [%1] \n\t" /* target->r4 */ \
2953 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2954 "add sp, sp, #32 \n\t" \
2956 : /*out*/ "=r" (_res) \
2957 : /*in*/ "0" (&_argvec[0]) \
2958 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2960 lval = (__typeof__(lval)) _res; \
2963 #endif /* PLAT_arm_linux */
2965 /* ------------------------ ppc32-aix5 ------------------------- */
2967 #if defined(PLAT_ppc32_aix5)
2969 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2971 /* These regs are trashed by the hidden call. */
2972 #define __CALLER_SAVED_REGS \
2973 "lr", "ctr", "xer", \
2974 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2975 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2978 /* Expand the stack frame, copying enough info that unwinding
2979 still works. Trashes r3. */
2981 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2982 "addi 1,1,-" #_n_fr "\n\t" \
2983 "lwz 3," #_n_fr "(1)\n\t" \
2986 #define VG_CONTRACT_FRAME_BY(_n_fr) \
2987 "addi 1,1," #_n_fr "\n\t"
2989 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2992 #define CALL_FN_W_v(lval, orig) \
2994 volatile OrigFn _orig = (orig); \
2995 volatile unsigned long _argvec[3+0]; \
2996 volatile unsigned long _res; \
2997 /* _argvec[0] holds current r2 across the call */ \
2998 _argvec[1] = (unsigned long)_orig.r2; \
2999 _argvec[2] = (unsigned long)_orig.nraddr; \
3002 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3003 "stw 2,-8(11)\n\t" /* save tocptr */ \
3004 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3005 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3006 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3009 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3010 VG_CONTRACT_FRAME_BY(512) \
3011 : /*out*/ "=r" (_res) \
3012 : /*in*/ "r" (&_argvec[2]) \
3013 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3015 lval = (__typeof__(lval)) _res; \
3018 #define CALL_FN_W_W(lval, orig, arg1) \
3020 volatile OrigFn _orig = (orig); \
3021 volatile unsigned long _argvec[3+1]; \
3022 volatile unsigned long _res; \
3023 /* _argvec[0] holds current r2 across the call */ \
3024 _argvec[1] = (unsigned long)_orig.r2; \
3025 _argvec[2] = (unsigned long)_orig.nraddr; \
3026 _argvec[2+1] = (unsigned long)arg1; \
3029 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3030 "stw 2,-8(11)\n\t" /* save tocptr */ \
3031 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3032 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3033 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3034 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3037 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3038 VG_CONTRACT_FRAME_BY(512) \
3039 : /*out*/ "=r" (_res) \
3040 : /*in*/ "r" (&_argvec[2]) \
3041 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3043 lval = (__typeof__(lval)) _res; \
3046 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3048 volatile OrigFn _orig = (orig); \
3049 volatile unsigned long _argvec[3+2]; \
3050 volatile unsigned long _res; \
3051 /* _argvec[0] holds current r2 across the call */ \
3052 _argvec[1] = (unsigned long)_orig.r2; \
3053 _argvec[2] = (unsigned long)_orig.nraddr; \
3054 _argvec[2+1] = (unsigned long)arg1; \
3055 _argvec[2+2] = (unsigned long)arg2; \
3058 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3059 "stw 2,-8(11)\n\t" /* save tocptr */ \
3060 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3061 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3062 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3063 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3064 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3067 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3068 VG_CONTRACT_FRAME_BY(512) \
3069 : /*out*/ "=r" (_res) \
3070 : /*in*/ "r" (&_argvec[2]) \
3071 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3073 lval = (__typeof__(lval)) _res; \
3076 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3078 volatile OrigFn _orig = (orig); \
3079 volatile unsigned long _argvec[3+3]; \
3080 volatile unsigned long _res; \
3081 /* _argvec[0] holds current r2 across the call */ \
3082 _argvec[1] = (unsigned long)_orig.r2; \
3083 _argvec[2] = (unsigned long)_orig.nraddr; \
3084 _argvec[2+1] = (unsigned long)arg1; \
3085 _argvec[2+2] = (unsigned long)arg2; \
3086 _argvec[2+3] = (unsigned long)arg3; \
3089 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3090 "stw 2,-8(11)\n\t" /* save tocptr */ \
3091 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3092 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3093 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3094 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3095 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3096 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3099 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3100 VG_CONTRACT_FRAME_BY(512) \
3101 : /*out*/ "=r" (_res) \
3102 : /*in*/ "r" (&_argvec[2]) \
3103 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3105 lval = (__typeof__(lval)) _res; \
3108 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3110 volatile OrigFn _orig = (orig); \
3111 volatile unsigned long _argvec[3+4]; \
3112 volatile unsigned long _res; \
3113 /* _argvec[0] holds current r2 across the call */ \
3114 _argvec[1] = (unsigned long)_orig.r2; \
3115 _argvec[2] = (unsigned long)_orig.nraddr; \
3116 _argvec[2+1] = (unsigned long)arg1; \
3117 _argvec[2+2] = (unsigned long)arg2; \
3118 _argvec[2+3] = (unsigned long)arg3; \
3119 _argvec[2+4] = (unsigned long)arg4; \
3122 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3123 "stw 2,-8(11)\n\t" /* save tocptr */ \
3124 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3125 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3126 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3127 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3128 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3129 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3130 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3133 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3134 VG_CONTRACT_FRAME_BY(512) \
3135 : /*out*/ "=r" (_res) \
3136 : /*in*/ "r" (&_argvec[2]) \
3137 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3139 lval = (__typeof__(lval)) _res; \
3142 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3144 volatile OrigFn _orig = (orig); \
3145 volatile unsigned long _argvec[3+5]; \
3146 volatile unsigned long _res; \
3147 /* _argvec[0] holds current r2 across the call */ \
3148 _argvec[1] = (unsigned long)_orig.r2; \
3149 _argvec[2] = (unsigned long)_orig.nraddr; \
3150 _argvec[2+1] = (unsigned long)arg1; \
3151 _argvec[2+2] = (unsigned long)arg2; \
3152 _argvec[2+3] = (unsigned long)arg3; \
3153 _argvec[2+4] = (unsigned long)arg4; \
3154 _argvec[2+5] = (unsigned long)arg5; \
3157 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3158 "stw 2,-8(11)\n\t" /* save tocptr */ \
3159 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3160 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3161 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3162 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3163 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3164 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3165 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3166 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3169 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3170 VG_CONTRACT_FRAME_BY(512) \
3171 : /*out*/ "=r" (_res) \
3172 : /*in*/ "r" (&_argvec[2]) \
3173 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3175 lval = (__typeof__(lval)) _res; \
3178 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3180 volatile OrigFn _orig = (orig); \
3181 volatile unsigned long _argvec[3+6]; \
3182 volatile unsigned long _res; \
3183 /* _argvec[0] holds current r2 across the call */ \
3184 _argvec[1] = (unsigned long)_orig.r2; \
3185 _argvec[2] = (unsigned long)_orig.nraddr; \
3186 _argvec[2+1] = (unsigned long)arg1; \
3187 _argvec[2+2] = (unsigned long)arg2; \
3188 _argvec[2+3] = (unsigned long)arg3; \
3189 _argvec[2+4] = (unsigned long)arg4; \
3190 _argvec[2+5] = (unsigned long)arg5; \
3191 _argvec[2+6] = (unsigned long)arg6; \
3194 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3195 "stw 2,-8(11)\n\t" /* save tocptr */ \
3196 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3197 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3198 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3199 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3200 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3201 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3202 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3203 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3204 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3207 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3208 VG_CONTRACT_FRAME_BY(512) \
3209 : /*out*/ "=r" (_res) \
3210 : /*in*/ "r" (&_argvec[2]) \
3211 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3213 lval = (__typeof__(lval)) _res; \
3216 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3219 volatile OrigFn _orig = (orig); \
3220 volatile unsigned long _argvec[3+7]; \
3221 volatile unsigned long _res; \
3222 /* _argvec[0] holds current r2 across the call */ \
3223 _argvec[1] = (unsigned long)_orig.r2; \
3224 _argvec[2] = (unsigned long)_orig.nraddr; \
3225 _argvec[2+1] = (unsigned long)arg1; \
3226 _argvec[2+2] = (unsigned long)arg2; \
3227 _argvec[2+3] = (unsigned long)arg3; \
3228 _argvec[2+4] = (unsigned long)arg4; \
3229 _argvec[2+5] = (unsigned long)arg5; \
3230 _argvec[2+6] = (unsigned long)arg6; \
3231 _argvec[2+7] = (unsigned long)arg7; \
3234 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3235 "stw 2,-8(11)\n\t" /* save tocptr */ \
3236 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3237 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3238 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3239 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3240 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3241 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3242 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3243 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3244 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3245 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3248 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3249 VG_CONTRACT_FRAME_BY(512) \
3250 : /*out*/ "=r" (_res) \
3251 : /*in*/ "r" (&_argvec[2]) \
3252 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3254 lval = (__typeof__(lval)) _res; \
3257 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3260 volatile OrigFn _orig = (orig); \
3261 volatile unsigned long _argvec[3+8]; \
3262 volatile unsigned long _res; \
3263 /* _argvec[0] holds current r2 across the call */ \
3264 _argvec[1] = (unsigned long)_orig.r2; \
3265 _argvec[2] = (unsigned long)_orig.nraddr; \
3266 _argvec[2+1] = (unsigned long)arg1; \
3267 _argvec[2+2] = (unsigned long)arg2; \
3268 _argvec[2+3] = (unsigned long)arg3; \
3269 _argvec[2+4] = (unsigned long)arg4; \
3270 _argvec[2+5] = (unsigned long)arg5; \
3271 _argvec[2+6] = (unsigned long)arg6; \
3272 _argvec[2+7] = (unsigned long)arg7; \
3273 _argvec[2+8] = (unsigned long)arg8; \
3276 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3277 "stw 2,-8(11)\n\t" /* save tocptr */ \
3278 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3279 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3280 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3281 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3282 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3283 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3284 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3285 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3286 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3287 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3288 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3291 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3292 VG_CONTRACT_FRAME_BY(512) \
3293 : /*out*/ "=r" (_res) \
3294 : /*in*/ "r" (&_argvec[2]) \
3295 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3297 lval = (__typeof__(lval)) _res; \
3300 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3303 volatile OrigFn _orig = (orig); \
3304 volatile unsigned long _argvec[3+9]; \
3305 volatile unsigned long _res; \
3306 /* _argvec[0] holds current r2 across the call */ \
3307 _argvec[1] = (unsigned long)_orig.r2; \
3308 _argvec[2] = (unsigned long)_orig.nraddr; \
3309 _argvec[2+1] = (unsigned long)arg1; \
3310 _argvec[2+2] = (unsigned long)arg2; \
3311 _argvec[2+3] = (unsigned long)arg3; \
3312 _argvec[2+4] = (unsigned long)arg4; \
3313 _argvec[2+5] = (unsigned long)arg5; \
3314 _argvec[2+6] = (unsigned long)arg6; \
3315 _argvec[2+7] = (unsigned long)arg7; \
3316 _argvec[2+8] = (unsigned long)arg8; \
3317 _argvec[2+9] = (unsigned long)arg9; \
3320 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3321 "stw 2,-8(11)\n\t" /* save tocptr */ \
3322 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3323 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3325 "lwz 3,36(11)\n\t" \
3328 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3329 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3330 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3331 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3332 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3333 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3334 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3335 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3336 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3337 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3340 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3341 VG_CONTRACT_FRAME_BY(64) \
3342 VG_CONTRACT_FRAME_BY(512) \
3343 : /*out*/ "=r" (_res) \
3344 : /*in*/ "r" (&_argvec[2]) \
3345 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3347 lval = (__typeof__(lval)) _res; \
3350 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3351 arg7,arg8,arg9,arg10) \
3353 volatile OrigFn _orig = (orig); \
3354 volatile unsigned long _argvec[3+10]; \
3355 volatile unsigned long _res; \
3356 /* _argvec[0] holds current r2 across the call */ \
3357 _argvec[1] = (unsigned long)_orig.r2; \
3358 _argvec[2] = (unsigned long)_orig.nraddr; \
3359 _argvec[2+1] = (unsigned long)arg1; \
3360 _argvec[2+2] = (unsigned long)arg2; \
3361 _argvec[2+3] = (unsigned long)arg3; \
3362 _argvec[2+4] = (unsigned long)arg4; \
3363 _argvec[2+5] = (unsigned long)arg5; \
3364 _argvec[2+6] = (unsigned long)arg6; \
3365 _argvec[2+7] = (unsigned long)arg7; \
3366 _argvec[2+8] = (unsigned long)arg8; \
3367 _argvec[2+9] = (unsigned long)arg9; \
3368 _argvec[2+10] = (unsigned long)arg10; \
3371 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3372 "stw 2,-8(11)\n\t" /* save tocptr */ \
3373 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3374 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3376 "lwz 3,40(11)\n\t" \
3379 "lwz 3,36(11)\n\t" \
3382 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3383 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3384 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3385 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3386 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3387 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3388 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3389 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3390 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3391 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3394 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3395 VG_CONTRACT_FRAME_BY(64) \
3396 VG_CONTRACT_FRAME_BY(512) \
3397 : /*out*/ "=r" (_res) \
3398 : /*in*/ "r" (&_argvec[2]) \
3399 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3401 lval = (__typeof__(lval)) _res; \
3404 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3405 arg7,arg8,arg9,arg10,arg11) \
3407 volatile OrigFn _orig = (orig); \
3408 volatile unsigned long _argvec[3+11]; \
3409 volatile unsigned long _res; \
3410 /* _argvec[0] holds current r2 across the call */ \
3411 _argvec[1] = (unsigned long)_orig.r2; \
3412 _argvec[2] = (unsigned long)_orig.nraddr; \
3413 _argvec[2+1] = (unsigned long)arg1; \
3414 _argvec[2+2] = (unsigned long)arg2; \
3415 _argvec[2+3] = (unsigned long)arg3; \
3416 _argvec[2+4] = (unsigned long)arg4; \
3417 _argvec[2+5] = (unsigned long)arg5; \
3418 _argvec[2+6] = (unsigned long)arg6; \
3419 _argvec[2+7] = (unsigned long)arg7; \
3420 _argvec[2+8] = (unsigned long)arg8; \
3421 _argvec[2+9] = (unsigned long)arg9; \
3422 _argvec[2+10] = (unsigned long)arg10; \
3423 _argvec[2+11] = (unsigned long)arg11; \
3426 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3427 "stw 2,-8(11)\n\t" /* save tocptr */ \
3428 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3429 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3431 "lwz 3,44(11)\n\t" \
3434 "lwz 3,40(11)\n\t" \
3437 "lwz 3,36(11)\n\t" \
3440 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3441 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3442 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3443 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3444 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3445 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3446 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3447 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3448 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3449 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3452 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3453 VG_CONTRACT_FRAME_BY(72) \
3454 VG_CONTRACT_FRAME_BY(512) \
3455 : /*out*/ "=r" (_res) \
3456 : /*in*/ "r" (&_argvec[2]) \
3457 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3459 lval = (__typeof__(lval)) _res; \
3462 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3463 arg7,arg8,arg9,arg10,arg11,arg12) \
3465 volatile OrigFn _orig = (orig); \
3466 volatile unsigned long _argvec[3+12]; \
3467 volatile unsigned long _res; \
3468 /* _argvec[0] holds current r2 across the call */ \
3469 _argvec[1] = (unsigned long)_orig.r2; \
3470 _argvec[2] = (unsigned long)_orig.nraddr; \
3471 _argvec[2+1] = (unsigned long)arg1; \
3472 _argvec[2+2] = (unsigned long)arg2; \
3473 _argvec[2+3] = (unsigned long)arg3; \
3474 _argvec[2+4] = (unsigned long)arg4; \
3475 _argvec[2+5] = (unsigned long)arg5; \
3476 _argvec[2+6] = (unsigned long)arg6; \
3477 _argvec[2+7] = (unsigned long)arg7; \
3478 _argvec[2+8] = (unsigned long)arg8; \
3479 _argvec[2+9] = (unsigned long)arg9; \
3480 _argvec[2+10] = (unsigned long)arg10; \
3481 _argvec[2+11] = (unsigned long)arg11; \
3482 _argvec[2+12] = (unsigned long)arg12; \
3485 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3486 "stw 2,-8(11)\n\t" /* save tocptr */ \
3487 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3488 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3490 "lwz 3,48(11)\n\t" \
3493 "lwz 3,44(11)\n\t" \
3496 "lwz 3,40(11)\n\t" \
3499 "lwz 3,36(11)\n\t" \
3502 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3503 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3504 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3505 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3506 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3507 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3508 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3509 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3510 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3511 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3514 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3515 VG_CONTRACT_FRAME_BY(72) \
3516 VG_CONTRACT_FRAME_BY(512) \
3517 : /*out*/ "=r" (_res) \
3518 : /*in*/ "r" (&_argvec[2]) \
3519 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3521 lval = (__typeof__(lval)) _res; \
3524 #endif /* PLAT_ppc32_aix5 */
3526 /* ------------------------ ppc64-aix5 ------------------------- */
3528 #if defined(PLAT_ppc64_aix5)
3530 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3532 /* These regs are trashed by the hidden call. */
3533 #define __CALLER_SAVED_REGS \
3534 "lr", "ctr", "xer", \
3535 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3536 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3539 /* Expand the stack frame, copying enough info that unwinding
3540 still works. Trashes r3. */
3542 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3543 "addi 1,1,-" #_n_fr "\n\t" \
3544 "ld 3," #_n_fr "(1)\n\t" \
3547 #define VG_CONTRACT_FRAME_BY(_n_fr) \
3548 "addi 1,1," #_n_fr "\n\t"
3550 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3553 #define CALL_FN_W_v(lval, orig) \
3555 volatile OrigFn _orig = (orig); \
3556 volatile unsigned long _argvec[3+0]; \
3557 volatile unsigned long _res; \
3558 /* _argvec[0] holds current r2 across the call */ \
3559 _argvec[1] = (unsigned long)_orig.r2; \
3560 _argvec[2] = (unsigned long)_orig.nraddr; \
3563 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3564 "std 2,-16(11)\n\t" /* save tocptr */ \
3565 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3566 "ld 11, 0(11)\n\t" /* target->r11 */ \
3567 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3570 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3571 VG_CONTRACT_FRAME_BY(512) \
3572 : /*out*/ "=r" (_res) \
3573 : /*in*/ "r" (&_argvec[2]) \
3574 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3576 lval = (__typeof__(lval)) _res; \
3579 #define CALL_FN_W_W(lval, orig, arg1) \
3581 volatile OrigFn _orig = (orig); \
3582 volatile unsigned long _argvec[3+1]; \
3583 volatile unsigned long _res; \
3584 /* _argvec[0] holds current r2 across the call */ \
3585 _argvec[1] = (unsigned long)_orig.r2; \
3586 _argvec[2] = (unsigned long)_orig.nraddr; \
3587 _argvec[2+1] = (unsigned long)arg1; \
3590 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3591 "std 2,-16(11)\n\t" /* save tocptr */ \
3592 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3593 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3594 "ld 11, 0(11)\n\t" /* target->r11 */ \
3595 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3598 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3599 VG_CONTRACT_FRAME_BY(512) \
3600 : /*out*/ "=r" (_res) \
3601 : /*in*/ "r" (&_argvec[2]) \
3602 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3604 lval = (__typeof__(lval)) _res; \
3607 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3609 volatile OrigFn _orig = (orig); \
3610 volatile unsigned long _argvec[3+2]; \
3611 volatile unsigned long _res; \
3612 /* _argvec[0] holds current r2 across the call */ \
3613 _argvec[1] = (unsigned long)_orig.r2; \
3614 _argvec[2] = (unsigned long)_orig.nraddr; \
3615 _argvec[2+1] = (unsigned long)arg1; \
3616 _argvec[2+2] = (unsigned long)arg2; \
3619 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3620 "std 2,-16(11)\n\t" /* save tocptr */ \
3621 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3622 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3623 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3624 "ld 11, 0(11)\n\t" /* target->r11 */ \
3625 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3628 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3629 VG_CONTRACT_FRAME_BY(512) \
3630 : /*out*/ "=r" (_res) \
3631 : /*in*/ "r" (&_argvec[2]) \
3632 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3634 lval = (__typeof__(lval)) _res; \
3637 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3639 volatile OrigFn _orig = (orig); \
3640 volatile unsigned long _argvec[3+3]; \
3641 volatile unsigned long _res; \
3642 /* _argvec[0] holds current r2 across the call */ \
3643 _argvec[1] = (unsigned long)_orig.r2; \
3644 _argvec[2] = (unsigned long)_orig.nraddr; \
3645 _argvec[2+1] = (unsigned long)arg1; \
3646 _argvec[2+2] = (unsigned long)arg2; \
3647 _argvec[2+3] = (unsigned long)arg3; \
3650 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3651 "std 2,-16(11)\n\t" /* save tocptr */ \
3652 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3653 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3654 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3655 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3656 "ld 11, 0(11)\n\t" /* target->r11 */ \
3657 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3660 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3661 VG_CONTRACT_FRAME_BY(512) \
3662 : /*out*/ "=r" (_res) \
3663 : /*in*/ "r" (&_argvec[2]) \
3664 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3666 lval = (__typeof__(lval)) _res; \
3669 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3671 volatile OrigFn _orig = (orig); \
3672 volatile unsigned long _argvec[3+4]; \
3673 volatile unsigned long _res; \
3674 /* _argvec[0] holds current r2 across the call */ \
3675 _argvec[1] = (unsigned long)_orig.r2; \
3676 _argvec[2] = (unsigned long)_orig.nraddr; \
3677 _argvec[2+1] = (unsigned long)arg1; \
3678 _argvec[2+2] = (unsigned long)arg2; \
3679 _argvec[2+3] = (unsigned long)arg3; \
3680 _argvec[2+4] = (unsigned long)arg4; \
3683 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3684 "std 2,-16(11)\n\t" /* save tocptr */ \
3685 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3686 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3687 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3688 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3689 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3690 "ld 11, 0(11)\n\t" /* target->r11 */ \
3691 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3694 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3695 VG_CONTRACT_FRAME_BY(512) \
3696 : /*out*/ "=r" (_res) \
3697 : /*in*/ "r" (&_argvec[2]) \
3698 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3700 lval = (__typeof__(lval)) _res; \
3703 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3705 volatile OrigFn _orig = (orig); \
3706 volatile unsigned long _argvec[3+5]; \
3707 volatile unsigned long _res; \
3708 /* _argvec[0] holds current r2 across the call */ \
3709 _argvec[1] = (unsigned long)_orig.r2; \
3710 _argvec[2] = (unsigned long)_orig.nraddr; \
3711 _argvec[2+1] = (unsigned long)arg1; \
3712 _argvec[2+2] = (unsigned long)arg2; \
3713 _argvec[2+3] = (unsigned long)arg3; \
3714 _argvec[2+4] = (unsigned long)arg4; \
3715 _argvec[2+5] = (unsigned long)arg5; \
3718 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3719 "std 2,-16(11)\n\t" /* save tocptr */ \
3720 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3721 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3722 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3723 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3724 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3725 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3726 "ld 11, 0(11)\n\t" /* target->r11 */ \
3727 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3730 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3731 VG_CONTRACT_FRAME_BY(512) \
3732 : /*out*/ "=r" (_res) \
3733 : /*in*/ "r" (&_argvec[2]) \
3734 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3736 lval = (__typeof__(lval)) _res; \
3739 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3741 volatile OrigFn _orig = (orig); \
3742 volatile unsigned long _argvec[3+6]; \
3743 volatile unsigned long _res; \
3744 /* _argvec[0] holds current r2 across the call */ \
3745 _argvec[1] = (unsigned long)_orig.r2; \
3746 _argvec[2] = (unsigned long)_orig.nraddr; \
3747 _argvec[2+1] = (unsigned long)arg1; \
3748 _argvec[2+2] = (unsigned long)arg2; \
3749 _argvec[2+3] = (unsigned long)arg3; \
3750 _argvec[2+4] = (unsigned long)arg4; \
3751 _argvec[2+5] = (unsigned long)arg5; \
3752 _argvec[2+6] = (unsigned long)arg6; \
3755 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3756 "std 2,-16(11)\n\t" /* save tocptr */ \
3757 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3758 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3759 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3760 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3761 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3762 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3763 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3764 "ld 11, 0(11)\n\t" /* target->r11 */ \
3765 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3768 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3769 VG_CONTRACT_FRAME_BY(512) \
3770 : /*out*/ "=r" (_res) \
3771 : /*in*/ "r" (&_argvec[2]) \
3772 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3774 lval = (__typeof__(lval)) _res; \
3777 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3780 volatile OrigFn _orig = (orig); \
3781 volatile unsigned long _argvec[3+7]; \
3782 volatile unsigned long _res; \
3783 /* _argvec[0] holds current r2 across the call */ \
3784 _argvec[1] = (unsigned long)_orig.r2; \
3785 _argvec[2] = (unsigned long)_orig.nraddr; \
3786 _argvec[2+1] = (unsigned long)arg1; \
3787 _argvec[2+2] = (unsigned long)arg2; \
3788 _argvec[2+3] = (unsigned long)arg3; \
3789 _argvec[2+4] = (unsigned long)arg4; \
3790 _argvec[2+5] = (unsigned long)arg5; \
3791 _argvec[2+6] = (unsigned long)arg6; \
3792 _argvec[2+7] = (unsigned long)arg7; \
3795 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3796 "std 2,-16(11)\n\t" /* save tocptr */ \
3797 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3798 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3799 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3800 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3801 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3802 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3803 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3804 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3805 "ld 11, 0(11)\n\t" /* target->r11 */ \
3806 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3809 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3810 VG_CONTRACT_FRAME_BY(512) \
3811 : /*out*/ "=r" (_res) \
3812 : /*in*/ "r" (&_argvec[2]) \
3813 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3815 lval = (__typeof__(lval)) _res; \
3818 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3821 volatile OrigFn _orig = (orig); \
3822 volatile unsigned long _argvec[3+8]; \
3823 volatile unsigned long _res; \
3824 /* _argvec[0] holds current r2 across the call */ \
3825 _argvec[1] = (unsigned long)_orig.r2; \
3826 _argvec[2] = (unsigned long)_orig.nraddr; \
3827 _argvec[2+1] = (unsigned long)arg1; \
3828 _argvec[2+2] = (unsigned long)arg2; \
3829 _argvec[2+3] = (unsigned long)arg3; \
3830 _argvec[2+4] = (unsigned long)arg4; \
3831 _argvec[2+5] = (unsigned long)arg5; \
3832 _argvec[2+6] = (unsigned long)arg6; \
3833 _argvec[2+7] = (unsigned long)arg7; \
3834 _argvec[2+8] = (unsigned long)arg8; \
3837 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3838 "std 2,-16(11)\n\t" /* save tocptr */ \
3839 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3840 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3841 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3842 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3843 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3844 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3845 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3846 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3847 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3848 "ld 11, 0(11)\n\t" /* target->r11 */ \
3849 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3852 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3853 VG_CONTRACT_FRAME_BY(512) \
3854 : /*out*/ "=r" (_res) \
3855 : /*in*/ "r" (&_argvec[2]) \
3856 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3858 lval = (__typeof__(lval)) _res; \
3861 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3864 volatile OrigFn _orig = (orig); \
3865 volatile unsigned long _argvec[3+9]; \
3866 volatile unsigned long _res; \
3867 /* _argvec[0] holds current r2 across the call */ \
3868 _argvec[1] = (unsigned long)_orig.r2; \
3869 _argvec[2] = (unsigned long)_orig.nraddr; \
3870 _argvec[2+1] = (unsigned long)arg1; \
3871 _argvec[2+2] = (unsigned long)arg2; \
3872 _argvec[2+3] = (unsigned long)arg3; \
3873 _argvec[2+4] = (unsigned long)arg4; \
3874 _argvec[2+5] = (unsigned long)arg5; \
3875 _argvec[2+6] = (unsigned long)arg6; \
3876 _argvec[2+7] = (unsigned long)arg7; \
3877 _argvec[2+8] = (unsigned long)arg8; \
3878 _argvec[2+9] = (unsigned long)arg9; \
3881 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3882 "std 2,-16(11)\n\t" /* save tocptr */ \
3883 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3884 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3887 "std 3,112(1)\n\t" \
3889 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3890 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3891 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3892 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3893 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3894 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3895 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3896 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3897 "ld 11, 0(11)\n\t" /* target->r11 */ \
3898 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3901 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3902 VG_CONTRACT_FRAME_BY(128) \
3903 VG_CONTRACT_FRAME_BY(512) \
3904 : /*out*/ "=r" (_res) \
3905 : /*in*/ "r" (&_argvec[2]) \
3906 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3908 lval = (__typeof__(lval)) _res; \
3911 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3912 arg7,arg8,arg9,arg10) \
3914 volatile OrigFn _orig = (orig); \
3915 volatile unsigned long _argvec[3+10]; \
3916 volatile unsigned long _res; \
3917 /* _argvec[0] holds current r2 across the call */ \
3918 _argvec[1] = (unsigned long)_orig.r2; \
3919 _argvec[2] = (unsigned long)_orig.nraddr; \
3920 _argvec[2+1] = (unsigned long)arg1; \
3921 _argvec[2+2] = (unsigned long)arg2; \
3922 _argvec[2+3] = (unsigned long)arg3; \
3923 _argvec[2+4] = (unsigned long)arg4; \
3924 _argvec[2+5] = (unsigned long)arg5; \
3925 _argvec[2+6] = (unsigned long)arg6; \
3926 _argvec[2+7] = (unsigned long)arg7; \
3927 _argvec[2+8] = (unsigned long)arg8; \
3928 _argvec[2+9] = (unsigned long)arg9; \
3929 _argvec[2+10] = (unsigned long)arg10; \
3932 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3933 "std 2,-16(11)\n\t" /* save tocptr */ \
3934 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3935 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3938 "std 3,120(1)\n\t" \
3941 "std 3,112(1)\n\t" \
3943 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3944 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3945 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3946 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3947 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3948 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3949 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3950 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3951 "ld 11, 0(11)\n\t" /* target->r11 */ \
3952 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3955 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3956 VG_CONTRACT_FRAME_BY(128) \
3957 VG_CONTRACT_FRAME_BY(512) \
3958 : /*out*/ "=r" (_res) \
3959 : /*in*/ "r" (&_argvec[2]) \
3960 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3962 lval = (__typeof__(lval)) _res; \
3965 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3966 arg7,arg8,arg9,arg10,arg11) \
3968 volatile OrigFn _orig = (orig); \
3969 volatile unsigned long _argvec[3+11]; \
3970 volatile unsigned long _res; \
3971 /* _argvec[0] holds current r2 across the call */ \
3972 _argvec[1] = (unsigned long)_orig.r2; \
3973 _argvec[2] = (unsigned long)_orig.nraddr; \
3974 _argvec[2+1] = (unsigned long)arg1; \
3975 _argvec[2+2] = (unsigned long)arg2; \
3976 _argvec[2+3] = (unsigned long)arg3; \
3977 _argvec[2+4] = (unsigned long)arg4; \
3978 _argvec[2+5] = (unsigned long)arg5; \
3979 _argvec[2+6] = (unsigned long)arg6; \
3980 _argvec[2+7] = (unsigned long)arg7; \
3981 _argvec[2+8] = (unsigned long)arg8; \
3982 _argvec[2+9] = (unsigned long)arg9; \
3983 _argvec[2+10] = (unsigned long)arg10; \
3984 _argvec[2+11] = (unsigned long)arg11; \
3987 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3988 "std 2,-16(11)\n\t" /* save tocptr */ \
3989 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3990 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3993 "std 3,128(1)\n\t" \
3996 "std 3,120(1)\n\t" \
3999 "std 3,112(1)\n\t" \
4001 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4002 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4003 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4004 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4005 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4006 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4007 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4008 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4009 "ld 11, 0(11)\n\t" /* target->r11 */ \
4010 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4013 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4014 VG_CONTRACT_FRAME_BY(144) \
4015 VG_CONTRACT_FRAME_BY(512) \
4016 : /*out*/ "=r" (_res) \
4017 : /*in*/ "r" (&_argvec[2]) \
4018 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4020 lval = (__typeof__(lval)) _res; \
4023 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4024 arg7,arg8,arg9,arg10,arg11,arg12) \
4026 volatile OrigFn _orig = (orig); \
4027 volatile unsigned long _argvec[3+12]; \
4028 volatile unsigned long _res; \
4029 /* _argvec[0] holds current r2 across the call */ \
4030 _argvec[1] = (unsigned long)_orig.r2; \
4031 _argvec[2] = (unsigned long)_orig.nraddr; \
4032 _argvec[2+1] = (unsigned long)arg1; \
4033 _argvec[2+2] = (unsigned long)arg2; \
4034 _argvec[2+3] = (unsigned long)arg3; \
4035 _argvec[2+4] = (unsigned long)arg4; \
4036 _argvec[2+5] = (unsigned long)arg5; \
4037 _argvec[2+6] = (unsigned long)arg6; \
4038 _argvec[2+7] = (unsigned long)arg7; \
4039 _argvec[2+8] = (unsigned long)arg8; \
4040 _argvec[2+9] = (unsigned long)arg9; \
4041 _argvec[2+10] = (unsigned long)arg10; \
4042 _argvec[2+11] = (unsigned long)arg11; \
4043 _argvec[2+12] = (unsigned long)arg12; \
4046 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4047 "std 2,-16(11)\n\t" /* save tocptr */ \
4048 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4049 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4052 "std 3,136(1)\n\t" \
4055 "std 3,128(1)\n\t" \
4058 "std 3,120(1)\n\t" \
4061 "std 3,112(1)\n\t" \
4063 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4064 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4065 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4066 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4067 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4068 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4069 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4070 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4071 "ld 11, 0(11)\n\t" /* target->r11 */ \
4072 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4075 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4076 VG_CONTRACT_FRAME_BY(144) \
4077 VG_CONTRACT_FRAME_BY(512) \
4078 : /*out*/ "=r" (_res) \
4079 : /*in*/ "r" (&_argvec[2]) \
4080 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4082 lval = (__typeof__(lval)) _res; \
4085 #endif /* PLAT_ppc64_aix5 */
4088 /* ------------------------------------------------------------------ */
4089 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4091 /* ------------------------------------------------------------------ */
4093 /* Some request codes. There are many more of these, but most are not
4094 exposed to end-user view. These are the public ones, all of the
4095 form 0x1000 + small_number.
4097 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4098 ones start at 0x2000.
4101 /* These macros are used by tools -- they must be public, but don't
4102 embed them into other programs. */
4103 #define VG_USERREQ_TOOL_BASE(a,b) \
4104 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
4105 #define VG_IS_TOOL_USERREQ(a, b, v) \
4106 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
4108 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4109 This enum comprises an ABI exported by Valgrind to programs
4110 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4111 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
4113 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4114 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
4116 /* These allow any function to be called from the simulated
4117 CPU but run on the real CPU. Nb: the first arg passed to
4118 the function is always the ThreadId of the running
4119 thread! So CLIENT_CALL0 actually requires a 1 arg
4121 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4122 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4123 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4124 VG_USERREQ__CLIENT_CALL3 = 0x1104,
4126 /* Can be useful in regression testing suites -- eg. can
4127 send Valgrind's output to /dev/null and still count
4129 VG_USERREQ__COUNT_ERRORS = 0x1201,
4131 /* These are useful and can be interpreted by any tool that
4132 tracks malloc() et al, by using vg_replace_malloc.c. */
4133 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4134 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
4135 /* Memory pool support. */
4136 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4137 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4138 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4139 VG_USERREQ__MEMPOOL_FREE = 0x1306,
4140 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
4141 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4142 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4143 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
4145 /* Allow printfs to valgrind log. */
4146 /* The first two pass the va_list argument by value, which
4147 assumes it is the same size as or smaller than a UWord,
4148 which generally isn't the case. Hence are deprecated.
4149 The second two pass the vargs by reference and so are
4150 immune to this problem. */
4151 /* both :: char* fmt, va_list vargs (DEPRECATED) */
4152 VG_USERREQ__PRINTF = 0x1401,
4153 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
4154 /* both :: char* fmt, va_list* vargs */
4155 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4156 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
4158 /* Stack support. */
4159 VG_USERREQ__STACK_REGISTER = 0x1501,
4160 VG_USERREQ__STACK_DEREGISTER = 0x1502,
4161 VG_USERREQ__STACK_CHANGE = 0x1503,
4164 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
4167 #if !defined(__GNUC__)
4168 # define __extension__ /* */
4171 /* Returns the number of Valgrinds this code is running under. That
4172 is, 0 if running natively, 1 if running under Valgrind, 2 if
4173 running under Valgrind which is running under another Valgrind,
4175 #define RUNNING_ON_VALGRIND __extension__ \
4176 ({unsigned int _qzz_res; \
4177 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
4178 VG_USERREQ__RUNNING_ON_VALGRIND, \
4184 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4185 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4186 since it provides a way to make sure valgrind will retranslate the
4187 invalidated area. Returns no value. */
4188 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4189 {unsigned int _qzz_res; \
4190 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4191 VG_USERREQ__DISCARD_TRANSLATIONS, \
4192 _qzz_addr, _qzz_len, 0, 0, 0); \
4196 /* These requests are for getting Valgrind itself to print something.
4197 Possibly with a backtrace. This is a really ugly hack. The return value
4198 is the number of characters printed, excluding the "**<pid>** " part at the
4199 start and the backtrace (if present). */
4201 #if defined(NVALGRIND)
4203 # define VALGRIND_PRINTF(...)
4204 # define VALGRIND_PRINTF_BACKTRACE(...)
4206 #else /* NVALGRIND */
4208 /* Modern GCC will optimize the static routine out if unused,
4209 and unused attribute will shut down warnings about it. */
4210 static int VALGRIND_PRINTF(const char *format, ...)
4211 __attribute__((format(__printf__, 1, 2), __unused__));
4213 VALGRIND_PRINTF(const char *format, ...)
4215 unsigned long _qzz_res;
4217 va_start(vargs, format);
4218 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4219 VG_USERREQ__PRINTF_VALIST_BY_REF,
4220 (unsigned long)format,
4221 (unsigned long)&vargs,
4224 return (int)_qzz_res;
4227 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4228 __attribute__((format(__printf__, 1, 2), __unused__));
4230 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4232 unsigned long _qzz_res;
4234 va_start(vargs, format);
4235 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4236 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
4237 (unsigned long)format,
4238 (unsigned long)&vargs,
4241 return (int)_qzz_res;
4244 #endif /* NVALGRIND */
4247 /* These requests allow control to move from the simulated CPU to the
4248 real CPU, calling an arbitary function.
4250 Note that the current ThreadId is inserted as the first argument.
4253 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4255 requires f to have this signature:
4257 Word f(Word tid, Word arg1, Word arg2)
4259 where "Word" is a word-sized type.
4261 Note that these client requests are not entirely reliable. For example,
4262 if you call a function with them that subsequently calls printf(),
4263 there's a high chance Valgrind will crash. Generally, your prospects of
4264 these working are made higher if the called function does not refer to
4265 any global variables, and does not refer to any libc or other functions
4266 (printf et al). Any kind of entanglement with libc or dynamic linking is
4267 likely to have a bad outcome, for tricky reasons which we've grappled
4268 with a lot in the past.
4270 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
4272 ({unsigned long _qyy_res; \
4273 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4274 VG_USERREQ__CLIENT_CALL0, \
4280 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
4282 ({unsigned long _qyy_res; \
4283 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4284 VG_USERREQ__CLIENT_CALL1, \
4286 _qyy_arg1, 0, 0, 0); \
4290 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
4292 ({unsigned long _qyy_res; \
4293 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4294 VG_USERREQ__CLIENT_CALL2, \
4296 _qyy_arg1, _qyy_arg2, 0, 0); \
4300 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
4302 ({unsigned long _qyy_res; \
4303 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4304 VG_USERREQ__CLIENT_CALL3, \
4306 _qyy_arg1, _qyy_arg2, \
4312 /* Counts the number of errors that have been recorded by a tool. Nb:
4313 the tool must record the errors with VG_(maybe_record_error)() or
4314 VG_(unique_error)() for them to be counted. */
4315 #define VALGRIND_COUNT_ERRORS \
4317 ({unsigned int _qyy_res; \
4318 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4319 VG_USERREQ__COUNT_ERRORS, \
4324 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4325 when heap blocks are allocated in order to give accurate results. This
4326 happens automatically for the standard allocator functions such as
4327 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4330 But if your program uses a custom allocator, this doesn't automatically
4331 happen, and Valgrind will not do as well. For example, if you allocate
4332 superblocks with mmap() and then allocates chunks of the superblocks, all
4333 Valgrind's observations will be at the mmap() level and it won't know that
4334 the chunks should be considered separate entities. In Memcheck's case,
4335 that means you probably won't get heap block overrun detection (because
4336 there won't be redzones marked as unaddressable) and you definitely won't
4337 get any leak detection.
4339 The following client requests allow a custom allocator to be annotated so
4340 that it can be handled accurately by Valgrind.
4342 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4343 by a malloc()-like function. For Memcheck (an illustrative case), this
4346 - It records that the block has been allocated. This means any addresses
4347 within the block mentioned in error messages will be
4348 identified as belonging to the block. It also means that if the block
4349 isn't freed it will be detected by the leak checker.
4351 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4352 not set), or addressable and defined (if 'is_zeroed' is set). This
4353 controls how accesses to the block by the program are handled.
4355 'addr' is the start of the usable block (ie. after any
4356 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4357 can apply redzones -- these are blocks of padding at the start and end of
4358 each block. Adding redzones is recommended as it makes it much more likely
4359 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4360 zeroed (or filled with another predictable value), as is the case for
4363 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4364 heap block -- that will be used by the client program -- is allocated.
4365 It's best to put it at the outermost level of the allocator if possible;
4366 for example, if you have a function my_alloc() which calls
4367 internal_alloc(), and the client request is put inside internal_alloc(),
4368 stack traces relating to the heap block will contain entries for both
4369 my_alloc() and internal_alloc(), which is probably not what you want.
4371 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4372 custom blocks from within a heap block, B, that has been allocated with
4373 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4374 -- the custom blocks will take precedence.
4376 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4377 Memcheck, it does two things:
4379 - It records that the block has been deallocated. This assumes that the
4380 block was annotated as having been allocated via
4381 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4383 - It marks the block as being unaddressable.
4385 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4386 heap block is deallocated.
4388 In many cases, these two client requests will not be enough to get your
4389 allocator working well with Memcheck. More specifically, if your allocator
4390 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4391 will be necessary to mark the memory as addressable just before the zeroing
4392 occurs, otherwise you'll get a lot of invalid write errors. For example,
4393 you'll need to do this if your allocator recycles freed blocks, but it
4394 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4395 Alternatively, if your allocator reuses freed blocks for allocator-internal
4396 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4398 Really, what's happening is a blurring of the lines between the client
4399 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4400 memory should be considered unaddressable to the client program, but the
4401 allocator knows more than the rest of the client program and so may be able
4402 to safely access it. Extra client requests are necessary for Valgrind to
4403 understand the distinction between the allocator and the rest of the
4406 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4407 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4409 Ignored if addr == 0.
4411 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4412 {unsigned int __unused _qzz_res; \
4413 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4414 VG_USERREQ__MALLOCLIKE_BLOCK, \
4415 addr, sizeB, rzB, is_zeroed, 0); \
4418 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4419 Ignored if addr == 0.
4421 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4422 {unsigned int __unused _qzz_res; \
4423 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4424 VG_USERREQ__FREELIKE_BLOCK, \
4425 addr, rzB, 0, 0, 0); \
4428 /* Create a memory pool. */
4429 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4430 {unsigned int _qzz_res; \
4431 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4432 VG_USERREQ__CREATE_MEMPOOL, \
4433 pool, rzB, is_zeroed, 0, 0); \
4436 /* Destroy a memory pool. */
4437 #define VALGRIND_DESTROY_MEMPOOL(pool) \
4438 {unsigned int _qzz_res; \
4439 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4440 VG_USERREQ__DESTROY_MEMPOOL, \
4441 pool, 0, 0, 0, 0); \
4444 /* Associate a piece of memory with a memory pool. */
4445 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4446 {unsigned int _qzz_res; \
4447 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4448 VG_USERREQ__MEMPOOL_ALLOC, \
4449 pool, addr, size, 0, 0); \
4452 /* Disassociate a piece of memory from a memory pool. */
4453 #define VALGRIND_MEMPOOL_FREE(pool, addr) \
4454 {unsigned int _qzz_res; \
4455 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4456 VG_USERREQ__MEMPOOL_FREE, \
4457 pool, addr, 0, 0, 0); \
4460 /* Disassociate any pieces outside a particular range. */
4461 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4462 {unsigned int _qzz_res; \
4463 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4464 VG_USERREQ__MEMPOOL_TRIM, \
4465 pool, addr, size, 0, 0); \
4468 /* Resize and/or move a piece associated with a memory pool. */
4469 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4470 {unsigned int _qzz_res; \
4471 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4472 VG_USERREQ__MOVE_MEMPOOL, \
4473 poolA, poolB, 0, 0, 0); \
4476 /* Resize and/or move a piece associated with a memory pool. */
4477 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4478 {unsigned int _qzz_res; \
4479 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4480 VG_USERREQ__MEMPOOL_CHANGE, \
4481 pool, addrA, addrB, size, 0); \
4484 /* Return 1 if a mempool exists, else 0. */
4485 #define VALGRIND_MEMPOOL_EXISTS(pool) \
4487 ({unsigned int _qzz_res; \
4488 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4489 VG_USERREQ__MEMPOOL_EXISTS, \
4490 pool, 0, 0, 0, 0); \
4494 /* Mark a piece of memory as being a stack. Returns a stack id. */
4495 #define VALGRIND_STACK_REGISTER(start, end) \
4497 ({unsigned int _qzz_res; \
4498 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4499 VG_USERREQ__STACK_REGISTER, \
4500 start, end, 0, 0, 0); \
4504 /* Unmark the piece of memory associated with a stack id as being a
4506 #define VALGRIND_STACK_DEREGISTER(id) \
4507 {unsigned int _qzz_res; \
4508 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4509 VG_USERREQ__STACK_DEREGISTER, \
4513 /* Change the start and end address of the stack id. */
4514 #define VALGRIND_STACK_CHANGE(id, start, end) \
4515 {unsigned int _qzz_res; \
4516 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4517 VG_USERREQ__STACK_CHANGE, \
4518 id, start, end, 0, 0); \
4521 /* Load PDB debug info for Wine PE image_map. */
4522 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4523 {unsigned int _qzz_res; \
4524 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4525 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4526 fd, ptr, total_size, delta, 0); \
4530 #undef PLAT_x86_linux
4531 #undef PLAT_amd64_linux
4532 #undef PLAT_ppc32_linux
4533 #undef PLAT_ppc64_linux
4534 #undef PLAT_arm_linux
4535 #undef PLAT_ppc32_aix5
4536 #undef PLAT_ppc64_aix5
4538 #endif /* __VALGRIND_H */