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. */
77 /* ------------------------------------------------------------------ */
78 /* VERSION NUMBER OF VALGRIND */
79 /* ------------------------------------------------------------------ */
81 /* Specify Valgrind's version number, so that user code can
82 conditionally compile based on our version number. Note that these
83 were introduced at version 3.6 and so do not exist in version 3.5
84 or earlier. The recommended way to use them to check for "version
87 #if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
88 && (__VALGRIND_MAJOR__ > 3 \
89 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
91 #define __VALGRIND_MAJOR__ 3
92 #define __VALGRIND_MINOR__ 6
97 /* Nb: this file might be included in a file compiled with -ansi. So
98 we can't use C++ style "//" comments nor the "asm" keyword (instead
101 /* Derive some tags indicating what the target platform is. Note
102 that in this file we're using the compiler's CPP symbols for
103 identifying architectures, which are different to the ones we use
104 within the rest of Valgrind. Note, __powerpc__ is active for both
105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
106 latter (on Linux, that is).
108 Misc note: how to find out what's predefined in gcc by default:
109 gcc -Wp,-dM somefile.c
111 #undef PLAT_ppc64_aix5
112 #undef PLAT_ppc32_aix5
113 #undef PLAT_x86_darwin
114 #undef PLAT_amd64_darwin
115 #undef PLAT_x86_win32
116 #undef PLAT_x86_linux
117 #undef PLAT_amd64_linux
118 #undef PLAT_ppc32_linux
119 #undef PLAT_ppc64_linux
120 #undef PLAT_arm_linux
121 #undef PLAT_s390x_linux
124 #if defined(_AIX) && defined(__64BIT__)
125 # define PLAT_ppc64_aix5 1
126 #elif defined(_AIX) && !defined(__64BIT__)
127 # define PLAT_ppc32_aix5 1
128 #elif defined(__APPLE__) && defined(__i386__)
129 # define PLAT_x86_darwin 1
130 #elif defined(__APPLE__) && defined(__x86_64__)
131 # define PLAT_amd64_darwin 1
132 #elif defined(__MINGW32__) || defined(__CYGWIN32__) || defined(_WIN32) && defined(_M_IX86)
133 # define PLAT_x86_win32 1
134 #elif defined(__linux__) && defined(__i386__)
135 # define PLAT_x86_linux 1
136 #elif defined(__linux__) && defined(__x86_64__)
137 # define PLAT_amd64_linux 1
138 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
139 # define PLAT_ppc32_linux 1
140 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
141 # define PLAT_ppc64_linux 1
142 #elif defined(__linux__) && defined(__arm__)
143 # define PLAT_arm_linux 1
144 #elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
145 # define PLAT_s390x_linux 1
147 /* If we're not compiling for our target platform, don't generate
149 # if !defined(NVALGRIND)
155 /* ------------------------------------------------------------------ */
156 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
157 /* in here of use to end-users -- skip to the next section. */
158 /* ------------------------------------------------------------------ */
160 #if defined(NVALGRIND)
162 /* Define NVALGRIND to completely remove the Valgrind magic sequence
163 from the compiled code (analogous to NDEBUG's effects on
165 #define VALGRIND_DO_CLIENT_REQUEST( \
166 _zzq_rlval, _zzq_default, _zzq_request, \
167 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
169 (_zzq_rlval) = (_zzq_default); \
172 #else /* ! NVALGRIND */
174 /* The following defines the magic code sequences which the JITter
175 spots and handles magically. Don't look too closely at them as
176 they will rot your brain.
178 The assembly code sequences for all architectures is in this one
179 file. This is because this file must be stand-alone, and we don't
180 want to have multiple files.
182 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
183 value gets put in the return slot, so that everything works when
184 this is executed not under Valgrind. Args are passed in a memory
185 block, and so there's no intrinsic limit to the number that could
186 be passed, but it's currently five.
189 _zzq_rlval result lvalue
190 _zzq_default default value (result returned when running on real CPU)
191 _zzq_request request code
192 _zzq_arg1..5 request params
194 The other two macros are used to support function wrapping, and are
195 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
196 guest's NRADDR pseudo-register and whatever other information is
197 needed to safely run the call original from the wrapper: on
198 ppc64-linux, the R2 value at the divert point is also needed. This
199 information is abstracted into a user-visible type, OrigFn.
201 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
202 guest, but guarantees that the branch instruction will not be
203 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
204 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
205 complete inline asm, since it needs to be combined with more magic
206 inline asm stuff to be useful.
209 /* ------------------------- x86-{linux,darwin} ---------------- */
211 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
212 || (defined(PLAT_x86_win32) && defined(__GNUC__))
216 unsigned int nraddr; /* where's the code? */
220 #define __SPECIAL_INSTRUCTION_PREAMBLE \
221 "roll $3, %%edi ; roll $13, %%edi\n\t" \
222 "roll $29, %%edi ; roll $19, %%edi\n\t"
224 #define VALGRIND_DO_CLIENT_REQUEST( \
225 _zzq_rlval, _zzq_default, _zzq_request, \
226 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
227 { volatile unsigned int _zzq_args[6]; \
228 volatile unsigned int _zzq_result; \
229 _zzq_args[0] = (unsigned int)(_zzq_request); \
230 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
231 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
232 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
233 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
234 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
235 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
236 /* %EDX = client_request ( %EAX ) */ \
237 "xchgl %%ebx,%%ebx" \
238 : "=d" (_zzq_result) \
239 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
242 _zzq_rlval = _zzq_result; \
245 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
246 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
247 volatile unsigned int __addr; \
248 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
249 /* %EAX = guest_NRADDR */ \
250 "xchgl %%ecx,%%ecx" \
255 _zzq_orig->nraddr = __addr; \
258 #define VALGRIND_CALL_NOREDIR_EAX \
259 __SPECIAL_INSTRUCTION_PREAMBLE \
260 /* call-noredir *%EAX */ \
261 "xchgl %%edx,%%edx\n\t"
262 #endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
264 /* ------------------------- x86-Win32 ------------------------- */
266 #if defined(PLAT_x86_win32) && !defined(__GNUC__)
270 unsigned int nraddr; /* where's the code? */
274 #if defined(_MSC_VER)
276 #define __SPECIAL_INSTRUCTION_PREAMBLE \
277 __asm rol edi, 3 __asm rol edi, 13 \
278 __asm rol edi, 29 __asm rol edi, 19
280 #define VALGRIND_DO_CLIENT_REQUEST( \
281 _zzq_rlval, _zzq_default, _zzq_request, \
282 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
283 { volatile uintptr_t _zzq_args[6]; \
284 volatile unsigned int _zzq_result; \
285 _zzq_args[0] = (uintptr_t)(_zzq_request); \
286 _zzq_args[1] = (uintptr_t)(_zzq_arg1); \
287 _zzq_args[2] = (uintptr_t)(_zzq_arg2); \
288 _zzq_args[3] = (uintptr_t)(_zzq_arg3); \
289 _zzq_args[4] = (uintptr_t)(_zzq_arg4); \
290 _zzq_args[5] = (uintptr_t)(_zzq_arg5); \
291 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default \
292 __SPECIAL_INSTRUCTION_PREAMBLE \
293 /* %EDX = client_request ( %EAX ) */ \
295 __asm mov _zzq_result, edx \
297 _zzq_rlval = _zzq_result; \
300 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
301 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
302 volatile unsigned int __addr; \
303 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
304 /* %EAX = guest_NRADDR */ \
306 __asm mov __addr, eax \
308 _zzq_orig->nraddr = __addr; \
311 #define VALGRIND_CALL_NOREDIR_EAX ERROR
314 #error Unsupported compiler.
317 #endif /* PLAT_x86_win32 */
319 /* ------------------------ amd64-{linux,darwin} --------------- */
321 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
325 unsigned long long int nraddr; /* where's the code? */
329 #define __SPECIAL_INSTRUCTION_PREAMBLE \
330 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
331 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
333 #define VALGRIND_DO_CLIENT_REQUEST( \
334 _zzq_rlval, _zzq_default, _zzq_request, \
335 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
336 { volatile unsigned long long int _zzq_args[6]; \
337 volatile unsigned long long int _zzq_result; \
338 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
339 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
340 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
341 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
342 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
343 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
344 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
345 /* %RDX = client_request ( %RAX ) */ \
346 "xchgq %%rbx,%%rbx" \
347 : "=d" (_zzq_result) \
348 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
351 _zzq_rlval = _zzq_result; \
354 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
355 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
356 volatile unsigned long long int __addr; \
357 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
358 /* %RAX = guest_NRADDR */ \
359 "xchgq %%rcx,%%rcx" \
364 _zzq_orig->nraddr = __addr; \
367 #define VALGRIND_CALL_NOREDIR_RAX \
368 __SPECIAL_INSTRUCTION_PREAMBLE \
369 /* call-noredir *%RAX */ \
370 "xchgq %%rdx,%%rdx\n\t"
371 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
373 /* ------------------------ ppc32-linux ------------------------ */
375 #if defined(PLAT_ppc32_linux)
379 unsigned int nraddr; /* where's the code? */
383 #define __SPECIAL_INSTRUCTION_PREAMBLE \
384 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
385 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\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 int _zzq_args[6]; \
392 unsigned int _zzq_result; \
393 unsigned int* _zzq_ptr; \
394 _zzq_args[0] = (unsigned int)(_zzq_request); \
395 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
396 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
397 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
398 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
399 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
400 _zzq_ptr = _zzq_args; \
401 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
402 "mr 4,%2\n\t" /*ptr*/ \
403 __SPECIAL_INSTRUCTION_PREAMBLE \
404 /* %R3 = client_request ( %R4 ) */ \
406 "mr %0,3" /*result*/ \
407 : "=b" (_zzq_result) \
408 : "b" (_zzq_default), "b" (_zzq_ptr) \
409 : "cc", "memory", "r3", "r4"); \
410 _zzq_rlval = _zzq_result; \
413 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
414 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
415 unsigned int __addr; \
416 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
417 /* %R3 = guest_NRADDR */ \
422 : "cc", "memory", "r3" \
424 _zzq_orig->nraddr = __addr; \
427 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
428 __SPECIAL_INSTRUCTION_PREAMBLE \
429 /* branch-and-link-to-noredir *%R11 */ \
431 #endif /* PLAT_ppc32_linux */
433 /* ------------------------ ppc64-linux ------------------------ */
435 #if defined(PLAT_ppc64_linux)
439 unsigned long long int nraddr; /* where's the code? */
440 unsigned long long int r2; /* what tocptr do we need? */
444 #define __SPECIAL_INSTRUCTION_PREAMBLE \
445 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
446 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
448 #define VALGRIND_DO_CLIENT_REQUEST( \
449 _zzq_rlval, _zzq_default, _zzq_request, \
450 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
452 { unsigned long long int _zzq_args[6]; \
453 register unsigned long long int _zzq_result __asm__("r3"); \
454 register unsigned long long int* _zzq_ptr __asm__("r4"); \
455 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
456 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
457 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
458 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
459 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
460 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
461 _zzq_ptr = _zzq_args; \
462 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
463 /* %R3 = client_request ( %R4 ) */ \
465 : "=r" (_zzq_result) \
466 : "0" (_zzq_default), "r" (_zzq_ptr) \
468 _zzq_rlval = _zzq_result; \
471 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
472 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
473 register unsigned long long int __addr __asm__("r3"); \
474 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
475 /* %R3 = guest_NRADDR */ \
481 _zzq_orig->nraddr = __addr; \
482 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
483 /* %R3 = guest_NRADDR_GPR2 */ \
489 _zzq_orig->r2 = __addr; \
492 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
493 __SPECIAL_INSTRUCTION_PREAMBLE \
494 /* branch-and-link-to-noredir *%R11 */ \
497 #endif /* PLAT_ppc64_linux */
499 /* ------------------------- arm-linux ------------------------- */
501 #if defined(PLAT_arm_linux)
505 unsigned int nraddr; /* where's the code? */
509 #define __SPECIAL_INSTRUCTION_PREAMBLE \
510 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
511 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
513 #define VALGRIND_DO_CLIENT_REQUEST( \
514 _zzq_rlval, _zzq_default, _zzq_request, \
515 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
517 { volatile unsigned int _zzq_args[6]; \
518 volatile unsigned int _zzq_result; \
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 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
526 "mov r4, %2\n\t" /*ptr*/ \
527 __SPECIAL_INSTRUCTION_PREAMBLE \
528 /* R3 = client_request ( R4 ) */ \
529 "orr r10, r10, r10\n\t" \
530 "mov %0, r3" /*result*/ \
531 : "=r" (_zzq_result) \
532 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
533 : "cc","memory", "r3", "r4"); \
534 _zzq_rlval = _zzq_result; \
537 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
538 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
539 unsigned int __addr; \
540 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
541 /* R3 = guest_NRADDR */ \
542 "orr r11, r11, r11\n\t" \
546 : "cc", "memory", "r3" \
548 _zzq_orig->nraddr = __addr; \
551 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
552 __SPECIAL_INSTRUCTION_PREAMBLE \
553 /* branch-and-link-to-noredir *%R4 */ \
554 "orr r12, r12, r12\n\t"
556 #endif /* PLAT_arm_linux */
558 /* ------------------------ ppc32-aix5 ------------------------- */
560 #if defined(PLAT_ppc32_aix5)
564 unsigned int nraddr; /* where's the code? */
565 unsigned int r2; /* what tocptr do we need? */
569 #define __SPECIAL_INSTRUCTION_PREAMBLE \
570 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
571 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
573 #define VALGRIND_DO_CLIENT_REQUEST( \
574 _zzq_rlval, _zzq_default, _zzq_request, \
575 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
577 { unsigned int _zzq_args[7]; \
578 register unsigned int _zzq_result; \
579 register unsigned int* _zzq_ptr; \
580 _zzq_args[0] = (unsigned int)(_zzq_request); \
581 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
582 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
583 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
584 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
585 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
586 _zzq_args[6] = (unsigned int)(_zzq_default); \
587 _zzq_ptr = _zzq_args; \
588 __asm__ volatile("mr 4,%1\n\t" \
590 __SPECIAL_INSTRUCTION_PREAMBLE \
591 /* %R3 = client_request ( %R4 ) */ \
594 : "=b" (_zzq_result) \
596 : "r3", "r4", "cc", "memory"); \
597 _zzq_rlval = _zzq_result; \
600 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
601 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
602 register unsigned int __addr; \
603 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
604 /* %R3 = guest_NRADDR */ \
609 : "r3", "cc", "memory" \
611 _zzq_orig->nraddr = __addr; \
612 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
613 /* %R3 = guest_NRADDR_GPR2 */ \
618 : "r3", "cc", "memory" \
620 _zzq_orig->r2 = __addr; \
623 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
624 __SPECIAL_INSTRUCTION_PREAMBLE \
625 /* branch-and-link-to-noredir *%R11 */ \
628 #endif /* PLAT_ppc32_aix5 */
630 /* ------------------------ ppc64-aix5 ------------------------- */
632 #if defined(PLAT_ppc64_aix5)
636 unsigned long long int nraddr; /* where's the code? */
637 unsigned long long int r2; /* what tocptr do we need? */
641 #define __SPECIAL_INSTRUCTION_PREAMBLE \
642 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
643 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
645 #define VALGRIND_DO_CLIENT_REQUEST( \
646 _zzq_rlval, _zzq_default, _zzq_request, \
647 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
649 { unsigned long long int _zzq_args[7]; \
650 register unsigned long long int _zzq_result; \
651 register unsigned long long int* _zzq_ptr; \
652 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
653 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
654 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
655 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
656 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
657 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
658 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
659 _zzq_ptr = _zzq_args; \
660 __asm__ volatile("mr 4,%1\n\t" \
662 __SPECIAL_INSTRUCTION_PREAMBLE \
663 /* %R3 = client_request ( %R4 ) */ \
666 : "=b" (_zzq_result) \
668 : "r3", "r4", "cc", "memory"); \
669 _zzq_rlval = _zzq_result; \
672 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
673 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
674 register unsigned long long int __addr; \
675 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
676 /* %R3 = guest_NRADDR */ \
681 : "r3", "cc", "memory" \
683 _zzq_orig->nraddr = __addr; \
684 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
685 /* %R3 = guest_NRADDR_GPR2 */ \
690 : "r3", "cc", "memory" \
692 _zzq_orig->r2 = __addr; \
695 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
696 __SPECIAL_INSTRUCTION_PREAMBLE \
697 /* branch-and-link-to-noredir *%R11 */ \
700 #endif /* PLAT_ppc64_aix5 */
702 /* ------------------------ s390x-linux ------------------------ */
704 #if defined(PLAT_s390x_linux)
708 unsigned long long int nraddr; /* where's the code? */
712 /* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
713 * code. This detection is implemented in platform specific toIR.c
714 * (e.g. VEX/priv/guest_s390_decoder.c).
716 #define __SPECIAL_INSTRUCTION_PREAMBLE \
722 #define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
723 #define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
724 #define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
726 #define VALGRIND_DO_CLIENT_REQUEST( \
727 _zzq_rlval, _zzq_default, _zzq_request, \
728 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
729 { volatile unsigned long long int _zzq_args[6]; \
730 volatile unsigned long long int _zzq_result; \
731 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
732 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
733 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
734 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
735 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
736 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
737 __asm__ volatile(/* r2 = args */ \
741 __SPECIAL_INSTRUCTION_PREAMBLE \
742 __CLIENT_REQUEST_CODE \
745 : "=d" (_zzq_result) \
746 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
747 : "cc", "2", "3", "memory" \
749 _zzq_rlval = _zzq_result; \
752 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
753 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
754 volatile unsigned long long int __addr; \
755 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
756 __GET_NR_CONTEXT_CODE \
760 : "cc", "3", "memory" \
762 _zzq_orig->nraddr = __addr; \
765 #define VALGRIND_CALL_NOREDIR_R1 \
766 __SPECIAL_INSTRUCTION_PREAMBLE \
769 #endif /* PLAT_s390x_linux */
771 /* Insert assembly code for other platforms here... */
773 #endif /* NVALGRIND */
776 /* ------------------------------------------------------------------ */
777 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
778 /* ugly. It's the least-worst tradeoff I can think of. */
779 /* ------------------------------------------------------------------ */
781 /* This section defines magic (a.k.a appalling-hack) macros for doing
782 guaranteed-no-redirection macros, so as to get from function
783 wrappers to the functions they are wrapping. The whole point is to
784 construct standard call sequences, but to do the call itself with a
785 special no-redirect call pseudo-instruction that the JIT
786 understands and handles specially. This section is long and
787 repetitious, and I can't see a way to make it shorter.
789 The naming scheme is as follows:
791 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
793 'W' stands for "word" and 'v' for "void". Hence there are
794 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
795 and for each, the possibility of returning a word-typed result, or
799 /* Use these to write the name of your wrapper. NOTE: duplicates
800 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
802 /* Use an extra level of macroisation so as to ensure the soname/fnname
803 args are fully macro-expanded before pasting them together. */
804 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
806 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
807 VG_CONCAT4(_vgwZU_,soname,_,fnname)
809 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
810 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
812 /* Use this macro from within a wrapper function to collect the
813 context (address and possibly other info) of the original function.
814 Once you have that you can then use it in one of the CALL_FN_
815 macros. The type of the argument _lval is OrigFn. */
816 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
818 /* Derivatives of the main macros below, for calling functions
821 #define CALL_FN_v_v(fnptr) \
822 do { volatile unsigned long _junk; \
823 CALL_FN_W_v(_junk,fnptr); } while (0)
825 #define CALL_FN_v_W(fnptr, arg1) \
826 do { volatile unsigned long _junk; \
827 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
829 #define CALL_FN_v_WW(fnptr, arg1,arg2) \
830 do { volatile unsigned long _junk; \
831 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
833 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
834 do { volatile unsigned long _junk; \
835 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
837 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
838 do { volatile unsigned long _junk; \
839 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
841 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
842 do { volatile unsigned long _junk; \
843 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
845 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
846 do { volatile unsigned long _junk; \
847 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
849 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
850 do { volatile unsigned long _junk; \
851 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
853 /* ------------------------- x86-{linux,darwin} ---------------- */
855 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
857 /* These regs are trashed by the hidden call. No need to mention eax
858 as gcc can already see that, plus causes gcc to bomb. */
859 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
861 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
864 #define CALL_FN_W_v(lval, orig) \
866 volatile OrigFn _orig = (orig); \
867 volatile unsigned long _argvec[1]; \
868 volatile unsigned long _res; \
869 _argvec[0] = (unsigned long)_orig.nraddr; \
871 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
872 VALGRIND_CALL_NOREDIR_EAX \
873 : /*out*/ "=a" (_res) \
874 : /*in*/ "a" (&_argvec[0]) \
875 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
877 lval = (__typeof__(lval)) _res; \
880 #define CALL_FN_W_W(lval, orig, arg1) \
882 volatile OrigFn _orig = (orig); \
883 volatile unsigned long _argvec[2]; \
884 volatile unsigned long _res; \
885 _argvec[0] = (unsigned long)_orig.nraddr; \
886 _argvec[1] = (unsigned long)(arg1); \
888 "subl $12, %%esp\n\t" \
889 "pushl 4(%%eax)\n\t" \
890 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
891 VALGRIND_CALL_NOREDIR_EAX \
892 "addl $16, %%esp\n" \
893 : /*out*/ "=a" (_res) \
894 : /*in*/ "a" (&_argvec[0]) \
895 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
897 lval = (__typeof__(lval)) _res; \
900 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
902 volatile OrigFn _orig = (orig); \
903 volatile unsigned long _argvec[3]; \
904 volatile unsigned long _res; \
905 _argvec[0] = (unsigned long)_orig.nraddr; \
906 _argvec[1] = (unsigned long)(arg1); \
907 _argvec[2] = (unsigned long)(arg2); \
909 "subl $8, %%esp\n\t" \
910 "pushl 8(%%eax)\n\t" \
911 "pushl 4(%%eax)\n\t" \
912 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
913 VALGRIND_CALL_NOREDIR_EAX \
914 "addl $16, %%esp\n" \
915 : /*out*/ "=a" (_res) \
916 : /*in*/ "a" (&_argvec[0]) \
917 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
919 lval = (__typeof__(lval)) _res; \
922 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
924 volatile OrigFn _orig = (orig); \
925 volatile unsigned long _argvec[4]; \
926 volatile unsigned long _res; \
927 _argvec[0] = (unsigned long)_orig.nraddr; \
928 _argvec[1] = (unsigned long)(arg1); \
929 _argvec[2] = (unsigned long)(arg2); \
930 _argvec[3] = (unsigned long)(arg3); \
932 "subl $4, %%esp\n\t" \
933 "pushl 12(%%eax)\n\t" \
934 "pushl 8(%%eax)\n\t" \
935 "pushl 4(%%eax)\n\t" \
936 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
937 VALGRIND_CALL_NOREDIR_EAX \
938 "addl $16, %%esp\n" \
939 : /*out*/ "=a" (_res) \
940 : /*in*/ "a" (&_argvec[0]) \
941 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
943 lval = (__typeof__(lval)) _res; \
946 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
948 volatile OrigFn _orig = (orig); \
949 volatile unsigned long _argvec[5]; \
950 volatile unsigned long _res; \
951 _argvec[0] = (unsigned long)_orig.nraddr; \
952 _argvec[1] = (unsigned long)(arg1); \
953 _argvec[2] = (unsigned long)(arg2); \
954 _argvec[3] = (unsigned long)(arg3); \
955 _argvec[4] = (unsigned long)(arg4); \
957 "pushl 16(%%eax)\n\t" \
958 "pushl 12(%%eax)\n\t" \
959 "pushl 8(%%eax)\n\t" \
960 "pushl 4(%%eax)\n\t" \
961 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
962 VALGRIND_CALL_NOREDIR_EAX \
963 "addl $16, %%esp\n" \
964 : /*out*/ "=a" (_res) \
965 : /*in*/ "a" (&_argvec[0]) \
966 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
968 lval = (__typeof__(lval)) _res; \
971 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
973 volatile OrigFn _orig = (orig); \
974 volatile unsigned long _argvec[6]; \
975 volatile unsigned long _res; \
976 _argvec[0] = (unsigned long)_orig.nraddr; \
977 _argvec[1] = (unsigned long)(arg1); \
978 _argvec[2] = (unsigned long)(arg2); \
979 _argvec[3] = (unsigned long)(arg3); \
980 _argvec[4] = (unsigned long)(arg4); \
981 _argvec[5] = (unsigned long)(arg5); \
983 "subl $12, %%esp\n\t" \
984 "pushl 20(%%eax)\n\t" \
985 "pushl 16(%%eax)\n\t" \
986 "pushl 12(%%eax)\n\t" \
987 "pushl 8(%%eax)\n\t" \
988 "pushl 4(%%eax)\n\t" \
989 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
990 VALGRIND_CALL_NOREDIR_EAX \
991 "addl $32, %%esp\n" \
992 : /*out*/ "=a" (_res) \
993 : /*in*/ "a" (&_argvec[0]) \
994 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
996 lval = (__typeof__(lval)) _res; \
999 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1001 volatile OrigFn _orig = (orig); \
1002 volatile unsigned long _argvec[7]; \
1003 volatile unsigned long _res; \
1004 _argvec[0] = (unsigned long)_orig.nraddr; \
1005 _argvec[1] = (unsigned long)(arg1); \
1006 _argvec[2] = (unsigned long)(arg2); \
1007 _argvec[3] = (unsigned long)(arg3); \
1008 _argvec[4] = (unsigned long)(arg4); \
1009 _argvec[5] = (unsigned long)(arg5); \
1010 _argvec[6] = (unsigned long)(arg6); \
1012 "subl $8, %%esp\n\t" \
1013 "pushl 24(%%eax)\n\t" \
1014 "pushl 20(%%eax)\n\t" \
1015 "pushl 16(%%eax)\n\t" \
1016 "pushl 12(%%eax)\n\t" \
1017 "pushl 8(%%eax)\n\t" \
1018 "pushl 4(%%eax)\n\t" \
1019 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1020 VALGRIND_CALL_NOREDIR_EAX \
1021 "addl $32, %%esp\n" \
1022 : /*out*/ "=a" (_res) \
1023 : /*in*/ "a" (&_argvec[0]) \
1024 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1026 lval = (__typeof__(lval)) _res; \
1029 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1032 volatile OrigFn _orig = (orig); \
1033 volatile unsigned long _argvec[8]; \
1034 volatile unsigned long _res; \
1035 _argvec[0] = (unsigned long)_orig.nraddr; \
1036 _argvec[1] = (unsigned long)(arg1); \
1037 _argvec[2] = (unsigned long)(arg2); \
1038 _argvec[3] = (unsigned long)(arg3); \
1039 _argvec[4] = (unsigned long)(arg4); \
1040 _argvec[5] = (unsigned long)(arg5); \
1041 _argvec[6] = (unsigned long)(arg6); \
1042 _argvec[7] = (unsigned long)(arg7); \
1044 "subl $4, %%esp\n\t" \
1045 "pushl 28(%%eax)\n\t" \
1046 "pushl 24(%%eax)\n\t" \
1047 "pushl 20(%%eax)\n\t" \
1048 "pushl 16(%%eax)\n\t" \
1049 "pushl 12(%%eax)\n\t" \
1050 "pushl 8(%%eax)\n\t" \
1051 "pushl 4(%%eax)\n\t" \
1052 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1053 VALGRIND_CALL_NOREDIR_EAX \
1054 "addl $32, %%esp\n" \
1055 : /*out*/ "=a" (_res) \
1056 : /*in*/ "a" (&_argvec[0]) \
1057 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1059 lval = (__typeof__(lval)) _res; \
1062 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1065 volatile OrigFn _orig = (orig); \
1066 volatile unsigned long _argvec[9]; \
1067 volatile unsigned long _res; \
1068 _argvec[0] = (unsigned long)_orig.nraddr; \
1069 _argvec[1] = (unsigned long)(arg1); \
1070 _argvec[2] = (unsigned long)(arg2); \
1071 _argvec[3] = (unsigned long)(arg3); \
1072 _argvec[4] = (unsigned long)(arg4); \
1073 _argvec[5] = (unsigned long)(arg5); \
1074 _argvec[6] = (unsigned long)(arg6); \
1075 _argvec[7] = (unsigned long)(arg7); \
1076 _argvec[8] = (unsigned long)(arg8); \
1078 "pushl 32(%%eax)\n\t" \
1079 "pushl 28(%%eax)\n\t" \
1080 "pushl 24(%%eax)\n\t" \
1081 "pushl 20(%%eax)\n\t" \
1082 "pushl 16(%%eax)\n\t" \
1083 "pushl 12(%%eax)\n\t" \
1084 "pushl 8(%%eax)\n\t" \
1085 "pushl 4(%%eax)\n\t" \
1086 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1087 VALGRIND_CALL_NOREDIR_EAX \
1088 "addl $32, %%esp\n" \
1089 : /*out*/ "=a" (_res) \
1090 : /*in*/ "a" (&_argvec[0]) \
1091 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1093 lval = (__typeof__(lval)) _res; \
1096 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1099 volatile OrigFn _orig = (orig); \
1100 volatile unsigned long _argvec[10]; \
1101 volatile unsigned long _res; \
1102 _argvec[0] = (unsigned long)_orig.nraddr; \
1103 _argvec[1] = (unsigned long)(arg1); \
1104 _argvec[2] = (unsigned long)(arg2); \
1105 _argvec[3] = (unsigned long)(arg3); \
1106 _argvec[4] = (unsigned long)(arg4); \
1107 _argvec[5] = (unsigned long)(arg5); \
1108 _argvec[6] = (unsigned long)(arg6); \
1109 _argvec[7] = (unsigned long)(arg7); \
1110 _argvec[8] = (unsigned long)(arg8); \
1111 _argvec[9] = (unsigned long)(arg9); \
1113 "subl $12, %%esp\n\t" \
1114 "pushl 36(%%eax)\n\t" \
1115 "pushl 32(%%eax)\n\t" \
1116 "pushl 28(%%eax)\n\t" \
1117 "pushl 24(%%eax)\n\t" \
1118 "pushl 20(%%eax)\n\t" \
1119 "pushl 16(%%eax)\n\t" \
1120 "pushl 12(%%eax)\n\t" \
1121 "pushl 8(%%eax)\n\t" \
1122 "pushl 4(%%eax)\n\t" \
1123 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1124 VALGRIND_CALL_NOREDIR_EAX \
1125 "addl $48, %%esp\n" \
1126 : /*out*/ "=a" (_res) \
1127 : /*in*/ "a" (&_argvec[0]) \
1128 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1130 lval = (__typeof__(lval)) _res; \
1133 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1134 arg7,arg8,arg9,arg10) \
1136 volatile OrigFn _orig = (orig); \
1137 volatile unsigned long _argvec[11]; \
1138 volatile unsigned long _res; \
1139 _argvec[0] = (unsigned long)_orig.nraddr; \
1140 _argvec[1] = (unsigned long)(arg1); \
1141 _argvec[2] = (unsigned long)(arg2); \
1142 _argvec[3] = (unsigned long)(arg3); \
1143 _argvec[4] = (unsigned long)(arg4); \
1144 _argvec[5] = (unsigned long)(arg5); \
1145 _argvec[6] = (unsigned long)(arg6); \
1146 _argvec[7] = (unsigned long)(arg7); \
1147 _argvec[8] = (unsigned long)(arg8); \
1148 _argvec[9] = (unsigned long)(arg9); \
1149 _argvec[10] = (unsigned long)(arg10); \
1151 "subl $8, %%esp\n\t" \
1152 "pushl 40(%%eax)\n\t" \
1153 "pushl 36(%%eax)\n\t" \
1154 "pushl 32(%%eax)\n\t" \
1155 "pushl 28(%%eax)\n\t" \
1156 "pushl 24(%%eax)\n\t" \
1157 "pushl 20(%%eax)\n\t" \
1158 "pushl 16(%%eax)\n\t" \
1159 "pushl 12(%%eax)\n\t" \
1160 "pushl 8(%%eax)\n\t" \
1161 "pushl 4(%%eax)\n\t" \
1162 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1163 VALGRIND_CALL_NOREDIR_EAX \
1164 "addl $48, %%esp\n" \
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_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1173 arg6,arg7,arg8,arg9,arg10, \
1176 volatile OrigFn _orig = (orig); \
1177 volatile unsigned long _argvec[12]; \
1178 volatile unsigned long _res; \
1179 _argvec[0] = (unsigned long)_orig.nraddr; \
1180 _argvec[1] = (unsigned long)(arg1); \
1181 _argvec[2] = (unsigned long)(arg2); \
1182 _argvec[3] = (unsigned long)(arg3); \
1183 _argvec[4] = (unsigned long)(arg4); \
1184 _argvec[5] = (unsigned long)(arg5); \
1185 _argvec[6] = (unsigned long)(arg6); \
1186 _argvec[7] = (unsigned long)(arg7); \
1187 _argvec[8] = (unsigned long)(arg8); \
1188 _argvec[9] = (unsigned long)(arg9); \
1189 _argvec[10] = (unsigned long)(arg10); \
1190 _argvec[11] = (unsigned long)(arg11); \
1192 "subl $4, %%esp\n\t" \
1193 "pushl 44(%%eax)\n\t" \
1194 "pushl 40(%%eax)\n\t" \
1195 "pushl 36(%%eax)\n\t" \
1196 "pushl 32(%%eax)\n\t" \
1197 "pushl 28(%%eax)\n\t" \
1198 "pushl 24(%%eax)\n\t" \
1199 "pushl 20(%%eax)\n\t" \
1200 "pushl 16(%%eax)\n\t" \
1201 "pushl 12(%%eax)\n\t" \
1202 "pushl 8(%%eax)\n\t" \
1203 "pushl 4(%%eax)\n\t" \
1204 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1205 VALGRIND_CALL_NOREDIR_EAX \
1206 "addl $48, %%esp\n" \
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_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1215 arg6,arg7,arg8,arg9,arg10, \
1218 volatile OrigFn _orig = (orig); \
1219 volatile unsigned long _argvec[13]; \
1220 volatile unsigned long _res; \
1221 _argvec[0] = (unsigned long)_orig.nraddr; \
1222 _argvec[1] = (unsigned long)(arg1); \
1223 _argvec[2] = (unsigned long)(arg2); \
1224 _argvec[3] = (unsigned long)(arg3); \
1225 _argvec[4] = (unsigned long)(arg4); \
1226 _argvec[5] = (unsigned long)(arg5); \
1227 _argvec[6] = (unsigned long)(arg6); \
1228 _argvec[7] = (unsigned long)(arg7); \
1229 _argvec[8] = (unsigned long)(arg8); \
1230 _argvec[9] = (unsigned long)(arg9); \
1231 _argvec[10] = (unsigned long)(arg10); \
1232 _argvec[11] = (unsigned long)(arg11); \
1233 _argvec[12] = (unsigned long)(arg12); \
1235 "pushl 48(%%eax)\n\t" \
1236 "pushl 44(%%eax)\n\t" \
1237 "pushl 40(%%eax)\n\t" \
1238 "pushl 36(%%eax)\n\t" \
1239 "pushl 32(%%eax)\n\t" \
1240 "pushl 28(%%eax)\n\t" \
1241 "pushl 24(%%eax)\n\t" \
1242 "pushl 20(%%eax)\n\t" \
1243 "pushl 16(%%eax)\n\t" \
1244 "pushl 12(%%eax)\n\t" \
1245 "pushl 8(%%eax)\n\t" \
1246 "pushl 4(%%eax)\n\t" \
1247 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1248 VALGRIND_CALL_NOREDIR_EAX \
1249 "addl $48, %%esp\n" \
1250 : /*out*/ "=a" (_res) \
1251 : /*in*/ "a" (&_argvec[0]) \
1252 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1254 lval = (__typeof__(lval)) _res; \
1257 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
1259 /* ------------------------ amd64-{linux,darwin} --------------- */
1261 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
1263 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1265 /* These regs are trashed by the hidden call. */
1266 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1267 "rdi", "r8", "r9", "r10", "r11"
1269 /* This is all pretty complex. It's so as to make stack unwinding
1270 work reliably. See bug 243270. The basic problem is the sub and
1271 add of 128 of %rsp in all of the following macros. If gcc believes
1272 the CFA is in %rsp, then unwinding may fail, because what's at the
1273 CFA is not what gcc "expected" when it constructs the CFIs for the
1274 places where the macros are instantiated.
1276 But we can't just add a CFI annotation to increase the CFA offset
1277 by 128, to match the sub of 128 from %rsp, because we don't know
1278 whether gcc has chosen %rsp as the CFA at that point, or whether it
1279 has chosen some other register (eg, %rbp). In the latter case,
1280 adding a CFI annotation to change the CFA offset is simply wrong.
1282 So the solution is to get hold of the CFA using
1283 __builtin_dwarf_cfa(), put it in a known register, and add a
1284 CFI annotation to say what the register is. We choose %rbp for
1285 this (perhaps perversely), because:
1287 (1) %rbp is already subject to unwinding. If a new register was
1288 chosen then the unwinder would have to unwind it in all stack
1289 traces, which is expensive, and
1291 (2) %rbp is already subject to precise exception updates in the
1292 JIT. If a new register was chosen, we'd have to have precise
1293 exceptions for it too, which reduces performance of the
1296 However .. one extra complication. We can't just whack the result
1297 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
1298 list of trashed registers at the end of the inline assembly
1299 fragments; gcc won't allow %rbp to appear in that list. Hence
1300 instead we need to stash %rbp in %r15 for the duration of the asm,
1301 and say that %r15 is trashed instead. gcc seems happy to go with
1304 Oh .. and this all needs to be conditionalised so that it is
1305 unchanged from before this commit, when compiled with older gccs
1306 that don't support __builtin_dwarf_cfa. Furthermore, since
1307 this header file is freestanding, it has to be independent of
1308 config.h, and so the following conditionalisation cannot depend on
1309 configure time checks.
1311 Although it's not clear from
1312 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1313 this expression excludes Darwin.
1314 .cfi directives in Darwin assembly appear to be completely
1315 different and I haven't investigated how they work.
1317 For even more entertainment value, note we have to use the
1318 completely undocumented __builtin_dwarf_cfa(), which appears to
1319 really compute the CFA, whereas __builtin_frame_address(0) claims
1320 to but actually doesn't. See
1321 https://bugs.kde.org/show_bug.cgi?id=243270#c47
1323 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
1324 # define __FRAME_POINTER \
1325 ,"r"(__builtin_dwarf_cfa())
1326 # define VALGRIND_CFI_PROLOGUE \
1327 "movq %%rbp, %%r15\n\t" \
1328 "movq %2, %%rbp\n\t" \
1329 ".cfi_remember_state\n\t" \
1330 ".cfi_def_cfa rbp, 0\n\t"
1331 # define VALGRIND_CFI_EPILOGUE \
1332 "movq %%r15, %%rbp\n\t" \
1333 ".cfi_restore_state\n\t"
1335 # define __FRAME_POINTER
1336 # define VALGRIND_CFI_PROLOGUE
1337 # define VALGRIND_CFI_EPILOGUE
1341 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1344 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1345 macros. In order not to trash the stack redzone, we need to drop
1346 %rsp by 128 before the hidden call, and restore afterwards. The
1347 nastyness is that it is only by luck that the stack still appears
1348 to be unwindable during the hidden call - since then the behaviour
1349 of any routine using this macro does not match what the CFI data
1352 Why is this important? Imagine that a wrapper has a stack
1353 allocated local, and passes to the hidden call, a pointer to it.
1354 Because gcc does not know about the hidden call, it may allocate
1355 that local in the redzone. Unfortunately the hidden call may then
1356 trash it before it comes to use it. So we must step clear of the
1357 redzone, for the duration of the hidden call, to make it safe.
1359 Probably the same problem afflicts the other redzone-style ABIs too
1360 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1361 self describing (none of this CFI nonsense) so at least messing
1362 with the stack pointer doesn't give a danger of non-unwindable
1365 #define CALL_FN_W_v(lval, orig) \
1367 volatile OrigFn _orig = (orig); \
1368 volatile unsigned long _argvec[1]; \
1369 volatile unsigned long _res; \
1370 _argvec[0] = (unsigned long)_orig.nraddr; \
1372 VALGRIND_CFI_PROLOGUE \
1373 "subq $128,%%rsp\n\t" \
1374 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1375 VALGRIND_CALL_NOREDIR_RAX \
1376 "addq $128,%%rsp\n\t" \
1377 VALGRIND_CFI_EPILOGUE \
1378 : /*out*/ "=a" (_res) \
1379 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1380 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1382 lval = (__typeof__(lval)) _res; \
1385 #define CALL_FN_W_W(lval, orig, arg1) \
1387 volatile OrigFn _orig = (orig); \
1388 volatile unsigned long _argvec[2]; \
1389 volatile unsigned long _res; \
1390 _argvec[0] = (unsigned long)_orig.nraddr; \
1391 _argvec[1] = (unsigned long)(arg1); \
1393 VALGRIND_CFI_PROLOGUE \
1394 "subq $128,%%rsp\n\t" \
1395 "movq 8(%%rax), %%rdi\n\t" \
1396 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1397 VALGRIND_CALL_NOREDIR_RAX \
1398 "addq $128,%%rsp\n\t" \
1399 VALGRIND_CFI_EPILOGUE \
1400 : /*out*/ "=a" (_res) \
1401 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1402 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1404 lval = (__typeof__(lval)) _res; \
1407 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1409 volatile OrigFn _orig = (orig); \
1410 volatile unsigned long _argvec[3]; \
1411 volatile unsigned long _res; \
1412 _argvec[0] = (unsigned long)_orig.nraddr; \
1413 _argvec[1] = (unsigned long)(arg1); \
1414 _argvec[2] = (unsigned long)(arg2); \
1416 VALGRIND_CFI_PROLOGUE \
1417 "subq $128,%%rsp\n\t" \
1418 "movq 16(%%rax), %%rsi\n\t" \
1419 "movq 8(%%rax), %%rdi\n\t" \
1420 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1421 VALGRIND_CALL_NOREDIR_RAX \
1422 "addq $128,%%rsp\n\t" \
1423 VALGRIND_CFI_EPILOGUE \
1424 : /*out*/ "=a" (_res) \
1425 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1426 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1428 lval = (__typeof__(lval)) _res; \
1431 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1433 volatile OrigFn _orig = (orig); \
1434 volatile unsigned long _argvec[4]; \
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); \
1441 VALGRIND_CFI_PROLOGUE \
1442 "subq $128,%%rsp\n\t" \
1443 "movq 24(%%rax), %%rdx\n\t" \
1444 "movq 16(%%rax), %%rsi\n\t" \
1445 "movq 8(%%rax), %%rdi\n\t" \
1446 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1447 VALGRIND_CALL_NOREDIR_RAX \
1448 "addq $128,%%rsp\n\t" \
1449 VALGRIND_CFI_EPILOGUE \
1450 : /*out*/ "=a" (_res) \
1451 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1452 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1454 lval = (__typeof__(lval)) _res; \
1457 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1459 volatile OrigFn _orig = (orig); \
1460 volatile unsigned long _argvec[5]; \
1461 volatile unsigned long _res; \
1462 _argvec[0] = (unsigned long)_orig.nraddr; \
1463 _argvec[1] = (unsigned long)(arg1); \
1464 _argvec[2] = (unsigned long)(arg2); \
1465 _argvec[3] = (unsigned long)(arg3); \
1466 _argvec[4] = (unsigned long)(arg4); \
1468 VALGRIND_CFI_PROLOGUE \
1469 "subq $128,%%rsp\n\t" \
1470 "movq 32(%%rax), %%rcx\n\t" \
1471 "movq 24(%%rax), %%rdx\n\t" \
1472 "movq 16(%%rax), %%rsi\n\t" \
1473 "movq 8(%%rax), %%rdi\n\t" \
1474 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1475 VALGRIND_CALL_NOREDIR_RAX \
1476 "addq $128,%%rsp\n\t" \
1477 VALGRIND_CFI_EPILOGUE \
1478 : /*out*/ "=a" (_res) \
1479 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1480 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1482 lval = (__typeof__(lval)) _res; \
1485 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1487 volatile OrigFn _orig = (orig); \
1488 volatile unsigned long _argvec[6]; \
1489 volatile unsigned long _res; \
1490 _argvec[0] = (unsigned long)_orig.nraddr; \
1491 _argvec[1] = (unsigned long)(arg1); \
1492 _argvec[2] = (unsigned long)(arg2); \
1493 _argvec[3] = (unsigned long)(arg3); \
1494 _argvec[4] = (unsigned long)(arg4); \
1495 _argvec[5] = (unsigned long)(arg5); \
1497 VALGRIND_CFI_PROLOGUE \
1498 "subq $128,%%rsp\n\t" \
1499 "movq 40(%%rax), %%r8\n\t" \
1500 "movq 32(%%rax), %%rcx\n\t" \
1501 "movq 24(%%rax), %%rdx\n\t" \
1502 "movq 16(%%rax), %%rsi\n\t" \
1503 "movq 8(%%rax), %%rdi\n\t" \
1504 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1505 VALGRIND_CALL_NOREDIR_RAX \
1506 "addq $128,%%rsp\n\t" \
1507 VALGRIND_CFI_EPILOGUE \
1508 : /*out*/ "=a" (_res) \
1509 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1510 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1512 lval = (__typeof__(lval)) _res; \
1515 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1517 volatile OrigFn _orig = (orig); \
1518 volatile unsigned long _argvec[7]; \
1519 volatile unsigned long _res; \
1520 _argvec[0] = (unsigned long)_orig.nraddr; \
1521 _argvec[1] = (unsigned long)(arg1); \
1522 _argvec[2] = (unsigned long)(arg2); \
1523 _argvec[3] = (unsigned long)(arg3); \
1524 _argvec[4] = (unsigned long)(arg4); \
1525 _argvec[5] = (unsigned long)(arg5); \
1526 _argvec[6] = (unsigned long)(arg6); \
1528 VALGRIND_CFI_PROLOGUE \
1529 "subq $128,%%rsp\n\t" \
1530 "movq 48(%%rax), %%r9\n\t" \
1531 "movq 40(%%rax), %%r8\n\t" \
1532 "movq 32(%%rax), %%rcx\n\t" \
1533 "movq 24(%%rax), %%rdx\n\t" \
1534 "movq 16(%%rax), %%rsi\n\t" \
1535 "movq 8(%%rax), %%rdi\n\t" \
1536 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1537 VALGRIND_CALL_NOREDIR_RAX \
1538 "addq $128,%%rsp\n\t" \
1539 VALGRIND_CFI_EPILOGUE \
1540 : /*out*/ "=a" (_res) \
1541 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1542 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1544 lval = (__typeof__(lval)) _res; \
1547 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1550 volatile OrigFn _orig = (orig); \
1551 volatile unsigned long _argvec[8]; \
1552 volatile unsigned long _res; \
1553 _argvec[0] = (unsigned long)_orig.nraddr; \
1554 _argvec[1] = (unsigned long)(arg1); \
1555 _argvec[2] = (unsigned long)(arg2); \
1556 _argvec[3] = (unsigned long)(arg3); \
1557 _argvec[4] = (unsigned long)(arg4); \
1558 _argvec[5] = (unsigned long)(arg5); \
1559 _argvec[6] = (unsigned long)(arg6); \
1560 _argvec[7] = (unsigned long)(arg7); \
1562 VALGRIND_CFI_PROLOGUE \
1563 "subq $136,%%rsp\n\t" \
1564 "pushq 56(%%rax)\n\t" \
1565 "movq 48(%%rax), %%r9\n\t" \
1566 "movq 40(%%rax), %%r8\n\t" \
1567 "movq 32(%%rax), %%rcx\n\t" \
1568 "movq 24(%%rax), %%rdx\n\t" \
1569 "movq 16(%%rax), %%rsi\n\t" \
1570 "movq 8(%%rax), %%rdi\n\t" \
1571 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1572 VALGRIND_CALL_NOREDIR_RAX \
1573 "addq $8, %%rsp\n" \
1574 "addq $136,%%rsp\n\t" \
1575 VALGRIND_CFI_EPILOGUE \
1576 : /*out*/ "=a" (_res) \
1577 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1578 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1580 lval = (__typeof__(lval)) _res; \
1583 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1586 volatile OrigFn _orig = (orig); \
1587 volatile unsigned long _argvec[9]; \
1588 volatile unsigned long _res; \
1589 _argvec[0] = (unsigned long)_orig.nraddr; \
1590 _argvec[1] = (unsigned long)(arg1); \
1591 _argvec[2] = (unsigned long)(arg2); \
1592 _argvec[3] = (unsigned long)(arg3); \
1593 _argvec[4] = (unsigned long)(arg4); \
1594 _argvec[5] = (unsigned long)(arg5); \
1595 _argvec[6] = (unsigned long)(arg6); \
1596 _argvec[7] = (unsigned long)(arg7); \
1597 _argvec[8] = (unsigned long)(arg8); \
1599 VALGRIND_CFI_PROLOGUE \
1600 "subq $128,%%rsp\n\t" \
1601 "pushq 64(%%rax)\n\t" \
1602 "pushq 56(%%rax)\n\t" \
1603 "movq 48(%%rax), %%r9\n\t" \
1604 "movq 40(%%rax), %%r8\n\t" \
1605 "movq 32(%%rax), %%rcx\n\t" \
1606 "movq 24(%%rax), %%rdx\n\t" \
1607 "movq 16(%%rax), %%rsi\n\t" \
1608 "movq 8(%%rax), %%rdi\n\t" \
1609 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1610 VALGRIND_CALL_NOREDIR_RAX \
1611 "addq $16, %%rsp\n" \
1612 "addq $128,%%rsp\n\t" \
1613 VALGRIND_CFI_EPILOGUE \
1614 : /*out*/ "=a" (_res) \
1615 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1616 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1618 lval = (__typeof__(lval)) _res; \
1621 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1624 volatile OrigFn _orig = (orig); \
1625 volatile unsigned long _argvec[10]; \
1626 volatile unsigned long _res; \
1627 _argvec[0] = (unsigned long)_orig.nraddr; \
1628 _argvec[1] = (unsigned long)(arg1); \
1629 _argvec[2] = (unsigned long)(arg2); \
1630 _argvec[3] = (unsigned long)(arg3); \
1631 _argvec[4] = (unsigned long)(arg4); \
1632 _argvec[5] = (unsigned long)(arg5); \
1633 _argvec[6] = (unsigned long)(arg6); \
1634 _argvec[7] = (unsigned long)(arg7); \
1635 _argvec[8] = (unsigned long)(arg8); \
1636 _argvec[9] = (unsigned long)(arg9); \
1638 VALGRIND_CFI_PROLOGUE \
1639 "subq $136,%%rsp\n\t" \
1640 "pushq 72(%%rax)\n\t" \
1641 "pushq 64(%%rax)\n\t" \
1642 "pushq 56(%%rax)\n\t" \
1643 "movq 48(%%rax), %%r9\n\t" \
1644 "movq 40(%%rax), %%r8\n\t" \
1645 "movq 32(%%rax), %%rcx\n\t" \
1646 "movq 24(%%rax), %%rdx\n\t" \
1647 "movq 16(%%rax), %%rsi\n\t" \
1648 "movq 8(%%rax), %%rdi\n\t" \
1649 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1650 VALGRIND_CALL_NOREDIR_RAX \
1651 "addq $24, %%rsp\n" \
1652 "addq $136,%%rsp\n\t" \
1653 VALGRIND_CFI_EPILOGUE \
1654 : /*out*/ "=a" (_res) \
1655 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1656 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1658 lval = (__typeof__(lval)) _res; \
1661 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1662 arg7,arg8,arg9,arg10) \
1664 volatile OrigFn _orig = (orig); \
1665 volatile unsigned long _argvec[11]; \
1666 volatile unsigned long _res; \
1667 _argvec[0] = (unsigned long)_orig.nraddr; \
1668 _argvec[1] = (unsigned long)(arg1); \
1669 _argvec[2] = (unsigned long)(arg2); \
1670 _argvec[3] = (unsigned long)(arg3); \
1671 _argvec[4] = (unsigned long)(arg4); \
1672 _argvec[5] = (unsigned long)(arg5); \
1673 _argvec[6] = (unsigned long)(arg6); \
1674 _argvec[7] = (unsigned long)(arg7); \
1675 _argvec[8] = (unsigned long)(arg8); \
1676 _argvec[9] = (unsigned long)(arg9); \
1677 _argvec[10] = (unsigned long)(arg10); \
1679 VALGRIND_CFI_PROLOGUE \
1680 "subq $128,%%rsp\n\t" \
1681 "pushq 80(%%rax)\n\t" \
1682 "pushq 72(%%rax)\n\t" \
1683 "pushq 64(%%rax)\n\t" \
1684 "pushq 56(%%rax)\n\t" \
1685 "movq 48(%%rax), %%r9\n\t" \
1686 "movq 40(%%rax), %%r8\n\t" \
1687 "movq 32(%%rax), %%rcx\n\t" \
1688 "movq 24(%%rax), %%rdx\n\t" \
1689 "movq 16(%%rax), %%rsi\n\t" \
1690 "movq 8(%%rax), %%rdi\n\t" \
1691 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1692 VALGRIND_CALL_NOREDIR_RAX \
1693 "addq $32, %%rsp\n" \
1694 "addq $128,%%rsp\n\t" \
1695 VALGRIND_CFI_EPILOGUE \
1696 : /*out*/ "=a" (_res) \
1697 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1698 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1700 lval = (__typeof__(lval)) _res; \
1703 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1704 arg7,arg8,arg9,arg10,arg11) \
1706 volatile OrigFn _orig = (orig); \
1707 volatile unsigned long _argvec[12]; \
1708 volatile unsigned long _res; \
1709 _argvec[0] = (unsigned long)_orig.nraddr; \
1710 _argvec[1] = (unsigned long)(arg1); \
1711 _argvec[2] = (unsigned long)(arg2); \
1712 _argvec[3] = (unsigned long)(arg3); \
1713 _argvec[4] = (unsigned long)(arg4); \
1714 _argvec[5] = (unsigned long)(arg5); \
1715 _argvec[6] = (unsigned long)(arg6); \
1716 _argvec[7] = (unsigned long)(arg7); \
1717 _argvec[8] = (unsigned long)(arg8); \
1718 _argvec[9] = (unsigned long)(arg9); \
1719 _argvec[10] = (unsigned long)(arg10); \
1720 _argvec[11] = (unsigned long)(arg11); \
1722 VALGRIND_CFI_PROLOGUE \
1723 "subq $136,%%rsp\n\t" \
1724 "pushq 88(%%rax)\n\t" \
1725 "pushq 80(%%rax)\n\t" \
1726 "pushq 72(%%rax)\n\t" \
1727 "pushq 64(%%rax)\n\t" \
1728 "pushq 56(%%rax)\n\t" \
1729 "movq 48(%%rax), %%r9\n\t" \
1730 "movq 40(%%rax), %%r8\n\t" \
1731 "movq 32(%%rax), %%rcx\n\t" \
1732 "movq 24(%%rax), %%rdx\n\t" \
1733 "movq 16(%%rax), %%rsi\n\t" \
1734 "movq 8(%%rax), %%rdi\n\t" \
1735 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1736 VALGRIND_CALL_NOREDIR_RAX \
1737 "addq $40, %%rsp\n" \
1738 "addq $136,%%rsp\n\t" \
1739 VALGRIND_CFI_EPILOGUE \
1740 : /*out*/ "=a" (_res) \
1741 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1742 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1744 lval = (__typeof__(lval)) _res; \
1747 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1748 arg7,arg8,arg9,arg10,arg11,arg12) \
1750 volatile OrigFn _orig = (orig); \
1751 volatile unsigned long _argvec[13]; \
1752 volatile unsigned long _res; \
1753 _argvec[0] = (unsigned long)_orig.nraddr; \
1754 _argvec[1] = (unsigned long)(arg1); \
1755 _argvec[2] = (unsigned long)(arg2); \
1756 _argvec[3] = (unsigned long)(arg3); \
1757 _argvec[4] = (unsigned long)(arg4); \
1758 _argvec[5] = (unsigned long)(arg5); \
1759 _argvec[6] = (unsigned long)(arg6); \
1760 _argvec[7] = (unsigned long)(arg7); \
1761 _argvec[8] = (unsigned long)(arg8); \
1762 _argvec[9] = (unsigned long)(arg9); \
1763 _argvec[10] = (unsigned long)(arg10); \
1764 _argvec[11] = (unsigned long)(arg11); \
1765 _argvec[12] = (unsigned long)(arg12); \
1767 VALGRIND_CFI_PROLOGUE \
1768 "subq $128,%%rsp\n\t" \
1769 "pushq 96(%%rax)\n\t" \
1770 "pushq 88(%%rax)\n\t" \
1771 "pushq 80(%%rax)\n\t" \
1772 "pushq 72(%%rax)\n\t" \
1773 "pushq 64(%%rax)\n\t" \
1774 "pushq 56(%%rax)\n\t" \
1775 "movq 48(%%rax), %%r9\n\t" \
1776 "movq 40(%%rax), %%r8\n\t" \
1777 "movq 32(%%rax), %%rcx\n\t" \
1778 "movq 24(%%rax), %%rdx\n\t" \
1779 "movq 16(%%rax), %%rsi\n\t" \
1780 "movq 8(%%rax), %%rdi\n\t" \
1781 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1782 VALGRIND_CALL_NOREDIR_RAX \
1783 "addq $48, %%rsp\n" \
1784 "addq $128,%%rsp\n\t" \
1785 VALGRIND_CFI_EPILOGUE \
1786 : /*out*/ "=a" (_res) \
1787 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1788 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
1790 lval = (__typeof__(lval)) _res; \
1793 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
1795 /* ------------------------ ppc32-linux ------------------------ */
1797 #if defined(PLAT_ppc32_linux)
1799 /* This is useful for finding out about the on-stack stuff:
1801 extern int f9 ( int,int,int,int,int,int,int,int,int );
1802 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1803 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1804 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1807 return f9(11,22,33,44,55,66,77,88,99);
1810 return f10(11,22,33,44,55,66,77,88,99,110);
1813 return f11(11,22,33,44,55,66,77,88,99,110,121);
1816 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1820 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1822 /* These regs are trashed by the hidden call. */
1823 #define __CALLER_SAVED_REGS \
1824 "lr", "ctr", "xer", \
1825 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1826 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1829 /* These CALL_FN_ macros assume that on ppc32-linux,
1830 sizeof(unsigned long) == 4. */
1832 #define CALL_FN_W_v(lval, orig) \
1834 volatile OrigFn _orig = (orig); \
1835 volatile unsigned long _argvec[1]; \
1836 volatile unsigned long _res; \
1837 _argvec[0] = (unsigned long)_orig.nraddr; \
1840 "lwz 11,0(11)\n\t" /* target->r11 */ \
1841 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1843 : /*out*/ "=r" (_res) \
1844 : /*in*/ "r" (&_argvec[0]) \
1845 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1847 lval = (__typeof__(lval)) _res; \
1850 #define CALL_FN_W_W(lval, orig, arg1) \
1852 volatile OrigFn _orig = (orig); \
1853 volatile unsigned long _argvec[2]; \
1854 volatile unsigned long _res; \
1855 _argvec[0] = (unsigned long)_orig.nraddr; \
1856 _argvec[1] = (unsigned long)arg1; \
1859 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1860 "lwz 11,0(11)\n\t" /* target->r11 */ \
1861 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1863 : /*out*/ "=r" (_res) \
1864 : /*in*/ "r" (&_argvec[0]) \
1865 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1867 lval = (__typeof__(lval)) _res; \
1870 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1872 volatile OrigFn _orig = (orig); \
1873 volatile unsigned long _argvec[3]; \
1874 volatile unsigned long _res; \
1875 _argvec[0] = (unsigned long)_orig.nraddr; \
1876 _argvec[1] = (unsigned long)arg1; \
1877 _argvec[2] = (unsigned long)arg2; \
1880 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1882 "lwz 11,0(11)\n\t" /* target->r11 */ \
1883 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1885 : /*out*/ "=r" (_res) \
1886 : /*in*/ "r" (&_argvec[0]) \
1887 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1889 lval = (__typeof__(lval)) _res; \
1892 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1894 volatile OrigFn _orig = (orig); \
1895 volatile unsigned long _argvec[4]; \
1896 volatile unsigned long _res; \
1897 _argvec[0] = (unsigned long)_orig.nraddr; \
1898 _argvec[1] = (unsigned long)arg1; \
1899 _argvec[2] = (unsigned long)arg2; \
1900 _argvec[3] = (unsigned long)arg3; \
1903 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1905 "lwz 5,12(11)\n\t" \
1906 "lwz 11,0(11)\n\t" /* target->r11 */ \
1907 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1909 : /*out*/ "=r" (_res) \
1910 : /*in*/ "r" (&_argvec[0]) \
1911 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1913 lval = (__typeof__(lval)) _res; \
1916 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1918 volatile OrigFn _orig = (orig); \
1919 volatile unsigned long _argvec[5]; \
1920 volatile unsigned long _res; \
1921 _argvec[0] = (unsigned long)_orig.nraddr; \
1922 _argvec[1] = (unsigned long)arg1; \
1923 _argvec[2] = (unsigned long)arg2; \
1924 _argvec[3] = (unsigned long)arg3; \
1925 _argvec[4] = (unsigned long)arg4; \
1928 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1930 "lwz 5,12(11)\n\t" \
1931 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1932 "lwz 11,0(11)\n\t" /* target->r11 */ \
1933 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1935 : /*out*/ "=r" (_res) \
1936 : /*in*/ "r" (&_argvec[0]) \
1937 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1939 lval = (__typeof__(lval)) _res; \
1942 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1944 volatile OrigFn _orig = (orig); \
1945 volatile unsigned long _argvec[6]; \
1946 volatile unsigned long _res; \
1947 _argvec[0] = (unsigned long)_orig.nraddr; \
1948 _argvec[1] = (unsigned long)arg1; \
1949 _argvec[2] = (unsigned long)arg2; \
1950 _argvec[3] = (unsigned long)arg3; \
1951 _argvec[4] = (unsigned long)arg4; \
1952 _argvec[5] = (unsigned long)arg5; \
1955 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1957 "lwz 5,12(11)\n\t" \
1958 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1959 "lwz 7,20(11)\n\t" \
1960 "lwz 11,0(11)\n\t" /* target->r11 */ \
1961 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1963 : /*out*/ "=r" (_res) \
1964 : /*in*/ "r" (&_argvec[0]) \
1965 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1967 lval = (__typeof__(lval)) _res; \
1970 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1972 volatile OrigFn _orig = (orig); \
1973 volatile unsigned long _argvec[7]; \
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; \
1984 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1986 "lwz 5,12(11)\n\t" \
1987 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1988 "lwz 7,20(11)\n\t" \
1989 "lwz 8,24(11)\n\t" \
1990 "lwz 11,0(11)\n\t" /* target->r11 */ \
1991 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1993 : /*out*/ "=r" (_res) \
1994 : /*in*/ "r" (&_argvec[0]) \
1995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1997 lval = (__typeof__(lval)) _res; \
2000 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2003 volatile OrigFn _orig = (orig); \
2004 volatile unsigned long _argvec[8]; \
2005 volatile unsigned long _res; \
2006 _argvec[0] = (unsigned long)_orig.nraddr; \
2007 _argvec[1] = (unsigned long)arg1; \
2008 _argvec[2] = (unsigned long)arg2; \
2009 _argvec[3] = (unsigned long)arg3; \
2010 _argvec[4] = (unsigned long)arg4; \
2011 _argvec[5] = (unsigned long)arg5; \
2012 _argvec[6] = (unsigned long)arg6; \
2013 _argvec[7] = (unsigned long)arg7; \
2016 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2018 "lwz 5,12(11)\n\t" \
2019 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2020 "lwz 7,20(11)\n\t" \
2021 "lwz 8,24(11)\n\t" \
2022 "lwz 9,28(11)\n\t" \
2023 "lwz 11,0(11)\n\t" /* target->r11 */ \
2024 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2026 : /*out*/ "=r" (_res) \
2027 : /*in*/ "r" (&_argvec[0]) \
2028 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2030 lval = (__typeof__(lval)) _res; \
2033 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2036 volatile OrigFn _orig = (orig); \
2037 volatile unsigned long _argvec[9]; \
2038 volatile unsigned long _res; \
2039 _argvec[0] = (unsigned long)_orig.nraddr; \
2040 _argvec[1] = (unsigned long)arg1; \
2041 _argvec[2] = (unsigned long)arg2; \
2042 _argvec[3] = (unsigned long)arg3; \
2043 _argvec[4] = (unsigned long)arg4; \
2044 _argvec[5] = (unsigned long)arg5; \
2045 _argvec[6] = (unsigned long)arg6; \
2046 _argvec[7] = (unsigned long)arg7; \
2047 _argvec[8] = (unsigned long)arg8; \
2050 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2052 "lwz 5,12(11)\n\t" \
2053 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2054 "lwz 7,20(11)\n\t" \
2055 "lwz 8,24(11)\n\t" \
2056 "lwz 9,28(11)\n\t" \
2057 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2058 "lwz 11,0(11)\n\t" /* target->r11 */ \
2059 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2061 : /*out*/ "=r" (_res) \
2062 : /*in*/ "r" (&_argvec[0]) \
2063 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2065 lval = (__typeof__(lval)) _res; \
2068 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2071 volatile OrigFn _orig = (orig); \
2072 volatile unsigned long _argvec[10]; \
2073 volatile unsigned long _res; \
2074 _argvec[0] = (unsigned long)_orig.nraddr; \
2075 _argvec[1] = (unsigned long)arg1; \
2076 _argvec[2] = (unsigned long)arg2; \
2077 _argvec[3] = (unsigned long)arg3; \
2078 _argvec[4] = (unsigned long)arg4; \
2079 _argvec[5] = (unsigned long)arg5; \
2080 _argvec[6] = (unsigned long)arg6; \
2081 _argvec[7] = (unsigned long)arg7; \
2082 _argvec[8] = (unsigned long)arg8; \
2083 _argvec[9] = (unsigned long)arg9; \
2086 "addi 1,1,-16\n\t" \
2088 "lwz 3,36(11)\n\t" \
2091 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2093 "lwz 5,12(11)\n\t" \
2094 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2095 "lwz 7,20(11)\n\t" \
2096 "lwz 8,24(11)\n\t" \
2097 "lwz 9,28(11)\n\t" \
2098 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2099 "lwz 11,0(11)\n\t" /* target->r11 */ \
2100 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2103 : /*out*/ "=r" (_res) \
2104 : /*in*/ "r" (&_argvec[0]) \
2105 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2107 lval = (__typeof__(lval)) _res; \
2110 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2111 arg7,arg8,arg9,arg10) \
2113 volatile OrigFn _orig = (orig); \
2114 volatile unsigned long _argvec[11]; \
2115 volatile unsigned long _res; \
2116 _argvec[0] = (unsigned long)_orig.nraddr; \
2117 _argvec[1] = (unsigned long)arg1; \
2118 _argvec[2] = (unsigned long)arg2; \
2119 _argvec[3] = (unsigned long)arg3; \
2120 _argvec[4] = (unsigned long)arg4; \
2121 _argvec[5] = (unsigned long)arg5; \
2122 _argvec[6] = (unsigned long)arg6; \
2123 _argvec[7] = (unsigned long)arg7; \
2124 _argvec[8] = (unsigned long)arg8; \
2125 _argvec[9] = (unsigned long)arg9; \
2126 _argvec[10] = (unsigned long)arg10; \
2129 "addi 1,1,-16\n\t" \
2131 "lwz 3,40(11)\n\t" \
2134 "lwz 3,36(11)\n\t" \
2137 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2139 "lwz 5,12(11)\n\t" \
2140 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2141 "lwz 7,20(11)\n\t" \
2142 "lwz 8,24(11)\n\t" \
2143 "lwz 9,28(11)\n\t" \
2144 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2145 "lwz 11,0(11)\n\t" /* target->r11 */ \
2146 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2149 : /*out*/ "=r" (_res) \
2150 : /*in*/ "r" (&_argvec[0]) \
2151 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2153 lval = (__typeof__(lval)) _res; \
2156 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2157 arg7,arg8,arg9,arg10,arg11) \
2159 volatile OrigFn _orig = (orig); \
2160 volatile unsigned long _argvec[12]; \
2161 volatile unsigned long _res; \
2162 _argvec[0] = (unsigned long)_orig.nraddr; \
2163 _argvec[1] = (unsigned long)arg1; \
2164 _argvec[2] = (unsigned long)arg2; \
2165 _argvec[3] = (unsigned long)arg3; \
2166 _argvec[4] = (unsigned long)arg4; \
2167 _argvec[5] = (unsigned long)arg5; \
2168 _argvec[6] = (unsigned long)arg6; \
2169 _argvec[7] = (unsigned long)arg7; \
2170 _argvec[8] = (unsigned long)arg8; \
2171 _argvec[9] = (unsigned long)arg9; \
2172 _argvec[10] = (unsigned long)arg10; \
2173 _argvec[11] = (unsigned long)arg11; \
2176 "addi 1,1,-32\n\t" \
2178 "lwz 3,44(11)\n\t" \
2181 "lwz 3,40(11)\n\t" \
2184 "lwz 3,36(11)\n\t" \
2187 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2189 "lwz 5,12(11)\n\t" \
2190 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2191 "lwz 7,20(11)\n\t" \
2192 "lwz 8,24(11)\n\t" \
2193 "lwz 9,28(11)\n\t" \
2194 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2195 "lwz 11,0(11)\n\t" /* target->r11 */ \
2196 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2199 : /*out*/ "=r" (_res) \
2200 : /*in*/ "r" (&_argvec[0]) \
2201 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2203 lval = (__typeof__(lval)) _res; \
2206 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2207 arg7,arg8,arg9,arg10,arg11,arg12) \
2209 volatile OrigFn _orig = (orig); \
2210 volatile unsigned long _argvec[13]; \
2211 volatile unsigned long _res; \
2212 _argvec[0] = (unsigned long)_orig.nraddr; \
2213 _argvec[1] = (unsigned long)arg1; \
2214 _argvec[2] = (unsigned long)arg2; \
2215 _argvec[3] = (unsigned long)arg3; \
2216 _argvec[4] = (unsigned long)arg4; \
2217 _argvec[5] = (unsigned long)arg5; \
2218 _argvec[6] = (unsigned long)arg6; \
2219 _argvec[7] = (unsigned long)arg7; \
2220 _argvec[8] = (unsigned long)arg8; \
2221 _argvec[9] = (unsigned long)arg9; \
2222 _argvec[10] = (unsigned long)arg10; \
2223 _argvec[11] = (unsigned long)arg11; \
2224 _argvec[12] = (unsigned long)arg12; \
2227 "addi 1,1,-32\n\t" \
2229 "lwz 3,48(11)\n\t" \
2232 "lwz 3,44(11)\n\t" \
2235 "lwz 3,40(11)\n\t" \
2238 "lwz 3,36(11)\n\t" \
2241 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2243 "lwz 5,12(11)\n\t" \
2244 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2245 "lwz 7,20(11)\n\t" \
2246 "lwz 8,24(11)\n\t" \
2247 "lwz 9,28(11)\n\t" \
2248 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2249 "lwz 11,0(11)\n\t" /* target->r11 */ \
2250 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2253 : /*out*/ "=r" (_res) \
2254 : /*in*/ "r" (&_argvec[0]) \
2255 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2257 lval = (__typeof__(lval)) _res; \
2260 #endif /* PLAT_ppc32_linux */
2262 /* ------------------------ ppc64-linux ------------------------ */
2264 #if defined(PLAT_ppc64_linux)
2266 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2268 /* These regs are trashed by the hidden call. */
2269 #define __CALLER_SAVED_REGS \
2270 "lr", "ctr", "xer", \
2271 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2272 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2275 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2278 #define CALL_FN_W_v(lval, orig) \
2280 volatile OrigFn _orig = (orig); \
2281 volatile unsigned long _argvec[3+0]; \
2282 volatile unsigned long _res; \
2283 /* _argvec[0] holds current r2 across the call */ \
2284 _argvec[1] = (unsigned long)_orig.r2; \
2285 _argvec[2] = (unsigned long)_orig.nraddr; \
2288 "std 2,-16(11)\n\t" /* save tocptr */ \
2289 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2290 "ld 11, 0(11)\n\t" /* target->r11 */ \
2291 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2294 "ld 2,-16(11)" /* restore tocptr */ \
2295 : /*out*/ "=r" (_res) \
2296 : /*in*/ "r" (&_argvec[2]) \
2297 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2299 lval = (__typeof__(lval)) _res; \
2302 #define CALL_FN_W_W(lval, orig, arg1) \
2304 volatile OrigFn _orig = (orig); \
2305 volatile unsigned long _argvec[3+1]; \
2306 volatile unsigned long _res; \
2307 /* _argvec[0] holds current r2 across the call */ \
2308 _argvec[1] = (unsigned long)_orig.r2; \
2309 _argvec[2] = (unsigned long)_orig.nraddr; \
2310 _argvec[2+1] = (unsigned long)arg1; \
2313 "std 2,-16(11)\n\t" /* save tocptr */ \
2314 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2315 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2316 "ld 11, 0(11)\n\t" /* target->r11 */ \
2317 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2320 "ld 2,-16(11)" /* restore tocptr */ \
2321 : /*out*/ "=r" (_res) \
2322 : /*in*/ "r" (&_argvec[2]) \
2323 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2325 lval = (__typeof__(lval)) _res; \
2328 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2330 volatile OrigFn _orig = (orig); \
2331 volatile unsigned long _argvec[3+2]; \
2332 volatile unsigned long _res; \
2333 /* _argvec[0] holds current r2 across the call */ \
2334 _argvec[1] = (unsigned long)_orig.r2; \
2335 _argvec[2] = (unsigned long)_orig.nraddr; \
2336 _argvec[2+1] = (unsigned long)arg1; \
2337 _argvec[2+2] = (unsigned long)arg2; \
2340 "std 2,-16(11)\n\t" /* save tocptr */ \
2341 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2342 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2343 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2344 "ld 11, 0(11)\n\t" /* target->r11 */ \
2345 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2348 "ld 2,-16(11)" /* restore tocptr */ \
2349 : /*out*/ "=r" (_res) \
2350 : /*in*/ "r" (&_argvec[2]) \
2351 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2353 lval = (__typeof__(lval)) _res; \
2356 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2358 volatile OrigFn _orig = (orig); \
2359 volatile unsigned long _argvec[3+3]; \
2360 volatile unsigned long _res; \
2361 /* _argvec[0] holds current r2 across the call */ \
2362 _argvec[1] = (unsigned long)_orig.r2; \
2363 _argvec[2] = (unsigned long)_orig.nraddr; \
2364 _argvec[2+1] = (unsigned long)arg1; \
2365 _argvec[2+2] = (unsigned long)arg2; \
2366 _argvec[2+3] = (unsigned long)arg3; \
2369 "std 2,-16(11)\n\t" /* save tocptr */ \
2370 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2371 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2372 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2373 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2374 "ld 11, 0(11)\n\t" /* target->r11 */ \
2375 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2378 "ld 2,-16(11)" /* restore tocptr */ \
2379 : /*out*/ "=r" (_res) \
2380 : /*in*/ "r" (&_argvec[2]) \
2381 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2383 lval = (__typeof__(lval)) _res; \
2386 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2388 volatile OrigFn _orig = (orig); \
2389 volatile unsigned long _argvec[3+4]; \
2390 volatile unsigned long _res; \
2391 /* _argvec[0] holds current r2 across the call */ \
2392 _argvec[1] = (unsigned long)_orig.r2; \
2393 _argvec[2] = (unsigned long)_orig.nraddr; \
2394 _argvec[2+1] = (unsigned long)arg1; \
2395 _argvec[2+2] = (unsigned long)arg2; \
2396 _argvec[2+3] = (unsigned long)arg3; \
2397 _argvec[2+4] = (unsigned long)arg4; \
2400 "std 2,-16(11)\n\t" /* save tocptr */ \
2401 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2402 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2403 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2404 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2405 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2406 "ld 11, 0(11)\n\t" /* target->r11 */ \
2407 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2410 "ld 2,-16(11)" /* restore tocptr */ \
2411 : /*out*/ "=r" (_res) \
2412 : /*in*/ "r" (&_argvec[2]) \
2413 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2415 lval = (__typeof__(lval)) _res; \
2418 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2420 volatile OrigFn _orig = (orig); \
2421 volatile unsigned long _argvec[3+5]; \
2422 volatile unsigned long _res; \
2423 /* _argvec[0] holds current r2 across the call */ \
2424 _argvec[1] = (unsigned long)_orig.r2; \
2425 _argvec[2] = (unsigned long)_orig.nraddr; \
2426 _argvec[2+1] = (unsigned long)arg1; \
2427 _argvec[2+2] = (unsigned long)arg2; \
2428 _argvec[2+3] = (unsigned long)arg3; \
2429 _argvec[2+4] = (unsigned long)arg4; \
2430 _argvec[2+5] = (unsigned long)arg5; \
2433 "std 2,-16(11)\n\t" /* save tocptr */ \
2434 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2435 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2436 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2437 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2438 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2439 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2440 "ld 11, 0(11)\n\t" /* target->r11 */ \
2441 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2444 "ld 2,-16(11)" /* restore tocptr */ \
2445 : /*out*/ "=r" (_res) \
2446 : /*in*/ "r" (&_argvec[2]) \
2447 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2449 lval = (__typeof__(lval)) _res; \
2452 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2454 volatile OrigFn _orig = (orig); \
2455 volatile unsigned long _argvec[3+6]; \
2456 volatile unsigned long _res; \
2457 /* _argvec[0] holds current r2 across the call */ \
2458 _argvec[1] = (unsigned long)_orig.r2; \
2459 _argvec[2] = (unsigned long)_orig.nraddr; \
2460 _argvec[2+1] = (unsigned long)arg1; \
2461 _argvec[2+2] = (unsigned long)arg2; \
2462 _argvec[2+3] = (unsigned long)arg3; \
2463 _argvec[2+4] = (unsigned long)arg4; \
2464 _argvec[2+5] = (unsigned long)arg5; \
2465 _argvec[2+6] = (unsigned long)arg6; \
2468 "std 2,-16(11)\n\t" /* save tocptr */ \
2469 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2470 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2471 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2472 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2473 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2474 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2475 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2476 "ld 11, 0(11)\n\t" /* target->r11 */ \
2477 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2480 "ld 2,-16(11)" /* restore tocptr */ \
2481 : /*out*/ "=r" (_res) \
2482 : /*in*/ "r" (&_argvec[2]) \
2483 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2485 lval = (__typeof__(lval)) _res; \
2488 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2491 volatile OrigFn _orig = (orig); \
2492 volatile unsigned long _argvec[3+7]; \
2493 volatile unsigned long _res; \
2494 /* _argvec[0] holds current r2 across the call */ \
2495 _argvec[1] = (unsigned long)_orig.r2; \
2496 _argvec[2] = (unsigned long)_orig.nraddr; \
2497 _argvec[2+1] = (unsigned long)arg1; \
2498 _argvec[2+2] = (unsigned long)arg2; \
2499 _argvec[2+3] = (unsigned long)arg3; \
2500 _argvec[2+4] = (unsigned long)arg4; \
2501 _argvec[2+5] = (unsigned long)arg5; \
2502 _argvec[2+6] = (unsigned long)arg6; \
2503 _argvec[2+7] = (unsigned long)arg7; \
2506 "std 2,-16(11)\n\t" /* save tocptr */ \
2507 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2508 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2509 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2510 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2511 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2512 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2513 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2514 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2515 "ld 11, 0(11)\n\t" /* target->r11 */ \
2516 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2519 "ld 2,-16(11)" /* restore tocptr */ \
2520 : /*out*/ "=r" (_res) \
2521 : /*in*/ "r" (&_argvec[2]) \
2522 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2524 lval = (__typeof__(lval)) _res; \
2527 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2530 volatile OrigFn _orig = (orig); \
2531 volatile unsigned long _argvec[3+8]; \
2532 volatile unsigned long _res; \
2533 /* _argvec[0] holds current r2 across the call */ \
2534 _argvec[1] = (unsigned long)_orig.r2; \
2535 _argvec[2] = (unsigned long)_orig.nraddr; \
2536 _argvec[2+1] = (unsigned long)arg1; \
2537 _argvec[2+2] = (unsigned long)arg2; \
2538 _argvec[2+3] = (unsigned long)arg3; \
2539 _argvec[2+4] = (unsigned long)arg4; \
2540 _argvec[2+5] = (unsigned long)arg5; \
2541 _argvec[2+6] = (unsigned long)arg6; \
2542 _argvec[2+7] = (unsigned long)arg7; \
2543 _argvec[2+8] = (unsigned long)arg8; \
2546 "std 2,-16(11)\n\t" /* save tocptr */ \
2547 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2548 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2549 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2550 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2551 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2552 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2553 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2554 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2555 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2556 "ld 11, 0(11)\n\t" /* target->r11 */ \
2557 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2560 "ld 2,-16(11)" /* restore tocptr */ \
2561 : /*out*/ "=r" (_res) \
2562 : /*in*/ "r" (&_argvec[2]) \
2563 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2565 lval = (__typeof__(lval)) _res; \
2568 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2571 volatile OrigFn _orig = (orig); \
2572 volatile unsigned long _argvec[3+9]; \
2573 volatile unsigned long _res; \
2574 /* _argvec[0] holds current r2 across the call */ \
2575 _argvec[1] = (unsigned long)_orig.r2; \
2576 _argvec[2] = (unsigned long)_orig.nraddr; \
2577 _argvec[2+1] = (unsigned long)arg1; \
2578 _argvec[2+2] = (unsigned long)arg2; \
2579 _argvec[2+3] = (unsigned long)arg3; \
2580 _argvec[2+4] = (unsigned long)arg4; \
2581 _argvec[2+5] = (unsigned long)arg5; \
2582 _argvec[2+6] = (unsigned long)arg6; \
2583 _argvec[2+7] = (unsigned long)arg7; \
2584 _argvec[2+8] = (unsigned long)arg8; \
2585 _argvec[2+9] = (unsigned long)arg9; \
2588 "std 2,-16(11)\n\t" /* save tocptr */ \
2589 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2590 "addi 1,1,-128\n\t" /* expand stack frame */ \
2593 "std 3,112(1)\n\t" \
2595 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2596 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2597 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2598 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2599 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2600 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2601 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2602 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2603 "ld 11, 0(11)\n\t" /* target->r11 */ \
2604 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2607 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2608 "addi 1,1,128" /* restore frame */ \
2609 : /*out*/ "=r" (_res) \
2610 : /*in*/ "r" (&_argvec[2]) \
2611 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2613 lval = (__typeof__(lval)) _res; \
2616 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2617 arg7,arg8,arg9,arg10) \
2619 volatile OrigFn _orig = (orig); \
2620 volatile unsigned long _argvec[3+10]; \
2621 volatile unsigned long _res; \
2622 /* _argvec[0] holds current r2 across the call */ \
2623 _argvec[1] = (unsigned long)_orig.r2; \
2624 _argvec[2] = (unsigned long)_orig.nraddr; \
2625 _argvec[2+1] = (unsigned long)arg1; \
2626 _argvec[2+2] = (unsigned long)arg2; \
2627 _argvec[2+3] = (unsigned long)arg3; \
2628 _argvec[2+4] = (unsigned long)arg4; \
2629 _argvec[2+5] = (unsigned long)arg5; \
2630 _argvec[2+6] = (unsigned long)arg6; \
2631 _argvec[2+7] = (unsigned long)arg7; \
2632 _argvec[2+8] = (unsigned long)arg8; \
2633 _argvec[2+9] = (unsigned long)arg9; \
2634 _argvec[2+10] = (unsigned long)arg10; \
2637 "std 2,-16(11)\n\t" /* save tocptr */ \
2638 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2639 "addi 1,1,-128\n\t" /* expand stack frame */ \
2642 "std 3,120(1)\n\t" \
2645 "std 3,112(1)\n\t" \
2647 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2648 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2649 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2650 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2651 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2652 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2653 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2654 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2655 "ld 11, 0(11)\n\t" /* target->r11 */ \
2656 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2659 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2660 "addi 1,1,128" /* restore frame */ \
2661 : /*out*/ "=r" (_res) \
2662 : /*in*/ "r" (&_argvec[2]) \
2663 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2665 lval = (__typeof__(lval)) _res; \
2668 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2669 arg7,arg8,arg9,arg10,arg11) \
2671 volatile OrigFn _orig = (orig); \
2672 volatile unsigned long _argvec[3+11]; \
2673 volatile unsigned long _res; \
2674 /* _argvec[0] holds current r2 across the call */ \
2675 _argvec[1] = (unsigned long)_orig.r2; \
2676 _argvec[2] = (unsigned long)_orig.nraddr; \
2677 _argvec[2+1] = (unsigned long)arg1; \
2678 _argvec[2+2] = (unsigned long)arg2; \
2679 _argvec[2+3] = (unsigned long)arg3; \
2680 _argvec[2+4] = (unsigned long)arg4; \
2681 _argvec[2+5] = (unsigned long)arg5; \
2682 _argvec[2+6] = (unsigned long)arg6; \
2683 _argvec[2+7] = (unsigned long)arg7; \
2684 _argvec[2+8] = (unsigned long)arg8; \
2685 _argvec[2+9] = (unsigned long)arg9; \
2686 _argvec[2+10] = (unsigned long)arg10; \
2687 _argvec[2+11] = (unsigned long)arg11; \
2690 "std 2,-16(11)\n\t" /* save tocptr */ \
2691 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2692 "addi 1,1,-144\n\t" /* expand stack frame */ \
2695 "std 3,128(1)\n\t" \
2698 "std 3,120(1)\n\t" \
2701 "std 3,112(1)\n\t" \
2703 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2704 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2705 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2706 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2707 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2708 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2709 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2710 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2711 "ld 11, 0(11)\n\t" /* target->r11 */ \
2712 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2715 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2716 "addi 1,1,144" /* restore frame */ \
2717 : /*out*/ "=r" (_res) \
2718 : /*in*/ "r" (&_argvec[2]) \
2719 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2721 lval = (__typeof__(lval)) _res; \
2724 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2725 arg7,arg8,arg9,arg10,arg11,arg12) \
2727 volatile OrigFn _orig = (orig); \
2728 volatile unsigned long _argvec[3+12]; \
2729 volatile unsigned long _res; \
2730 /* _argvec[0] holds current r2 across the call */ \
2731 _argvec[1] = (unsigned long)_orig.r2; \
2732 _argvec[2] = (unsigned long)_orig.nraddr; \
2733 _argvec[2+1] = (unsigned long)arg1; \
2734 _argvec[2+2] = (unsigned long)arg2; \
2735 _argvec[2+3] = (unsigned long)arg3; \
2736 _argvec[2+4] = (unsigned long)arg4; \
2737 _argvec[2+5] = (unsigned long)arg5; \
2738 _argvec[2+6] = (unsigned long)arg6; \
2739 _argvec[2+7] = (unsigned long)arg7; \
2740 _argvec[2+8] = (unsigned long)arg8; \
2741 _argvec[2+9] = (unsigned long)arg9; \
2742 _argvec[2+10] = (unsigned long)arg10; \
2743 _argvec[2+11] = (unsigned long)arg11; \
2744 _argvec[2+12] = (unsigned long)arg12; \
2747 "std 2,-16(11)\n\t" /* save tocptr */ \
2748 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2749 "addi 1,1,-144\n\t" /* expand stack frame */ \
2752 "std 3,136(1)\n\t" \
2755 "std 3,128(1)\n\t" \
2758 "std 3,120(1)\n\t" \
2761 "std 3,112(1)\n\t" \
2763 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2764 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2765 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2766 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2767 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2768 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2769 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2770 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2771 "ld 11, 0(11)\n\t" /* target->r11 */ \
2772 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2775 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2776 "addi 1,1,144" /* restore frame */ \
2777 : /*out*/ "=r" (_res) \
2778 : /*in*/ "r" (&_argvec[2]) \
2779 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2781 lval = (__typeof__(lval)) _res; \
2784 #endif /* PLAT_ppc64_linux */
2786 /* ------------------------- arm-linux ------------------------- */
2788 #if defined(PLAT_arm_linux)
2790 /* These regs are trashed by the hidden call. */
2791 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2793 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2796 #define CALL_FN_W_v(lval, orig) \
2798 volatile OrigFn _orig = (orig); \
2799 volatile unsigned long _argvec[1]; \
2800 volatile unsigned long _res; \
2801 _argvec[0] = (unsigned long)_orig.nraddr; \
2803 "ldr r4, [%1] \n\t" /* target->r4 */ \
2804 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2806 : /*out*/ "=r" (_res) \
2807 : /*in*/ "0" (&_argvec[0]) \
2808 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2810 lval = (__typeof__(lval)) _res; \
2813 #define CALL_FN_W_W(lval, orig, arg1) \
2815 volatile OrigFn _orig = (orig); \
2816 volatile unsigned long _argvec[2]; \
2817 volatile unsigned long _res; \
2818 _argvec[0] = (unsigned long)_orig.nraddr; \
2819 _argvec[1] = (unsigned long)(arg1); \
2821 "ldr r0, [%1, #4] \n\t" \
2822 "ldr r4, [%1] \n\t" /* target->r4 */ \
2823 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
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_WW(lval, orig, arg1,arg2) \
2834 volatile OrigFn _orig = (orig); \
2835 volatile unsigned long _argvec[3]; \
2836 volatile unsigned long _res; \
2837 _argvec[0] = (unsigned long)_orig.nraddr; \
2838 _argvec[1] = (unsigned long)(arg1); \
2839 _argvec[2] = (unsigned long)(arg2); \
2841 "ldr r0, [%1, #4] \n\t" \
2842 "ldr r1, [%1, #8] \n\t" \
2843 "ldr r4, [%1] \n\t" /* target->r4 */ \
2844 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2846 : /*out*/ "=r" (_res) \
2847 : /*in*/ "0" (&_argvec[0]) \
2848 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2850 lval = (__typeof__(lval)) _res; \
2853 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2855 volatile OrigFn _orig = (orig); \
2856 volatile unsigned long _argvec[4]; \
2857 volatile unsigned long _res; \
2858 _argvec[0] = (unsigned long)_orig.nraddr; \
2859 _argvec[1] = (unsigned long)(arg1); \
2860 _argvec[2] = (unsigned long)(arg2); \
2861 _argvec[3] = (unsigned long)(arg3); \
2863 "ldr r0, [%1, #4] \n\t" \
2864 "ldr r1, [%1, #8] \n\t" \
2865 "ldr r2, [%1, #12] \n\t" \
2866 "ldr r4, [%1] \n\t" /* target->r4 */ \
2867 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2869 : /*out*/ "=r" (_res) \
2870 : /*in*/ "0" (&_argvec[0]) \
2871 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2873 lval = (__typeof__(lval)) _res; \
2876 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2878 volatile OrigFn _orig = (orig); \
2879 volatile unsigned long _argvec[5]; \
2880 volatile unsigned long _res; \
2881 _argvec[0] = (unsigned long)_orig.nraddr; \
2882 _argvec[1] = (unsigned long)(arg1); \
2883 _argvec[2] = (unsigned long)(arg2); \
2884 _argvec[3] = (unsigned long)(arg3); \
2885 _argvec[4] = (unsigned long)(arg4); \
2887 "ldr r0, [%1, #4] \n\t" \
2888 "ldr r1, [%1, #8] \n\t" \
2889 "ldr r2, [%1, #12] \n\t" \
2890 "ldr r3, [%1, #16] \n\t" \
2891 "ldr r4, [%1] \n\t" /* target->r4 */ \
2892 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2894 : /*out*/ "=r" (_res) \
2895 : /*in*/ "0" (&_argvec[0]) \
2896 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2898 lval = (__typeof__(lval)) _res; \
2901 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2903 volatile OrigFn _orig = (orig); \
2904 volatile unsigned long _argvec[6]; \
2905 volatile unsigned long _res; \
2906 _argvec[0] = (unsigned long)_orig.nraddr; \
2907 _argvec[1] = (unsigned long)(arg1); \
2908 _argvec[2] = (unsigned long)(arg2); \
2909 _argvec[3] = (unsigned long)(arg3); \
2910 _argvec[4] = (unsigned long)(arg4); \
2911 _argvec[5] = (unsigned long)(arg5); \
2913 "ldr r0, [%1, #20] \n\t" \
2915 "ldr r0, [%1, #4] \n\t" \
2916 "ldr r1, [%1, #8] \n\t" \
2917 "ldr r2, [%1, #12] \n\t" \
2918 "ldr r3, [%1, #16] \n\t" \
2919 "ldr r4, [%1] \n\t" /* target->r4 */ \
2920 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2921 "add sp, sp, #4 \n\t" \
2923 : /*out*/ "=r" (_res) \
2924 : /*in*/ "0" (&_argvec[0]) \
2925 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2927 lval = (__typeof__(lval)) _res; \
2930 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2932 volatile OrigFn _orig = (orig); \
2933 volatile unsigned long _argvec[7]; \
2934 volatile unsigned long _res; \
2935 _argvec[0] = (unsigned long)_orig.nraddr; \
2936 _argvec[1] = (unsigned long)(arg1); \
2937 _argvec[2] = (unsigned long)(arg2); \
2938 _argvec[3] = (unsigned long)(arg3); \
2939 _argvec[4] = (unsigned long)(arg4); \
2940 _argvec[5] = (unsigned long)(arg5); \
2941 _argvec[6] = (unsigned long)(arg6); \
2943 "ldr r0, [%1, #20] \n\t" \
2944 "ldr r1, [%1, #24] \n\t" \
2945 "push {r0, r1} \n\t" \
2946 "ldr r0, [%1, #4] \n\t" \
2947 "ldr r1, [%1, #8] \n\t" \
2948 "ldr r2, [%1, #12] \n\t" \
2949 "ldr r3, [%1, #16] \n\t" \
2950 "ldr r4, [%1] \n\t" /* target->r4 */ \
2951 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2952 "add sp, sp, #8 \n\t" \
2954 : /*out*/ "=r" (_res) \
2955 : /*in*/ "0" (&_argvec[0]) \
2956 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2958 lval = (__typeof__(lval)) _res; \
2961 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2964 volatile OrigFn _orig = (orig); \
2965 volatile unsigned long _argvec[8]; \
2966 volatile unsigned long _res; \
2967 _argvec[0] = (unsigned long)_orig.nraddr; \
2968 _argvec[1] = (unsigned long)(arg1); \
2969 _argvec[2] = (unsigned long)(arg2); \
2970 _argvec[3] = (unsigned long)(arg3); \
2971 _argvec[4] = (unsigned long)(arg4); \
2972 _argvec[5] = (unsigned long)(arg5); \
2973 _argvec[6] = (unsigned long)(arg6); \
2974 _argvec[7] = (unsigned long)(arg7); \
2976 "ldr r0, [%1, #20] \n\t" \
2977 "ldr r1, [%1, #24] \n\t" \
2978 "ldr r2, [%1, #28] \n\t" \
2979 "push {r0, r1, r2} \n\t" \
2980 "ldr r0, [%1, #4] \n\t" \
2981 "ldr r1, [%1, #8] \n\t" \
2982 "ldr r2, [%1, #12] \n\t" \
2983 "ldr r3, [%1, #16] \n\t" \
2984 "ldr r4, [%1] \n\t" /* target->r4 */ \
2985 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2986 "add sp, sp, #12 \n\t" \
2988 : /*out*/ "=r" (_res) \
2989 : /*in*/ "0" (&_argvec[0]) \
2990 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2992 lval = (__typeof__(lval)) _res; \
2995 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2998 volatile OrigFn _orig = (orig); \
2999 volatile unsigned long _argvec[9]; \
3000 volatile unsigned long _res; \
3001 _argvec[0] = (unsigned long)_orig.nraddr; \
3002 _argvec[1] = (unsigned long)(arg1); \
3003 _argvec[2] = (unsigned long)(arg2); \
3004 _argvec[3] = (unsigned long)(arg3); \
3005 _argvec[4] = (unsigned long)(arg4); \
3006 _argvec[5] = (unsigned long)(arg5); \
3007 _argvec[6] = (unsigned long)(arg6); \
3008 _argvec[7] = (unsigned long)(arg7); \
3009 _argvec[8] = (unsigned long)(arg8); \
3011 "ldr r0, [%1, #20] \n\t" \
3012 "ldr r1, [%1, #24] \n\t" \
3013 "ldr r2, [%1, #28] \n\t" \
3014 "ldr r3, [%1, #32] \n\t" \
3015 "push {r0, r1, r2, r3} \n\t" \
3016 "ldr r0, [%1, #4] \n\t" \
3017 "ldr r1, [%1, #8] \n\t" \
3018 "ldr r2, [%1, #12] \n\t" \
3019 "ldr r3, [%1, #16] \n\t" \
3020 "ldr r4, [%1] \n\t" /* target->r4 */ \
3021 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3022 "add sp, sp, #16 \n\t" \
3024 : /*out*/ "=r" (_res) \
3025 : /*in*/ "0" (&_argvec[0]) \
3026 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3028 lval = (__typeof__(lval)) _res; \
3031 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3034 volatile OrigFn _orig = (orig); \
3035 volatile unsigned long _argvec[10]; \
3036 volatile unsigned long _res; \
3037 _argvec[0] = (unsigned long)_orig.nraddr; \
3038 _argvec[1] = (unsigned long)(arg1); \
3039 _argvec[2] = (unsigned long)(arg2); \
3040 _argvec[3] = (unsigned long)(arg3); \
3041 _argvec[4] = (unsigned long)(arg4); \
3042 _argvec[5] = (unsigned long)(arg5); \
3043 _argvec[6] = (unsigned long)(arg6); \
3044 _argvec[7] = (unsigned long)(arg7); \
3045 _argvec[8] = (unsigned long)(arg8); \
3046 _argvec[9] = (unsigned long)(arg9); \
3048 "ldr r0, [%1, #20] \n\t" \
3049 "ldr r1, [%1, #24] \n\t" \
3050 "ldr r2, [%1, #28] \n\t" \
3051 "ldr r3, [%1, #32] \n\t" \
3052 "ldr r4, [%1, #36] \n\t" \
3053 "push {r0, r1, r2, r3, r4} \n\t" \
3054 "ldr r0, [%1, #4] \n\t" \
3055 "ldr r1, [%1, #8] \n\t" \
3056 "ldr r2, [%1, #12] \n\t" \
3057 "ldr r3, [%1, #16] \n\t" \
3058 "ldr r4, [%1] \n\t" /* target->r4 */ \
3059 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3060 "add sp, sp, #20 \n\t" \
3062 : /*out*/ "=r" (_res) \
3063 : /*in*/ "0" (&_argvec[0]) \
3064 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3066 lval = (__typeof__(lval)) _res; \
3069 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3070 arg7,arg8,arg9,arg10) \
3072 volatile OrigFn _orig = (orig); \
3073 volatile unsigned long _argvec[11]; \
3074 volatile unsigned long _res; \
3075 _argvec[0] = (unsigned long)_orig.nraddr; \
3076 _argvec[1] = (unsigned long)(arg1); \
3077 _argvec[2] = (unsigned long)(arg2); \
3078 _argvec[3] = (unsigned long)(arg3); \
3079 _argvec[4] = (unsigned long)(arg4); \
3080 _argvec[5] = (unsigned long)(arg5); \
3081 _argvec[6] = (unsigned long)(arg6); \
3082 _argvec[7] = (unsigned long)(arg7); \
3083 _argvec[8] = (unsigned long)(arg8); \
3084 _argvec[9] = (unsigned long)(arg9); \
3085 _argvec[10] = (unsigned long)(arg10); \
3087 "ldr r0, [%1, #40] \n\t" \
3089 "ldr r0, [%1, #20] \n\t" \
3090 "ldr r1, [%1, #24] \n\t" \
3091 "ldr r2, [%1, #28] \n\t" \
3092 "ldr r3, [%1, #32] \n\t" \
3093 "ldr r4, [%1, #36] \n\t" \
3094 "push {r0, r1, r2, r3, r4} \n\t" \
3095 "ldr r0, [%1, #4] \n\t" \
3096 "ldr r1, [%1, #8] \n\t" \
3097 "ldr r2, [%1, #12] \n\t" \
3098 "ldr r3, [%1, #16] \n\t" \
3099 "ldr r4, [%1] \n\t" /* target->r4 */ \
3100 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3101 "add sp, sp, #24 \n\t" \
3103 : /*out*/ "=r" (_res) \
3104 : /*in*/ "0" (&_argvec[0]) \
3105 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3107 lval = (__typeof__(lval)) _res; \
3110 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3111 arg6,arg7,arg8,arg9,arg10, \
3114 volatile OrigFn _orig = (orig); \
3115 volatile unsigned long _argvec[12]; \
3116 volatile unsigned long _res; \
3117 _argvec[0] = (unsigned long)_orig.nraddr; \
3118 _argvec[1] = (unsigned long)(arg1); \
3119 _argvec[2] = (unsigned long)(arg2); \
3120 _argvec[3] = (unsigned long)(arg3); \
3121 _argvec[4] = (unsigned long)(arg4); \
3122 _argvec[5] = (unsigned long)(arg5); \
3123 _argvec[6] = (unsigned long)(arg6); \
3124 _argvec[7] = (unsigned long)(arg7); \
3125 _argvec[8] = (unsigned long)(arg8); \
3126 _argvec[9] = (unsigned long)(arg9); \
3127 _argvec[10] = (unsigned long)(arg10); \
3128 _argvec[11] = (unsigned long)(arg11); \
3130 "ldr r0, [%1, #40] \n\t" \
3131 "ldr r1, [%1, #44] \n\t" \
3132 "push {r0, r1} \n\t" \
3133 "ldr r0, [%1, #20] \n\t" \
3134 "ldr r1, [%1, #24] \n\t" \
3135 "ldr r2, [%1, #28] \n\t" \
3136 "ldr r3, [%1, #32] \n\t" \
3137 "ldr r4, [%1, #36] \n\t" \
3138 "push {r0, r1, r2, r3, r4} \n\t" \
3139 "ldr r0, [%1, #4] \n\t" \
3140 "ldr r1, [%1, #8] \n\t" \
3141 "ldr r2, [%1, #12] \n\t" \
3142 "ldr r3, [%1, #16] \n\t" \
3143 "ldr r4, [%1] \n\t" /* target->r4 */ \
3144 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3145 "add sp, sp, #28 \n\t" \
3147 : /*out*/ "=r" (_res) \
3148 : /*in*/ "0" (&_argvec[0]) \
3149 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3151 lval = (__typeof__(lval)) _res; \
3154 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3155 arg6,arg7,arg8,arg9,arg10, \
3158 volatile OrigFn _orig = (orig); \
3159 volatile unsigned long _argvec[13]; \
3160 volatile unsigned long _res; \
3161 _argvec[0] = (unsigned long)_orig.nraddr; \
3162 _argvec[1] = (unsigned long)(arg1); \
3163 _argvec[2] = (unsigned long)(arg2); \
3164 _argvec[3] = (unsigned long)(arg3); \
3165 _argvec[4] = (unsigned long)(arg4); \
3166 _argvec[5] = (unsigned long)(arg5); \
3167 _argvec[6] = (unsigned long)(arg6); \
3168 _argvec[7] = (unsigned long)(arg7); \
3169 _argvec[8] = (unsigned long)(arg8); \
3170 _argvec[9] = (unsigned long)(arg9); \
3171 _argvec[10] = (unsigned long)(arg10); \
3172 _argvec[11] = (unsigned long)(arg11); \
3173 _argvec[12] = (unsigned long)(arg12); \
3175 "ldr r0, [%1, #40] \n\t" \
3176 "ldr r1, [%1, #44] \n\t" \
3177 "ldr r2, [%1, #48] \n\t" \
3178 "push {r0, r1, r2} \n\t" \
3179 "ldr r0, [%1, #20] \n\t" \
3180 "ldr r1, [%1, #24] \n\t" \
3181 "ldr r2, [%1, #28] \n\t" \
3182 "ldr r3, [%1, #32] \n\t" \
3183 "ldr r4, [%1, #36] \n\t" \
3184 "push {r0, r1, r2, r3, r4} \n\t" \
3185 "ldr r0, [%1, #4] \n\t" \
3186 "ldr r1, [%1, #8] \n\t" \
3187 "ldr r2, [%1, #12] \n\t" \
3188 "ldr r3, [%1, #16] \n\t" \
3189 "ldr r4, [%1] \n\t" /* target->r4 */ \
3190 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3191 "add sp, sp, #32 \n\t" \
3193 : /*out*/ "=r" (_res) \
3194 : /*in*/ "0" (&_argvec[0]) \
3195 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3197 lval = (__typeof__(lval)) _res; \
3200 #endif /* PLAT_arm_linux */
3202 /* ------------------------ ppc32-aix5 ------------------------- */
3204 #if defined(PLAT_ppc32_aix5)
3206 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3208 /* These regs are trashed by the hidden call. */
3209 #define __CALLER_SAVED_REGS \
3210 "lr", "ctr", "xer", \
3211 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3212 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3215 /* Expand the stack frame, copying enough info that unwinding
3216 still works. Trashes r3. */
3218 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3219 "addi 1,1,-" #_n_fr "\n\t" \
3220 "lwz 3," #_n_fr "(1)\n\t" \
3223 #define VG_CONTRACT_FRAME_BY(_n_fr) \
3224 "addi 1,1," #_n_fr "\n\t"
3226 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
3229 #define CALL_FN_W_v(lval, orig) \
3231 volatile OrigFn _orig = (orig); \
3232 volatile unsigned long _argvec[3+0]; \
3233 volatile unsigned long _res; \
3234 /* _argvec[0] holds current r2 across the call */ \
3235 _argvec[1] = (unsigned long)_orig.r2; \
3236 _argvec[2] = (unsigned long)_orig.nraddr; \
3239 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3240 "stw 2,-8(11)\n\t" /* save tocptr */ \
3241 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3242 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3243 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3246 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3247 VG_CONTRACT_FRAME_BY(512) \
3248 : /*out*/ "=r" (_res) \
3249 : /*in*/ "r" (&_argvec[2]) \
3250 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3252 lval = (__typeof__(lval)) _res; \
3255 #define CALL_FN_W_W(lval, orig, arg1) \
3257 volatile OrigFn _orig = (orig); \
3258 volatile unsigned long _argvec[3+1]; \
3259 volatile unsigned long _res; \
3260 /* _argvec[0] holds current r2 across the call */ \
3261 _argvec[1] = (unsigned long)_orig.r2; \
3262 _argvec[2] = (unsigned long)_orig.nraddr; \
3263 _argvec[2+1] = (unsigned long)arg1; \
3266 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3267 "stw 2,-8(11)\n\t" /* save tocptr */ \
3268 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3269 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3270 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3271 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3274 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3275 VG_CONTRACT_FRAME_BY(512) \
3276 : /*out*/ "=r" (_res) \
3277 : /*in*/ "r" (&_argvec[2]) \
3278 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3280 lval = (__typeof__(lval)) _res; \
3283 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3285 volatile OrigFn _orig = (orig); \
3286 volatile unsigned long _argvec[3+2]; \
3287 volatile unsigned long _res; \
3288 /* _argvec[0] holds current r2 across the call */ \
3289 _argvec[1] = (unsigned long)_orig.r2; \
3290 _argvec[2] = (unsigned long)_orig.nraddr; \
3291 _argvec[2+1] = (unsigned long)arg1; \
3292 _argvec[2+2] = (unsigned long)arg2; \
3295 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3296 "stw 2,-8(11)\n\t" /* save tocptr */ \
3297 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3298 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3299 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3300 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3301 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3304 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3305 VG_CONTRACT_FRAME_BY(512) \
3306 : /*out*/ "=r" (_res) \
3307 : /*in*/ "r" (&_argvec[2]) \
3308 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3310 lval = (__typeof__(lval)) _res; \
3313 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3315 volatile OrigFn _orig = (orig); \
3316 volatile unsigned long _argvec[3+3]; \
3317 volatile unsigned long _res; \
3318 /* _argvec[0] holds current r2 across the call */ \
3319 _argvec[1] = (unsigned long)_orig.r2; \
3320 _argvec[2] = (unsigned long)_orig.nraddr; \
3321 _argvec[2+1] = (unsigned long)arg1; \
3322 _argvec[2+2] = (unsigned long)arg2; \
3323 _argvec[2+3] = (unsigned long)arg3; \
3326 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3327 "stw 2,-8(11)\n\t" /* save tocptr */ \
3328 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3329 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3330 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3331 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3332 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3333 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3336 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3337 VG_CONTRACT_FRAME_BY(512) \
3338 : /*out*/ "=r" (_res) \
3339 : /*in*/ "r" (&_argvec[2]) \
3340 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3342 lval = (__typeof__(lval)) _res; \
3345 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3347 volatile OrigFn _orig = (orig); \
3348 volatile unsigned long _argvec[3+4]; \
3349 volatile unsigned long _res; \
3350 /* _argvec[0] holds current r2 across the call */ \
3351 _argvec[1] = (unsigned long)_orig.r2; \
3352 _argvec[2] = (unsigned long)_orig.nraddr; \
3353 _argvec[2+1] = (unsigned long)arg1; \
3354 _argvec[2+2] = (unsigned long)arg2; \
3355 _argvec[2+3] = (unsigned long)arg3; \
3356 _argvec[2+4] = (unsigned long)arg4; \
3359 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3360 "stw 2,-8(11)\n\t" /* save tocptr */ \
3361 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3362 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3363 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3364 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3365 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3366 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3367 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3370 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3371 VG_CONTRACT_FRAME_BY(512) \
3372 : /*out*/ "=r" (_res) \
3373 : /*in*/ "r" (&_argvec[2]) \
3374 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3376 lval = (__typeof__(lval)) _res; \
3379 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3381 volatile OrigFn _orig = (orig); \
3382 volatile unsigned long _argvec[3+5]; \
3383 volatile unsigned long _res; \
3384 /* _argvec[0] holds current r2 across the call */ \
3385 _argvec[1] = (unsigned long)_orig.r2; \
3386 _argvec[2] = (unsigned long)_orig.nraddr; \
3387 _argvec[2+1] = (unsigned long)arg1; \
3388 _argvec[2+2] = (unsigned long)arg2; \
3389 _argvec[2+3] = (unsigned long)arg3; \
3390 _argvec[2+4] = (unsigned long)arg4; \
3391 _argvec[2+5] = (unsigned long)arg5; \
3394 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3395 "stw 2,-8(11)\n\t" /* save tocptr */ \
3396 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3397 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3398 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3399 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3400 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3401 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3402 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3403 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3406 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3407 VG_CONTRACT_FRAME_BY(512) \
3408 : /*out*/ "=r" (_res) \
3409 : /*in*/ "r" (&_argvec[2]) \
3410 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3412 lval = (__typeof__(lval)) _res; \
3415 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3417 volatile OrigFn _orig = (orig); \
3418 volatile unsigned long _argvec[3+6]; \
3419 volatile unsigned long _res; \
3420 /* _argvec[0] holds current r2 across the call */ \
3421 _argvec[1] = (unsigned long)_orig.r2; \
3422 _argvec[2] = (unsigned long)_orig.nraddr; \
3423 _argvec[2+1] = (unsigned long)arg1; \
3424 _argvec[2+2] = (unsigned long)arg2; \
3425 _argvec[2+3] = (unsigned long)arg3; \
3426 _argvec[2+4] = (unsigned long)arg4; \
3427 _argvec[2+5] = (unsigned long)arg5; \
3428 _argvec[2+6] = (unsigned long)arg6; \
3431 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3432 "stw 2,-8(11)\n\t" /* save tocptr */ \
3433 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3434 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3435 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3436 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3437 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3438 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3439 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3440 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3441 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3444 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3445 VG_CONTRACT_FRAME_BY(512) \
3446 : /*out*/ "=r" (_res) \
3447 : /*in*/ "r" (&_argvec[2]) \
3448 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3450 lval = (__typeof__(lval)) _res; \
3453 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3456 volatile OrigFn _orig = (orig); \
3457 volatile unsigned long _argvec[3+7]; \
3458 volatile unsigned long _res; \
3459 /* _argvec[0] holds current r2 across the call */ \
3460 _argvec[1] = (unsigned long)_orig.r2; \
3461 _argvec[2] = (unsigned long)_orig.nraddr; \
3462 _argvec[2+1] = (unsigned long)arg1; \
3463 _argvec[2+2] = (unsigned long)arg2; \
3464 _argvec[2+3] = (unsigned long)arg3; \
3465 _argvec[2+4] = (unsigned long)arg4; \
3466 _argvec[2+5] = (unsigned long)arg5; \
3467 _argvec[2+6] = (unsigned long)arg6; \
3468 _argvec[2+7] = (unsigned long)arg7; \
3471 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3472 "stw 2,-8(11)\n\t" /* save tocptr */ \
3473 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3474 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3475 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3476 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3477 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3478 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3479 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3480 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3481 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3482 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3485 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3486 VG_CONTRACT_FRAME_BY(512) \
3487 : /*out*/ "=r" (_res) \
3488 : /*in*/ "r" (&_argvec[2]) \
3489 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3491 lval = (__typeof__(lval)) _res; \
3494 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3497 volatile OrigFn _orig = (orig); \
3498 volatile unsigned long _argvec[3+8]; \
3499 volatile unsigned long _res; \
3500 /* _argvec[0] holds current r2 across the call */ \
3501 _argvec[1] = (unsigned long)_orig.r2; \
3502 _argvec[2] = (unsigned long)_orig.nraddr; \
3503 _argvec[2+1] = (unsigned long)arg1; \
3504 _argvec[2+2] = (unsigned long)arg2; \
3505 _argvec[2+3] = (unsigned long)arg3; \
3506 _argvec[2+4] = (unsigned long)arg4; \
3507 _argvec[2+5] = (unsigned long)arg5; \
3508 _argvec[2+6] = (unsigned long)arg6; \
3509 _argvec[2+7] = (unsigned long)arg7; \
3510 _argvec[2+8] = (unsigned long)arg8; \
3513 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3514 "stw 2,-8(11)\n\t" /* save tocptr */ \
3515 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3516 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3517 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3518 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3519 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3520 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3521 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3522 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3523 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3524 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3525 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3528 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3529 VG_CONTRACT_FRAME_BY(512) \
3530 : /*out*/ "=r" (_res) \
3531 : /*in*/ "r" (&_argvec[2]) \
3532 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3534 lval = (__typeof__(lval)) _res; \
3537 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3540 volatile OrigFn _orig = (orig); \
3541 volatile unsigned long _argvec[3+9]; \
3542 volatile unsigned long _res; \
3543 /* _argvec[0] holds current r2 across the call */ \
3544 _argvec[1] = (unsigned long)_orig.r2; \
3545 _argvec[2] = (unsigned long)_orig.nraddr; \
3546 _argvec[2+1] = (unsigned long)arg1; \
3547 _argvec[2+2] = (unsigned long)arg2; \
3548 _argvec[2+3] = (unsigned long)arg3; \
3549 _argvec[2+4] = (unsigned long)arg4; \
3550 _argvec[2+5] = (unsigned long)arg5; \
3551 _argvec[2+6] = (unsigned long)arg6; \
3552 _argvec[2+7] = (unsigned long)arg7; \
3553 _argvec[2+8] = (unsigned long)arg8; \
3554 _argvec[2+9] = (unsigned long)arg9; \
3557 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3558 "stw 2,-8(11)\n\t" /* save tocptr */ \
3559 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3560 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3562 "lwz 3,36(11)\n\t" \
3565 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3566 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3567 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3568 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3569 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3570 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3571 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3572 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3573 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3574 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3577 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3578 VG_CONTRACT_FRAME_BY(64) \
3579 VG_CONTRACT_FRAME_BY(512) \
3580 : /*out*/ "=r" (_res) \
3581 : /*in*/ "r" (&_argvec[2]) \
3582 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3584 lval = (__typeof__(lval)) _res; \
3587 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3588 arg7,arg8,arg9,arg10) \
3590 volatile OrigFn _orig = (orig); \
3591 volatile unsigned long _argvec[3+10]; \
3592 volatile unsigned long _res; \
3593 /* _argvec[0] holds current r2 across the call */ \
3594 _argvec[1] = (unsigned long)_orig.r2; \
3595 _argvec[2] = (unsigned long)_orig.nraddr; \
3596 _argvec[2+1] = (unsigned long)arg1; \
3597 _argvec[2+2] = (unsigned long)arg2; \
3598 _argvec[2+3] = (unsigned long)arg3; \
3599 _argvec[2+4] = (unsigned long)arg4; \
3600 _argvec[2+5] = (unsigned long)arg5; \
3601 _argvec[2+6] = (unsigned long)arg6; \
3602 _argvec[2+7] = (unsigned long)arg7; \
3603 _argvec[2+8] = (unsigned long)arg8; \
3604 _argvec[2+9] = (unsigned long)arg9; \
3605 _argvec[2+10] = (unsigned long)arg10; \
3608 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3609 "stw 2,-8(11)\n\t" /* save tocptr */ \
3610 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3611 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3613 "lwz 3,40(11)\n\t" \
3616 "lwz 3,36(11)\n\t" \
3619 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3620 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3621 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3622 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3623 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3624 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3625 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3626 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3627 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3628 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3631 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3632 VG_CONTRACT_FRAME_BY(64) \
3633 VG_CONTRACT_FRAME_BY(512) \
3634 : /*out*/ "=r" (_res) \
3635 : /*in*/ "r" (&_argvec[2]) \
3636 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3638 lval = (__typeof__(lval)) _res; \
3641 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3642 arg7,arg8,arg9,arg10,arg11) \
3644 volatile OrigFn _orig = (orig); \
3645 volatile unsigned long _argvec[3+11]; \
3646 volatile unsigned long _res; \
3647 /* _argvec[0] holds current r2 across the call */ \
3648 _argvec[1] = (unsigned long)_orig.r2; \
3649 _argvec[2] = (unsigned long)_orig.nraddr; \
3650 _argvec[2+1] = (unsigned long)arg1; \
3651 _argvec[2+2] = (unsigned long)arg2; \
3652 _argvec[2+3] = (unsigned long)arg3; \
3653 _argvec[2+4] = (unsigned long)arg4; \
3654 _argvec[2+5] = (unsigned long)arg5; \
3655 _argvec[2+6] = (unsigned long)arg6; \
3656 _argvec[2+7] = (unsigned long)arg7; \
3657 _argvec[2+8] = (unsigned long)arg8; \
3658 _argvec[2+9] = (unsigned long)arg9; \
3659 _argvec[2+10] = (unsigned long)arg10; \
3660 _argvec[2+11] = (unsigned long)arg11; \
3663 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3664 "stw 2,-8(11)\n\t" /* save tocptr */ \
3665 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3666 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3668 "lwz 3,44(11)\n\t" \
3671 "lwz 3,40(11)\n\t" \
3674 "lwz 3,36(11)\n\t" \
3677 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3678 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3679 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3680 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3681 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3682 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3683 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3684 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3685 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3686 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3689 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3690 VG_CONTRACT_FRAME_BY(72) \
3691 VG_CONTRACT_FRAME_BY(512) \
3692 : /*out*/ "=r" (_res) \
3693 : /*in*/ "r" (&_argvec[2]) \
3694 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3696 lval = (__typeof__(lval)) _res; \
3699 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3700 arg7,arg8,arg9,arg10,arg11,arg12) \
3702 volatile OrigFn _orig = (orig); \
3703 volatile unsigned long _argvec[3+12]; \
3704 volatile unsigned long _res; \
3705 /* _argvec[0] holds current r2 across the call */ \
3706 _argvec[1] = (unsigned long)_orig.r2; \
3707 _argvec[2] = (unsigned long)_orig.nraddr; \
3708 _argvec[2+1] = (unsigned long)arg1; \
3709 _argvec[2+2] = (unsigned long)arg2; \
3710 _argvec[2+3] = (unsigned long)arg3; \
3711 _argvec[2+4] = (unsigned long)arg4; \
3712 _argvec[2+5] = (unsigned long)arg5; \
3713 _argvec[2+6] = (unsigned long)arg6; \
3714 _argvec[2+7] = (unsigned long)arg7; \
3715 _argvec[2+8] = (unsigned long)arg8; \
3716 _argvec[2+9] = (unsigned long)arg9; \
3717 _argvec[2+10] = (unsigned long)arg10; \
3718 _argvec[2+11] = (unsigned long)arg11; \
3719 _argvec[2+12] = (unsigned long)arg12; \
3722 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3723 "stw 2,-8(11)\n\t" /* save tocptr */ \
3724 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3725 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3727 "lwz 3,48(11)\n\t" \
3730 "lwz 3,44(11)\n\t" \
3733 "lwz 3,40(11)\n\t" \
3736 "lwz 3,36(11)\n\t" \
3739 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3740 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3741 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3742 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3743 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3744 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3745 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3746 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3747 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3748 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3751 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3752 VG_CONTRACT_FRAME_BY(72) \
3753 VG_CONTRACT_FRAME_BY(512) \
3754 : /*out*/ "=r" (_res) \
3755 : /*in*/ "r" (&_argvec[2]) \
3756 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3758 lval = (__typeof__(lval)) _res; \
3761 #endif /* PLAT_ppc32_aix5 */
3763 /* ------------------------ ppc64-aix5 ------------------------- */
3765 #if defined(PLAT_ppc64_aix5)
3767 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3769 /* These regs are trashed by the hidden call. */
3770 #define __CALLER_SAVED_REGS \
3771 "lr", "ctr", "xer", \
3772 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3773 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3776 /* Expand the stack frame, copying enough info that unwinding
3777 still works. Trashes r3. */
3779 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3780 "addi 1,1,-" #_n_fr "\n\t" \
3781 "ld 3," #_n_fr "(1)\n\t" \
3784 #define VG_CONTRACT_FRAME_BY(_n_fr) \
3785 "addi 1,1," #_n_fr "\n\t"
3787 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3790 #define CALL_FN_W_v(lval, orig) \
3792 volatile OrigFn _orig = (orig); \
3793 volatile unsigned long _argvec[3+0]; \
3794 volatile unsigned long _res; \
3795 /* _argvec[0] holds current r2 across the call */ \
3796 _argvec[1] = (unsigned long)_orig.r2; \
3797 _argvec[2] = (unsigned long)_orig.nraddr; \
3800 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3801 "std 2,-16(11)\n\t" /* save tocptr */ \
3802 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3803 "ld 11, 0(11)\n\t" /* target->r11 */ \
3804 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3807 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3808 VG_CONTRACT_FRAME_BY(512) \
3809 : /*out*/ "=r" (_res) \
3810 : /*in*/ "r" (&_argvec[2]) \
3811 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3813 lval = (__typeof__(lval)) _res; \
3816 #define CALL_FN_W_W(lval, orig, arg1) \
3818 volatile OrigFn _orig = (orig); \
3819 volatile unsigned long _argvec[3+1]; \
3820 volatile unsigned long _res; \
3821 /* _argvec[0] holds current r2 across the call */ \
3822 _argvec[1] = (unsigned long)_orig.r2; \
3823 _argvec[2] = (unsigned long)_orig.nraddr; \
3824 _argvec[2+1] = (unsigned long)arg1; \
3827 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3828 "std 2,-16(11)\n\t" /* save tocptr */ \
3829 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3830 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3831 "ld 11, 0(11)\n\t" /* target->r11 */ \
3832 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3835 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3836 VG_CONTRACT_FRAME_BY(512) \
3837 : /*out*/ "=r" (_res) \
3838 : /*in*/ "r" (&_argvec[2]) \
3839 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3841 lval = (__typeof__(lval)) _res; \
3844 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3846 volatile OrigFn _orig = (orig); \
3847 volatile unsigned long _argvec[3+2]; \
3848 volatile unsigned long _res; \
3849 /* _argvec[0] holds current r2 across the call */ \
3850 _argvec[1] = (unsigned long)_orig.r2; \
3851 _argvec[2] = (unsigned long)_orig.nraddr; \
3852 _argvec[2+1] = (unsigned long)arg1; \
3853 _argvec[2+2] = (unsigned long)arg2; \
3856 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3857 "std 2,-16(11)\n\t" /* save tocptr */ \
3858 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3859 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3860 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3861 "ld 11, 0(11)\n\t" /* target->r11 */ \
3862 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3865 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3866 VG_CONTRACT_FRAME_BY(512) \
3867 : /*out*/ "=r" (_res) \
3868 : /*in*/ "r" (&_argvec[2]) \
3869 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3871 lval = (__typeof__(lval)) _res; \
3874 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3876 volatile OrigFn _orig = (orig); \
3877 volatile unsigned long _argvec[3+3]; \
3878 volatile unsigned long _res; \
3879 /* _argvec[0] holds current r2 across the call */ \
3880 _argvec[1] = (unsigned long)_orig.r2; \
3881 _argvec[2] = (unsigned long)_orig.nraddr; \
3882 _argvec[2+1] = (unsigned long)arg1; \
3883 _argvec[2+2] = (unsigned long)arg2; \
3884 _argvec[2+3] = (unsigned long)arg3; \
3887 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3888 "std 2,-16(11)\n\t" /* save tocptr */ \
3889 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3890 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3891 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3892 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3893 "ld 11, 0(11)\n\t" /* target->r11 */ \
3894 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3897 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3898 VG_CONTRACT_FRAME_BY(512) \
3899 : /*out*/ "=r" (_res) \
3900 : /*in*/ "r" (&_argvec[2]) \
3901 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3903 lval = (__typeof__(lval)) _res; \
3906 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3908 volatile OrigFn _orig = (orig); \
3909 volatile unsigned long _argvec[3+4]; \
3910 volatile unsigned long _res; \
3911 /* _argvec[0] holds current r2 across the call */ \
3912 _argvec[1] = (unsigned long)_orig.r2; \
3913 _argvec[2] = (unsigned long)_orig.nraddr; \
3914 _argvec[2+1] = (unsigned long)arg1; \
3915 _argvec[2+2] = (unsigned long)arg2; \
3916 _argvec[2+3] = (unsigned long)arg3; \
3917 _argvec[2+4] = (unsigned long)arg4; \
3920 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3921 "std 2,-16(11)\n\t" /* save tocptr */ \
3922 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3923 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3924 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3925 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3926 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3927 "ld 11, 0(11)\n\t" /* target->r11 */ \
3928 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3931 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3932 VG_CONTRACT_FRAME_BY(512) \
3933 : /*out*/ "=r" (_res) \
3934 : /*in*/ "r" (&_argvec[2]) \
3935 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3937 lval = (__typeof__(lval)) _res; \
3940 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3942 volatile OrigFn _orig = (orig); \
3943 volatile unsigned long _argvec[3+5]; \
3944 volatile unsigned long _res; \
3945 /* _argvec[0] holds current r2 across the call */ \
3946 _argvec[1] = (unsigned long)_orig.r2; \
3947 _argvec[2] = (unsigned long)_orig.nraddr; \
3948 _argvec[2+1] = (unsigned long)arg1; \
3949 _argvec[2+2] = (unsigned long)arg2; \
3950 _argvec[2+3] = (unsigned long)arg3; \
3951 _argvec[2+4] = (unsigned long)arg4; \
3952 _argvec[2+5] = (unsigned long)arg5; \
3955 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3956 "std 2,-16(11)\n\t" /* save tocptr */ \
3957 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3958 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3959 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3960 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3961 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3962 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3963 "ld 11, 0(11)\n\t" /* target->r11 */ \
3964 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3967 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3968 VG_CONTRACT_FRAME_BY(512) \
3969 : /*out*/ "=r" (_res) \
3970 : /*in*/ "r" (&_argvec[2]) \
3971 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3973 lval = (__typeof__(lval)) _res; \
3976 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3978 volatile OrigFn _orig = (orig); \
3979 volatile unsigned long _argvec[3+6]; \
3980 volatile unsigned long _res; \
3981 /* _argvec[0] holds current r2 across the call */ \
3982 _argvec[1] = (unsigned long)_orig.r2; \
3983 _argvec[2] = (unsigned long)_orig.nraddr; \
3984 _argvec[2+1] = (unsigned long)arg1; \
3985 _argvec[2+2] = (unsigned long)arg2; \
3986 _argvec[2+3] = (unsigned long)arg3; \
3987 _argvec[2+4] = (unsigned long)arg4; \
3988 _argvec[2+5] = (unsigned long)arg5; \
3989 _argvec[2+6] = (unsigned long)arg6; \
3992 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3993 "std 2,-16(11)\n\t" /* save tocptr */ \
3994 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3995 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3996 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3997 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3998 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3999 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4000 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4001 "ld 11, 0(11)\n\t" /* target->r11 */ \
4002 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4005 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4006 VG_CONTRACT_FRAME_BY(512) \
4007 : /*out*/ "=r" (_res) \
4008 : /*in*/ "r" (&_argvec[2]) \
4009 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4011 lval = (__typeof__(lval)) _res; \
4014 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4017 volatile OrigFn _orig = (orig); \
4018 volatile unsigned long _argvec[3+7]; \
4019 volatile unsigned long _res; \
4020 /* _argvec[0] holds current r2 across the call */ \
4021 _argvec[1] = (unsigned long)_orig.r2; \
4022 _argvec[2] = (unsigned long)_orig.nraddr; \
4023 _argvec[2+1] = (unsigned long)arg1; \
4024 _argvec[2+2] = (unsigned long)arg2; \
4025 _argvec[2+3] = (unsigned long)arg3; \
4026 _argvec[2+4] = (unsigned long)arg4; \
4027 _argvec[2+5] = (unsigned long)arg5; \
4028 _argvec[2+6] = (unsigned long)arg6; \
4029 _argvec[2+7] = (unsigned long)arg7; \
4032 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4033 "std 2,-16(11)\n\t" /* save tocptr */ \
4034 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4035 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4036 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4037 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4038 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4039 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4040 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4041 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4042 "ld 11, 0(11)\n\t" /* target->r11 */ \
4043 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4046 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4047 VG_CONTRACT_FRAME_BY(512) \
4048 : /*out*/ "=r" (_res) \
4049 : /*in*/ "r" (&_argvec[2]) \
4050 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4052 lval = (__typeof__(lval)) _res; \
4055 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4058 volatile OrigFn _orig = (orig); \
4059 volatile unsigned long _argvec[3+8]; \
4060 volatile unsigned long _res; \
4061 /* _argvec[0] holds current r2 across the call */ \
4062 _argvec[1] = (unsigned long)_orig.r2; \
4063 _argvec[2] = (unsigned long)_orig.nraddr; \
4064 _argvec[2+1] = (unsigned long)arg1; \
4065 _argvec[2+2] = (unsigned long)arg2; \
4066 _argvec[2+3] = (unsigned long)arg3; \
4067 _argvec[2+4] = (unsigned long)arg4; \
4068 _argvec[2+5] = (unsigned long)arg5; \
4069 _argvec[2+6] = (unsigned long)arg6; \
4070 _argvec[2+7] = (unsigned long)arg7; \
4071 _argvec[2+8] = (unsigned long)arg8; \
4074 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4075 "std 2,-16(11)\n\t" /* save tocptr */ \
4076 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4077 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4078 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4079 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4080 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4081 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4082 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4083 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4084 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4085 "ld 11, 0(11)\n\t" /* target->r11 */ \
4086 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4089 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4090 VG_CONTRACT_FRAME_BY(512) \
4091 : /*out*/ "=r" (_res) \
4092 : /*in*/ "r" (&_argvec[2]) \
4093 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4095 lval = (__typeof__(lval)) _res; \
4098 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4101 volatile OrigFn _orig = (orig); \
4102 volatile unsigned long _argvec[3+9]; \
4103 volatile unsigned long _res; \
4104 /* _argvec[0] holds current r2 across the call */ \
4105 _argvec[1] = (unsigned long)_orig.r2; \
4106 _argvec[2] = (unsigned long)_orig.nraddr; \
4107 _argvec[2+1] = (unsigned long)arg1; \
4108 _argvec[2+2] = (unsigned long)arg2; \
4109 _argvec[2+3] = (unsigned long)arg3; \
4110 _argvec[2+4] = (unsigned long)arg4; \
4111 _argvec[2+5] = (unsigned long)arg5; \
4112 _argvec[2+6] = (unsigned long)arg6; \
4113 _argvec[2+7] = (unsigned long)arg7; \
4114 _argvec[2+8] = (unsigned long)arg8; \
4115 _argvec[2+9] = (unsigned long)arg9; \
4118 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4119 "std 2,-16(11)\n\t" /* save tocptr */ \
4120 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4121 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4124 "std 3,112(1)\n\t" \
4126 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4127 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4128 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4129 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4130 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4131 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4132 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4133 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4134 "ld 11, 0(11)\n\t" /* target->r11 */ \
4135 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4138 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4139 VG_CONTRACT_FRAME_BY(128) \
4140 VG_CONTRACT_FRAME_BY(512) \
4141 : /*out*/ "=r" (_res) \
4142 : /*in*/ "r" (&_argvec[2]) \
4143 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4145 lval = (__typeof__(lval)) _res; \
4148 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4149 arg7,arg8,arg9,arg10) \
4151 volatile OrigFn _orig = (orig); \
4152 volatile unsigned long _argvec[3+10]; \
4153 volatile unsigned long _res; \
4154 /* _argvec[0] holds current r2 across the call */ \
4155 _argvec[1] = (unsigned long)_orig.r2; \
4156 _argvec[2] = (unsigned long)_orig.nraddr; \
4157 _argvec[2+1] = (unsigned long)arg1; \
4158 _argvec[2+2] = (unsigned long)arg2; \
4159 _argvec[2+3] = (unsigned long)arg3; \
4160 _argvec[2+4] = (unsigned long)arg4; \
4161 _argvec[2+5] = (unsigned long)arg5; \
4162 _argvec[2+6] = (unsigned long)arg6; \
4163 _argvec[2+7] = (unsigned long)arg7; \
4164 _argvec[2+8] = (unsigned long)arg8; \
4165 _argvec[2+9] = (unsigned long)arg9; \
4166 _argvec[2+10] = (unsigned long)arg10; \
4169 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4170 "std 2,-16(11)\n\t" /* save tocptr */ \
4171 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4172 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4175 "std 3,120(1)\n\t" \
4178 "std 3,112(1)\n\t" \
4180 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4181 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4182 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4183 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4184 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4185 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4186 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4187 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4188 "ld 11, 0(11)\n\t" /* target->r11 */ \
4189 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4192 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4193 VG_CONTRACT_FRAME_BY(128) \
4194 VG_CONTRACT_FRAME_BY(512) \
4195 : /*out*/ "=r" (_res) \
4196 : /*in*/ "r" (&_argvec[2]) \
4197 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4199 lval = (__typeof__(lval)) _res; \
4202 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4203 arg7,arg8,arg9,arg10,arg11) \
4205 volatile OrigFn _orig = (orig); \
4206 volatile unsigned long _argvec[3+11]; \
4207 volatile unsigned long _res; \
4208 /* _argvec[0] holds current r2 across the call */ \
4209 _argvec[1] = (unsigned long)_orig.r2; \
4210 _argvec[2] = (unsigned long)_orig.nraddr; \
4211 _argvec[2+1] = (unsigned long)arg1; \
4212 _argvec[2+2] = (unsigned long)arg2; \
4213 _argvec[2+3] = (unsigned long)arg3; \
4214 _argvec[2+4] = (unsigned long)arg4; \
4215 _argvec[2+5] = (unsigned long)arg5; \
4216 _argvec[2+6] = (unsigned long)arg6; \
4217 _argvec[2+7] = (unsigned long)arg7; \
4218 _argvec[2+8] = (unsigned long)arg8; \
4219 _argvec[2+9] = (unsigned long)arg9; \
4220 _argvec[2+10] = (unsigned long)arg10; \
4221 _argvec[2+11] = (unsigned long)arg11; \
4224 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4225 "std 2,-16(11)\n\t" /* save tocptr */ \
4226 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4227 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4230 "std 3,128(1)\n\t" \
4233 "std 3,120(1)\n\t" \
4236 "std 3,112(1)\n\t" \
4238 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4239 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4240 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4241 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4242 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4243 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4244 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4245 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4246 "ld 11, 0(11)\n\t" /* target->r11 */ \
4247 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4250 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4251 VG_CONTRACT_FRAME_BY(144) \
4252 VG_CONTRACT_FRAME_BY(512) \
4253 : /*out*/ "=r" (_res) \
4254 : /*in*/ "r" (&_argvec[2]) \
4255 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4257 lval = (__typeof__(lval)) _res; \
4260 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4261 arg7,arg8,arg9,arg10,arg11,arg12) \
4263 volatile OrigFn _orig = (orig); \
4264 volatile unsigned long _argvec[3+12]; \
4265 volatile unsigned long _res; \
4266 /* _argvec[0] holds current r2 across the call */ \
4267 _argvec[1] = (unsigned long)_orig.r2; \
4268 _argvec[2] = (unsigned long)_orig.nraddr; \
4269 _argvec[2+1] = (unsigned long)arg1; \
4270 _argvec[2+2] = (unsigned long)arg2; \
4271 _argvec[2+3] = (unsigned long)arg3; \
4272 _argvec[2+4] = (unsigned long)arg4; \
4273 _argvec[2+5] = (unsigned long)arg5; \
4274 _argvec[2+6] = (unsigned long)arg6; \
4275 _argvec[2+7] = (unsigned long)arg7; \
4276 _argvec[2+8] = (unsigned long)arg8; \
4277 _argvec[2+9] = (unsigned long)arg9; \
4278 _argvec[2+10] = (unsigned long)arg10; \
4279 _argvec[2+11] = (unsigned long)arg11; \
4280 _argvec[2+12] = (unsigned long)arg12; \
4283 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4284 "std 2,-16(11)\n\t" /* save tocptr */ \
4285 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4286 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4289 "std 3,136(1)\n\t" \
4292 "std 3,128(1)\n\t" \
4295 "std 3,120(1)\n\t" \
4298 "std 3,112(1)\n\t" \
4300 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4301 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4302 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4303 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4304 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4305 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4306 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4307 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4308 "ld 11, 0(11)\n\t" /* target->r11 */ \
4309 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4312 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4313 VG_CONTRACT_FRAME_BY(144) \
4314 VG_CONTRACT_FRAME_BY(512) \
4315 : /*out*/ "=r" (_res) \
4316 : /*in*/ "r" (&_argvec[2]) \
4317 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4319 lval = (__typeof__(lval)) _res; \
4322 #endif /* PLAT_ppc64_aix5 */
4324 /* ------------------------- s390x-linux ------------------------- */
4326 #if defined(PLAT_s390x_linux)
4328 /* Similar craziness as x86 (see above), but we use r11 as frame
4329 pointer and save the old r11 in r7. r11 might be used for
4330 argvec, therefore we copy argvec in r1 since r1 is clobbered
4331 after the call anyway. */
4332 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4333 # define __FRAME_POINTER \
4334 ,"d"(__builtin_dwarf_cfa())
4335 # define VALGRIND_CFI_PROLOGUE \
4336 ".cfi_remember_state\n\t" \
4337 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
4340 ".cfi_def_cfa r11, 0\n\t"
4341 # define VALGRIND_CFI_EPILOGUE \
4343 ".cfi_restore_state\n\t"
4345 # define __FRAME_POINTER
4346 # define VALGRIND_CFI_PROLOGUE \
4348 # define VALGRIND_CFI_EPILOGUE
4354 /* These regs are trashed by the hidden call. Note that we overwrite
4355 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4356 function a proper return address. All others are ABI defined call
4358 #define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4359 "f0","f1","f2","f3","f4","f5","f6","f7"
4362 #define CALL_FN_W_v(lval, orig) \
4364 volatile OrigFn _orig = (orig); \
4365 volatile unsigned long _argvec[1]; \
4366 volatile unsigned long _res; \
4367 _argvec[0] = (unsigned long)_orig.nraddr; \
4369 VALGRIND_CFI_PROLOGUE \
4370 "aghi 15,-160\n\t" \
4371 "lg 1, 0(1)\n\t" /* target->r1 */ \
4372 VALGRIND_CALL_NOREDIR_R1 \
4375 VALGRIND_CFI_EPILOGUE \
4376 : /*out*/ "=d" (_res) \
4377 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
4378 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4380 lval = (__typeof__(lval)) _res; \
4383 /* The call abi has the arguments in r2-r6 and stack */
4384 #define CALL_FN_W_W(lval, orig, arg1) \
4386 volatile OrigFn _orig = (orig); \
4387 volatile unsigned long _argvec[2]; \
4388 volatile unsigned long _res; \
4389 _argvec[0] = (unsigned long)_orig.nraddr; \
4390 _argvec[1] = (unsigned long)arg1; \
4392 VALGRIND_CFI_PROLOGUE \
4393 "aghi 15,-160\n\t" \
4396 VALGRIND_CALL_NOREDIR_R1 \
4399 VALGRIND_CFI_EPILOGUE \
4400 : /*out*/ "=d" (_res) \
4401 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4402 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4404 lval = (__typeof__(lval)) _res; \
4407 #define CALL_FN_W_WW(lval, orig, arg1, arg2) \
4409 volatile OrigFn _orig = (orig); \
4410 volatile unsigned long _argvec[3]; \
4411 volatile unsigned long _res; \
4412 _argvec[0] = (unsigned long)_orig.nraddr; \
4413 _argvec[1] = (unsigned long)arg1; \
4414 _argvec[2] = (unsigned long)arg2; \
4416 VALGRIND_CFI_PROLOGUE \
4417 "aghi 15,-160\n\t" \
4421 VALGRIND_CALL_NOREDIR_R1 \
4424 VALGRIND_CFI_EPILOGUE \
4425 : /*out*/ "=d" (_res) \
4426 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4427 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4429 lval = (__typeof__(lval)) _res; \
4432 #define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
4434 volatile OrigFn _orig = (orig); \
4435 volatile unsigned long _argvec[4]; \
4436 volatile unsigned long _res; \
4437 _argvec[0] = (unsigned long)_orig.nraddr; \
4438 _argvec[1] = (unsigned long)arg1; \
4439 _argvec[2] = (unsigned long)arg2; \
4440 _argvec[3] = (unsigned long)arg3; \
4442 VALGRIND_CFI_PROLOGUE \
4443 "aghi 15,-160\n\t" \
4448 VALGRIND_CALL_NOREDIR_R1 \
4451 VALGRIND_CFI_EPILOGUE \
4452 : /*out*/ "=d" (_res) \
4453 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4454 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4456 lval = (__typeof__(lval)) _res; \
4459 #define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
4461 volatile OrigFn _orig = (orig); \
4462 volatile unsigned long _argvec[5]; \
4463 volatile unsigned long _res; \
4464 _argvec[0] = (unsigned long)_orig.nraddr; \
4465 _argvec[1] = (unsigned long)arg1; \
4466 _argvec[2] = (unsigned long)arg2; \
4467 _argvec[3] = (unsigned long)arg3; \
4468 _argvec[4] = (unsigned long)arg4; \
4470 VALGRIND_CFI_PROLOGUE \
4471 "aghi 15,-160\n\t" \
4477 VALGRIND_CALL_NOREDIR_R1 \
4480 VALGRIND_CFI_EPILOGUE \
4481 : /*out*/ "=d" (_res) \
4482 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4483 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4485 lval = (__typeof__(lval)) _res; \
4488 #define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
4490 volatile OrigFn _orig = (orig); \
4491 volatile unsigned long _argvec[6]; \
4492 volatile unsigned long _res; \
4493 _argvec[0] = (unsigned long)_orig.nraddr; \
4494 _argvec[1] = (unsigned long)arg1; \
4495 _argvec[2] = (unsigned long)arg2; \
4496 _argvec[3] = (unsigned long)arg3; \
4497 _argvec[4] = (unsigned long)arg4; \
4498 _argvec[5] = (unsigned long)arg5; \
4500 VALGRIND_CFI_PROLOGUE \
4501 "aghi 15,-160\n\t" \
4508 VALGRIND_CALL_NOREDIR_R1 \
4511 VALGRIND_CFI_EPILOGUE \
4512 : /*out*/ "=d" (_res) \
4513 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4514 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4516 lval = (__typeof__(lval)) _res; \
4519 #define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4522 volatile OrigFn _orig = (orig); \
4523 volatile unsigned long _argvec[7]; \
4524 volatile unsigned long _res; \
4525 _argvec[0] = (unsigned long)_orig.nraddr; \
4526 _argvec[1] = (unsigned long)arg1; \
4527 _argvec[2] = (unsigned long)arg2; \
4528 _argvec[3] = (unsigned long)arg3; \
4529 _argvec[4] = (unsigned long)arg4; \
4530 _argvec[5] = (unsigned long)arg5; \
4531 _argvec[6] = (unsigned long)arg6; \
4533 VALGRIND_CFI_PROLOGUE \
4534 "aghi 15,-168\n\t" \
4540 "mvc 160(8,15), 48(1)\n\t" \
4542 VALGRIND_CALL_NOREDIR_R1 \
4545 VALGRIND_CFI_EPILOGUE \
4546 : /*out*/ "=d" (_res) \
4547 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4548 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4550 lval = (__typeof__(lval)) _res; \
4553 #define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4556 volatile OrigFn _orig = (orig); \
4557 volatile unsigned long _argvec[8]; \
4558 volatile unsigned long _res; \
4559 _argvec[0] = (unsigned long)_orig.nraddr; \
4560 _argvec[1] = (unsigned long)arg1; \
4561 _argvec[2] = (unsigned long)arg2; \
4562 _argvec[3] = (unsigned long)arg3; \
4563 _argvec[4] = (unsigned long)arg4; \
4564 _argvec[5] = (unsigned long)arg5; \
4565 _argvec[6] = (unsigned long)arg6; \
4566 _argvec[7] = (unsigned long)arg7; \
4568 VALGRIND_CFI_PROLOGUE \
4569 "aghi 15,-176\n\t" \
4575 "mvc 160(8,15), 48(1)\n\t" \
4576 "mvc 168(8,15), 56(1)\n\t" \
4578 VALGRIND_CALL_NOREDIR_R1 \
4581 VALGRIND_CFI_EPILOGUE \
4582 : /*out*/ "=d" (_res) \
4583 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4584 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4586 lval = (__typeof__(lval)) _res; \
4589 #define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4592 volatile OrigFn _orig = (orig); \
4593 volatile unsigned long _argvec[9]; \
4594 volatile unsigned long _res; \
4595 _argvec[0] = (unsigned long)_orig.nraddr; \
4596 _argvec[1] = (unsigned long)arg1; \
4597 _argvec[2] = (unsigned long)arg2; \
4598 _argvec[3] = (unsigned long)arg3; \
4599 _argvec[4] = (unsigned long)arg4; \
4600 _argvec[5] = (unsigned long)arg5; \
4601 _argvec[6] = (unsigned long)arg6; \
4602 _argvec[7] = (unsigned long)arg7; \
4603 _argvec[8] = (unsigned long)arg8; \
4605 VALGRIND_CFI_PROLOGUE \
4606 "aghi 15,-184\n\t" \
4612 "mvc 160(8,15), 48(1)\n\t" \
4613 "mvc 168(8,15), 56(1)\n\t" \
4614 "mvc 176(8,15), 64(1)\n\t" \
4616 VALGRIND_CALL_NOREDIR_R1 \
4619 VALGRIND_CFI_EPILOGUE \
4620 : /*out*/ "=d" (_res) \
4621 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4622 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4624 lval = (__typeof__(lval)) _res; \
4627 #define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4628 arg6, arg7 ,arg8, arg9) \
4630 volatile OrigFn _orig = (orig); \
4631 volatile unsigned long _argvec[10]; \
4632 volatile unsigned long _res; \
4633 _argvec[0] = (unsigned long)_orig.nraddr; \
4634 _argvec[1] = (unsigned long)arg1; \
4635 _argvec[2] = (unsigned long)arg2; \
4636 _argvec[3] = (unsigned long)arg3; \
4637 _argvec[4] = (unsigned long)arg4; \
4638 _argvec[5] = (unsigned long)arg5; \
4639 _argvec[6] = (unsigned long)arg6; \
4640 _argvec[7] = (unsigned long)arg7; \
4641 _argvec[8] = (unsigned long)arg8; \
4642 _argvec[9] = (unsigned long)arg9; \
4644 VALGRIND_CFI_PROLOGUE \
4645 "aghi 15,-192\n\t" \
4651 "mvc 160(8,15), 48(1)\n\t" \
4652 "mvc 168(8,15), 56(1)\n\t" \
4653 "mvc 176(8,15), 64(1)\n\t" \
4654 "mvc 184(8,15), 72(1)\n\t" \
4656 VALGRIND_CALL_NOREDIR_R1 \
4659 VALGRIND_CFI_EPILOGUE \
4660 : /*out*/ "=d" (_res) \
4661 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4662 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4664 lval = (__typeof__(lval)) _res; \
4667 #define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4668 arg6, arg7 ,arg8, arg9, arg10) \
4670 volatile OrigFn _orig = (orig); \
4671 volatile unsigned long _argvec[11]; \
4672 volatile unsigned long _res; \
4673 _argvec[0] = (unsigned long)_orig.nraddr; \
4674 _argvec[1] = (unsigned long)arg1; \
4675 _argvec[2] = (unsigned long)arg2; \
4676 _argvec[3] = (unsigned long)arg3; \
4677 _argvec[4] = (unsigned long)arg4; \
4678 _argvec[5] = (unsigned long)arg5; \
4679 _argvec[6] = (unsigned long)arg6; \
4680 _argvec[7] = (unsigned long)arg7; \
4681 _argvec[8] = (unsigned long)arg8; \
4682 _argvec[9] = (unsigned long)arg9; \
4683 _argvec[10] = (unsigned long)arg10; \
4685 VALGRIND_CFI_PROLOGUE \
4686 "aghi 15,-200\n\t" \
4692 "mvc 160(8,15), 48(1)\n\t" \
4693 "mvc 168(8,15), 56(1)\n\t" \
4694 "mvc 176(8,15), 64(1)\n\t" \
4695 "mvc 184(8,15), 72(1)\n\t" \
4696 "mvc 192(8,15), 80(1)\n\t" \
4698 VALGRIND_CALL_NOREDIR_R1 \
4701 VALGRIND_CFI_EPILOGUE \
4702 : /*out*/ "=d" (_res) \
4703 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4704 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4706 lval = (__typeof__(lval)) _res; \
4709 #define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4710 arg6, arg7 ,arg8, arg9, arg10, arg11) \
4712 volatile OrigFn _orig = (orig); \
4713 volatile unsigned long _argvec[12]; \
4714 volatile unsigned long _res; \
4715 _argvec[0] = (unsigned long)_orig.nraddr; \
4716 _argvec[1] = (unsigned long)arg1; \
4717 _argvec[2] = (unsigned long)arg2; \
4718 _argvec[3] = (unsigned long)arg3; \
4719 _argvec[4] = (unsigned long)arg4; \
4720 _argvec[5] = (unsigned long)arg5; \
4721 _argvec[6] = (unsigned long)arg6; \
4722 _argvec[7] = (unsigned long)arg7; \
4723 _argvec[8] = (unsigned long)arg8; \
4724 _argvec[9] = (unsigned long)arg9; \
4725 _argvec[10] = (unsigned long)arg10; \
4726 _argvec[11] = (unsigned long)arg11; \
4728 VALGRIND_CFI_PROLOGUE \
4729 "aghi 15,-208\n\t" \
4735 "mvc 160(8,15), 48(1)\n\t" \
4736 "mvc 168(8,15), 56(1)\n\t" \
4737 "mvc 176(8,15), 64(1)\n\t" \
4738 "mvc 184(8,15), 72(1)\n\t" \
4739 "mvc 192(8,15), 80(1)\n\t" \
4740 "mvc 200(8,15), 88(1)\n\t" \
4742 VALGRIND_CALL_NOREDIR_R1 \
4745 VALGRIND_CFI_EPILOGUE \
4746 : /*out*/ "=d" (_res) \
4747 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4750 lval = (__typeof__(lval)) _res; \
4753 #define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4754 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
4756 volatile OrigFn _orig = (orig); \
4757 volatile unsigned long _argvec[13]; \
4758 volatile unsigned long _res; \
4759 _argvec[0] = (unsigned long)_orig.nraddr; \
4760 _argvec[1] = (unsigned long)arg1; \
4761 _argvec[2] = (unsigned long)arg2; \
4762 _argvec[3] = (unsigned long)arg3; \
4763 _argvec[4] = (unsigned long)arg4; \
4764 _argvec[5] = (unsigned long)arg5; \
4765 _argvec[6] = (unsigned long)arg6; \
4766 _argvec[7] = (unsigned long)arg7; \
4767 _argvec[8] = (unsigned long)arg8; \
4768 _argvec[9] = (unsigned long)arg9; \
4769 _argvec[10] = (unsigned long)arg10; \
4770 _argvec[11] = (unsigned long)arg11; \
4771 _argvec[12] = (unsigned long)arg12; \
4773 VALGRIND_CFI_PROLOGUE \
4774 "aghi 15,-216\n\t" \
4780 "mvc 160(8,15), 48(1)\n\t" \
4781 "mvc 168(8,15), 56(1)\n\t" \
4782 "mvc 176(8,15), 64(1)\n\t" \
4783 "mvc 184(8,15), 72(1)\n\t" \
4784 "mvc 192(8,15), 80(1)\n\t" \
4785 "mvc 200(8,15), 88(1)\n\t" \
4786 "mvc 208(8,15), 96(1)\n\t" \
4788 VALGRIND_CALL_NOREDIR_R1 \
4791 VALGRIND_CFI_EPILOGUE \
4792 : /*out*/ "=d" (_res) \
4793 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4794 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4796 lval = (__typeof__(lval)) _res; \
4800 #endif /* PLAT_s390x_linux */
4803 /* ------------------------------------------------------------------ */
4804 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4806 /* ------------------------------------------------------------------ */
4808 /* Some request codes. There are many more of these, but most are not
4809 exposed to end-user view. These are the public ones, all of the
4810 form 0x1000 + small_number.
4812 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4813 ones start at 0x2000.
4816 /* These macros are used by tools -- they must be public, but don't
4817 embed them into other programs. */
4818 #define VG_USERREQ_TOOL_BASE(a,b) \
4819 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
4820 #define VG_IS_TOOL_USERREQ(a, b, v) \
4821 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
4823 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4824 This enum comprises an ABI exported by Valgrind to programs
4825 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4826 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
4828 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4829 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
4831 /* These allow any function to be called from the simulated
4832 CPU but run on the real CPU. Nb: the first arg passed to
4833 the function is always the ThreadId of the running
4834 thread! So CLIENT_CALL0 actually requires a 1 arg
4836 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4837 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4838 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4839 VG_USERREQ__CLIENT_CALL3 = 0x1104,
4841 /* Can be useful in regression testing suites -- eg. can
4842 send Valgrind's output to /dev/null and still count
4844 VG_USERREQ__COUNT_ERRORS = 0x1201,
4846 /* These are useful and can be interpreted by any tool that
4847 tracks malloc() et al, by using vg_replace_malloc.c. */
4848 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4849 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
4850 /* Memory pool support. */
4851 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4852 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4853 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4854 VG_USERREQ__MEMPOOL_FREE = 0x1306,
4855 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
4856 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4857 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4858 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
4860 /* Allow printfs to valgrind log. */
4861 /* The first two pass the va_list argument by value, which
4862 assumes it is the same size as or smaller than a UWord,
4863 which generally isn't the case. Hence are deprecated.
4864 The second two pass the vargs by reference and so are
4865 immune to this problem. */
4866 /* both :: char* fmt, va_list vargs (DEPRECATED) */
4867 VG_USERREQ__PRINTF = 0x1401,
4868 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
4869 /* both :: char* fmt, va_list* vargs */
4870 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4871 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
4873 /* Stack support. */
4874 VG_USERREQ__STACK_REGISTER = 0x1501,
4875 VG_USERREQ__STACK_DEREGISTER = 0x1502,
4876 VG_USERREQ__STACK_CHANGE = 0x1503,
4879 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
4881 /* Querying of debug info. */
4882 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701
4885 #if !defined(__GNUC__)
4886 # define __extension__ /* */
4891 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
4892 * client request and whose value equals the client request result.
4895 #if defined(NVALGRIND)
4897 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4898 _zzq_default, _zzq_request, \
4899 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4902 #else /*defined(NVALGRIND)*/
4904 #if defined(_MSC_VER)
4906 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4907 _zzq_default, _zzq_request, \
4908 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4909 (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \
4910 (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \
4911 (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \
4912 (uintptr_t)(_zzq_arg5)))
4914 static __inline unsigned
4915 vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default,
4916 unsigned _zzq_request, uintptr_t _zzq_arg1,
4917 uintptr_t _zzq_arg2, uintptr_t _zzq_arg3,
4918 uintptr_t _zzq_arg4, uintptr_t _zzq_arg5)
4920 unsigned _zzq_rlval;
4921 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request,
4922 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5);
4926 #else /*defined(_MSC_VER)*/
4928 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4929 _zzq_default, _zzq_request, \
4930 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4931 (__extension__({unsigned int _zzq_rlval; \
4932 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \
4933 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4937 #endif /*defined(_MSC_VER)*/
4939 #endif /*defined(NVALGRIND)*/
4942 /* Returns the number of Valgrinds this code is running under. That
4943 is, 0 if running natively, 1 if running under Valgrind, 2 if
4944 running under Valgrind which is running under another Valgrind,
4946 #define RUNNING_ON_VALGRIND \
4947 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
4948 VG_USERREQ__RUNNING_ON_VALGRIND, \
4952 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4953 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4954 since it provides a way to make sure valgrind will retranslate the
4955 invalidated area. Returns no value. */
4956 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4957 {unsigned int _qzz_res VG_UNUSED; \
4958 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4959 VG_USERREQ__DISCARD_TRANSLATIONS, \
4960 _qzz_addr, _qzz_len, 0, 0, 0); \
4964 /* These requests are for getting Valgrind itself to print something.
4965 Possibly with a backtrace. This is a really ugly hack. The return value
4966 is the number of characters printed, excluding the "**<pid>** " part at the
4967 start and the backtrace (if present). */
4969 #if defined(NVALGRIND)
4971 # define VALGRIND_PRINTF(...)
4972 # define VALGRIND_PRINTF_BACKTRACE(...)
4974 #else /* NVALGRIND */
4976 #if !defined(_MSC_VER)
4977 /* Modern GCC will optimize the static routine out if unused,
4978 and unused attribute will shut down warnings about it. */
4979 static int VALGRIND_PRINTF(const char *format, ...)
4980 __attribute__((format(__printf__, 1, 2), __unused__));
4983 #if defined(_MSC_VER)
4986 VALGRIND_PRINTF(const char *format, ...)
4988 unsigned long _qzz_res;
4990 va_start(vargs, format);
4991 #if defined(_MSC_VER)
4992 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4993 VG_USERREQ__PRINTF_VALIST_BY_REF,
4998 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4999 VG_USERREQ__PRINTF_VALIST_BY_REF,
5000 (unsigned long)format,
5001 (unsigned long)&vargs,
5005 return (int)_qzz_res;
5008 #if !defined(_MSC_VER)
5009 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
5010 __attribute__((format(__printf__, 1, 2), __unused__));
5013 #if defined(_MSC_VER)
5016 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
5018 unsigned long _qzz_res;
5020 va_start(vargs, format);
5021 #if defined(_MSC_VER)
5022 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
5023 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
5028 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
5029 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
5030 (unsigned long)format,
5031 (unsigned long)&vargs,
5035 return (int)_qzz_res;
5038 #endif /* NVALGRIND */
5041 /* These requests allow control to move from the simulated CPU to the
5042 real CPU, calling an arbitary function.
5044 Note that the current ThreadId is inserted as the first argument.
5047 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
5049 requires f to have this signature:
5051 Word f(Word tid, Word arg1, Word arg2)
5053 where "Word" is a word-sized type.
5055 Note that these client requests are not entirely reliable. For example,
5056 if you call a function with them that subsequently calls printf(),
5057 there's a high chance Valgrind will crash. Generally, your prospects of
5058 these working are made higher if the called function does not refer to
5059 any global variables, and does not refer to any libc or other functions
5060 (printf et al). Any kind of entanglement with libc or dynamic linking is
5061 likely to have a bad outcome, for tricky reasons which we've grappled
5062 with a lot in the past.
5064 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
5066 ({unsigned long _qyy_res; \
5067 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
5068 VG_USERREQ__CLIENT_CALL0, \
5074 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
5076 ({unsigned long _qyy_res; \
5077 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
5078 VG_USERREQ__CLIENT_CALL1, \
5080 _qyy_arg1, 0, 0, 0); \
5084 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
5086 ({unsigned long _qyy_res; \
5087 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
5088 VG_USERREQ__CLIENT_CALL2, \
5090 _qyy_arg1, _qyy_arg2, 0, 0); \
5094 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
5096 ({unsigned long _qyy_res; \
5097 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
5098 VG_USERREQ__CLIENT_CALL3, \
5100 _qyy_arg1, _qyy_arg2, \
5106 /* Counts the number of errors that have been recorded by a tool. Nb:
5107 the tool must record the errors with VG_(maybe_record_error)() or
5108 VG_(unique_error)() for them to be counted. */
5109 #define VALGRIND_COUNT_ERRORS \
5111 ({unsigned int _qyy_res; \
5112 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
5113 VG_USERREQ__COUNT_ERRORS, \
5118 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
5119 when heap blocks are allocated in order to give accurate results. This
5120 happens automatically for the standard allocator functions such as
5121 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
5124 But if your program uses a custom allocator, this doesn't automatically
5125 happen, and Valgrind will not do as well. For example, if you allocate
5126 superblocks with mmap() and then allocates chunks of the superblocks, all
5127 Valgrind's observations will be at the mmap() level and it won't know that
5128 the chunks should be considered separate entities. In Memcheck's case,
5129 that means you probably won't get heap block overrun detection (because
5130 there won't be redzones marked as unaddressable) and you definitely won't
5131 get any leak detection.
5133 The following client requests allow a custom allocator to be annotated so
5134 that it can be handled accurately by Valgrind.
5136 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
5137 by a malloc()-like function. For Memcheck (an illustrative case), this
5140 - It records that the block has been allocated. This means any addresses
5141 within the block mentioned in error messages will be
5142 identified as belonging to the block. It also means that if the block
5143 isn't freed it will be detected by the leak checker.
5145 - It marks the block as being addressable and undefined (if 'is_zeroed' is
5146 not set), or addressable and defined (if 'is_zeroed' is set). This
5147 controls how accesses to the block by the program are handled.
5149 'addr' is the start of the usable block (ie. after any
5150 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
5151 can apply redzones -- these are blocks of padding at the start and end of
5152 each block. Adding redzones is recommended as it makes it much more likely
5153 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
5154 zeroed (or filled with another predictable value), as is the case for
5157 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
5158 heap block -- that will be used by the client program -- is allocated.
5159 It's best to put it at the outermost level of the allocator if possible;
5160 for example, if you have a function my_alloc() which calls
5161 internal_alloc(), and the client request is put inside internal_alloc(),
5162 stack traces relating to the heap block will contain entries for both
5163 my_alloc() and internal_alloc(), which is probably not what you want.
5165 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
5166 custom blocks from within a heap block, B, that has been allocated with
5167 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
5168 -- the custom blocks will take precedence.
5170 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
5171 Memcheck, it does two things:
5173 - It records that the block has been deallocated. This assumes that the
5174 block was annotated as having been allocated via
5175 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
5177 - It marks the block as being unaddressable.
5179 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
5180 heap block is deallocated.
5182 In many cases, these two client requests will not be enough to get your
5183 allocator working well with Memcheck. More specifically, if your allocator
5184 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
5185 will be necessary to mark the memory as addressable just before the zeroing
5186 occurs, otherwise you'll get a lot of invalid write errors. For example,
5187 you'll need to do this if your allocator recycles freed blocks, but it
5188 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
5189 Alternatively, if your allocator reuses freed blocks for allocator-internal
5190 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
5192 Really, what's happening is a blurring of the lines between the client
5193 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
5194 memory should be considered unaddressable to the client program, but the
5195 allocator knows more than the rest of the client program and so may be able
5196 to safely access it. Extra client requests are necessary for Valgrind to
5197 understand the distinction between the allocator and the rest of the
5200 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
5201 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
5203 Ignored if addr == 0.
5205 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
5206 {unsigned int _qzz_res VG_UNUSED; \
5207 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5208 VG_USERREQ__MALLOCLIKE_BLOCK, \
5209 addr, sizeB, rzB, is_zeroed, 0); \
5212 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
5213 Ignored if addr == 0.
5215 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
5216 {unsigned int _qzz_res VG_UNUSED; \
5217 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5218 VG_USERREQ__FREELIKE_BLOCK, \
5219 addr, rzB, 0, 0, 0); \
5222 /* Create a memory pool. */
5223 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
5224 {unsigned int _qzz_res VG_UNUSED; \
5225 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5226 VG_USERREQ__CREATE_MEMPOOL, \
5227 pool, rzB, is_zeroed, 0, 0); \
5230 /* Destroy a memory pool. */
5231 #define VALGRIND_DESTROY_MEMPOOL(pool) \
5232 {unsigned int _qzz_res VG_UNUSED; \
5233 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5234 VG_USERREQ__DESTROY_MEMPOOL, \
5235 pool, 0, 0, 0, 0); \
5238 /* Associate a piece of memory with a memory pool. */
5239 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
5240 {unsigned int _qzz_res VG_UNUSED; \
5241 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5242 VG_USERREQ__MEMPOOL_ALLOC, \
5243 pool, addr, size, 0, 0); \
5246 /* Disassociate a piece of memory from a memory pool. */
5247 #define VALGRIND_MEMPOOL_FREE(pool, addr) \
5248 {unsigned int _qzz_res VG_UNUSED; \
5249 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5250 VG_USERREQ__MEMPOOL_FREE, \
5251 pool, addr, 0, 0, 0); \
5254 /* Disassociate any pieces outside a particular range. */
5255 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
5256 {unsigned int _qzz_res VG_UNUSED; \
5257 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5258 VG_USERREQ__MEMPOOL_TRIM, \
5259 pool, addr, size, 0, 0); \
5262 /* Resize and/or move a piece associated with a memory pool. */
5263 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
5264 {unsigned int _qzz_res VG_UNUSED; \
5265 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5266 VG_USERREQ__MOVE_MEMPOOL, \
5267 poolA, poolB, 0, 0, 0); \
5270 /* Resize and/or move a piece associated with a memory pool. */
5271 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
5272 {unsigned int _qzz_res VG_UNUSED; \
5273 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5274 VG_USERREQ__MEMPOOL_CHANGE, \
5275 pool, addrA, addrB, size, 0); \
5278 /* Return 1 if a mempool exists, else 0. */
5279 #define VALGRIND_MEMPOOL_EXISTS(pool) \
5281 ({unsigned int _qzz_res; \
5282 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5283 VG_USERREQ__MEMPOOL_EXISTS, \
5284 pool, 0, 0, 0, 0); \
5288 /* Mark a piece of memory as being a stack. Returns a stack id. */
5289 #define VALGRIND_STACK_REGISTER(start, end) \
5291 ({unsigned int _qzz_res; \
5292 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5293 VG_USERREQ__STACK_REGISTER, \
5294 start, end, 0, 0, 0); \
5298 /* Unmark the piece of memory associated with a stack id as being a
5300 #define VALGRIND_STACK_DEREGISTER(id) \
5301 {unsigned int _qzz_res VG_UNUSED; \
5302 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5303 VG_USERREQ__STACK_DEREGISTER, \
5307 /* Change the start and end address of the stack id. */
5308 #define VALGRIND_STACK_CHANGE(id, start, end) \
5309 {unsigned int _qzz_res VG_UNUSED; \
5310 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5311 VG_USERREQ__STACK_CHANGE, \
5312 id, start, end, 0, 0); \
5315 /* Load PDB debug info for Wine PE image_map. */
5316 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
5317 {unsigned int _qzz_res VG_UNUSED; \
5318 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5319 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
5320 fd, ptr, total_size, delta, 0); \
5323 /* Map a code address to a source file name and line number. buf64
5324 must point to a 64-byte buffer in the caller's address space. The
5325 result will be dumped in there and is guaranteed to be zero
5326 terminated. If no info is found, the first byte is set to zero. */
5327 #define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
5328 {unsigned int _qzz_res VG_UNUSED; \
5329 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
5330 VG_USERREQ__MAP_IP_TO_SRCLOC, \
5331 addr, buf64, 0, 0, 0); \
5335 #undef PLAT_x86_linux
5336 #undef PLAT_amd64_linux
5337 #undef PLAT_ppc32_linux
5338 #undef PLAT_ppc64_linux
5339 #undef PLAT_arm_linux
5340 #undef PLAT_s390x_linux
5341 #undef PLAT_ppc32_aix5
5342 #undef PLAT_ppc64_aix5
5344 #endif /* __VALGRIND_H */