drd: Fix fork() handling
[valgrind.git] / include / valgrind.h
blob577c8f05e5b02ea8f332d43b6d24b30c248f4eb1
1 /* -*- c -*-
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
13 framework.
15 Copyright (C) 2000-2017 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
19 are met:
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
34 permission.
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. */
73 #ifndef __VALGRIND_H
74 #define __VALGRIND_H
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
85 X.Y or later" is (eg)
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__ 14
95 #include <stdarg.h>
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
99 use "__asm__"). */
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_x86_darwin
112 #undef PLAT_amd64_darwin
113 #undef PLAT_x86_win32
114 #undef PLAT_amd64_win64
115 #undef PLAT_x86_linux
116 #undef PLAT_amd64_linux
117 #undef PLAT_ppc32_linux
118 #undef PLAT_ppc64be_linux
119 #undef PLAT_ppc64le_linux
120 #undef PLAT_arm_linux
121 #undef PLAT_arm64_linux
122 #undef PLAT_s390x_linux
123 #undef PLAT_mips32_linux
124 #undef PLAT_mips64_linux
125 #undef PLAT_x86_solaris
126 #undef PLAT_amd64_solaris
129 #if defined(__APPLE__) && defined(__i386__)
130 # define PLAT_x86_darwin 1
131 #elif defined(__APPLE__) && defined(__x86_64__)
132 # define PLAT_amd64_darwin 1
133 #elif (defined(__MINGW32__) && !defined(__MINGW64__)) \
134 || defined(__CYGWIN32__) \
135 || (defined(_WIN32) && defined(_M_IX86))
136 # define PLAT_x86_win32 1
137 #elif defined(__MINGW64__) \
138 || (defined(_WIN64) && defined(_M_X64))
139 # define PLAT_amd64_win64 1
140 #elif defined(__linux__) && defined(__i386__)
141 # define PLAT_x86_linux 1
142 #elif defined(__linux__) && defined(__x86_64__) && !defined(__ILP32__)
143 # define PLAT_amd64_linux 1
144 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
145 # define PLAT_ppc32_linux 1
146 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
147 /* Big Endian uses ELF version 1 */
148 # define PLAT_ppc64be_linux 1
149 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2
150 /* Little Endian uses ELF version 2 */
151 # define PLAT_ppc64le_linux 1
152 #elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
153 # define PLAT_arm_linux 1
154 #elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
155 # define PLAT_arm64_linux 1
156 #elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
157 # define PLAT_s390x_linux 1
158 #elif defined(__linux__) && defined(__mips__) && (__mips==64)
159 # define PLAT_mips64_linux 1
160 #elif defined(__linux__) && defined(__mips__) && (__mips!=64)
161 # define PLAT_mips32_linux 1
162 #elif defined(__sun) && defined(__i386__)
163 # define PLAT_x86_solaris 1
164 #elif defined(__sun) && defined(__x86_64__)
165 # define PLAT_amd64_solaris 1
166 #else
167 /* If we're not compiling for our target platform, don't generate
168 any inline asms. */
169 # if !defined(NVALGRIND)
170 # define NVALGRIND 1
171 # endif
172 #endif
175 /* ------------------------------------------------------------------ */
176 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
177 /* in here of use to end-users -- skip to the next section. */
178 /* ------------------------------------------------------------------ */
181 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
182 * request. Accepts both pointers and integers as arguments.
184 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
185 * client request that does not return a value.
187 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
188 * client request and whose value equals the client request result. Accepts
189 * both pointers and integers as arguments. Note that such calls are not
190 * necessarily pure functions -- they may have side effects.
193 #define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
194 _zzq_request, _zzq_arg1, _zzq_arg2, \
195 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
196 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
197 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
198 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
200 #define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
201 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
202 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
203 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
204 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
206 #if defined(NVALGRIND)
208 /* Define NVALGRIND to completely remove the Valgrind magic sequence
209 from the compiled code (analogous to NDEBUG's effects on
210 assert()) */
211 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
212 _zzq_default, _zzq_request, \
213 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
214 (_zzq_default)
216 #else /* ! NVALGRIND */
218 /* The following defines the magic code sequences which the JITter
219 spots and handles magically. Don't look too closely at them as
220 they will rot your brain.
222 The assembly code sequences for all architectures is in this one
223 file. This is because this file must be stand-alone, and we don't
224 want to have multiple files.
226 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
227 value gets put in the return slot, so that everything works when
228 this is executed not under Valgrind. Args are passed in a memory
229 block, and so there's no intrinsic limit to the number that could
230 be passed, but it's currently five.
232 The macro args are:
233 _zzq_rlval result lvalue
234 _zzq_default default value (result returned when running on real CPU)
235 _zzq_request request code
236 _zzq_arg1..5 request params
238 The other two macros are used to support function wrapping, and are
239 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
240 guest's NRADDR pseudo-register and whatever other information is
241 needed to safely run the call original from the wrapper: on
242 ppc64-linux, the R2 value at the divert point is also needed. This
243 information is abstracted into a user-visible type, OrigFn.
245 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
246 guest, but guarantees that the branch instruction will not be
247 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
248 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
249 complete inline asm, since it needs to be combined with more magic
250 inline asm stuff to be useful.
253 /* ----------------- x86-{linux,darwin,solaris} ---------------- */
255 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
256 || (defined(PLAT_x86_win32) && defined(__GNUC__)) \
257 || defined(PLAT_x86_solaris)
259 typedef
260 struct {
261 unsigned int nraddr; /* where's the code? */
263 OrigFn;
265 #define __SPECIAL_INSTRUCTION_PREAMBLE \
266 "roll $3, %%edi ; roll $13, %%edi\n\t" \
267 "roll $29, %%edi ; roll $19, %%edi\n\t"
269 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
270 _zzq_default, _zzq_request, \
271 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
272 __extension__ \
273 ({volatile unsigned int _zzq_args[6]; \
274 volatile unsigned int _zzq_result; \
275 _zzq_args[0] = (unsigned int)(_zzq_request); \
276 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
277 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
278 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
279 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
280 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
281 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
282 /* %EDX = client_request ( %EAX ) */ \
283 "xchgl %%ebx,%%ebx" \
284 : "=d" (_zzq_result) \
285 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
286 : "cc", "memory" \
287 ); \
288 _zzq_result; \
291 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
292 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
293 volatile unsigned int __addr; \
294 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
295 /* %EAX = guest_NRADDR */ \
296 "xchgl %%ecx,%%ecx" \
297 : "=a" (__addr) \
299 : "cc", "memory" \
300 ); \
301 _zzq_orig->nraddr = __addr; \
304 #define VALGRIND_CALL_NOREDIR_EAX \
305 __SPECIAL_INSTRUCTION_PREAMBLE \
306 /* call-noredir *%EAX */ \
307 "xchgl %%edx,%%edx\n\t"
309 #define VALGRIND_VEX_INJECT_IR() \
310 do { \
311 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
312 "xchgl %%edi,%%edi\n\t" \
313 : : : "cc", "memory" \
314 ); \
315 } while (0)
317 #endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__)
318 || PLAT_x86_solaris */
320 /* ------------------------- x86-Win32 ------------------------- */
322 #if defined(PLAT_x86_win32) && !defined(__GNUC__)
324 typedef
325 struct {
326 unsigned int nraddr; /* where's the code? */
328 OrigFn;
330 #if defined(_MSC_VER)
332 #define __SPECIAL_INSTRUCTION_PREAMBLE \
333 __asm rol edi, 3 __asm rol edi, 13 \
334 __asm rol edi, 29 __asm rol edi, 19
336 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
337 _zzq_default, _zzq_request, \
338 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
339 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
340 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
341 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
342 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
344 static __inline uintptr_t
345 valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
346 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
347 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
348 uintptr_t _zzq_arg5)
350 volatile uintptr_t _zzq_args[6];
351 volatile unsigned int _zzq_result;
352 _zzq_args[0] = (uintptr_t)(_zzq_request);
353 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
354 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
355 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
356 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
357 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
358 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
359 __SPECIAL_INSTRUCTION_PREAMBLE
360 /* %EDX = client_request ( %EAX ) */
361 __asm xchg ebx,ebx
362 __asm mov _zzq_result, edx
364 return _zzq_result;
367 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
368 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
369 volatile unsigned int __addr; \
370 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
371 /* %EAX = guest_NRADDR */ \
372 __asm xchg ecx,ecx \
373 __asm mov __addr, eax \
375 _zzq_orig->nraddr = __addr; \
378 #define VALGRIND_CALL_NOREDIR_EAX ERROR
380 #define VALGRIND_VEX_INJECT_IR() \
381 do { \
382 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
383 __asm xchg edi,edi \
385 } while (0)
387 #else
388 #error Unsupported compiler.
389 #endif
391 #endif /* PLAT_x86_win32 */
393 /* ----------------- amd64-{linux,darwin,solaris} --------------- */
395 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
396 || defined(PLAT_amd64_solaris) \
397 || (defined(PLAT_amd64_win64) && defined(__GNUC__))
399 typedef
400 struct {
401 unsigned long int nraddr; /* where's the code? */
403 OrigFn;
405 #define __SPECIAL_INSTRUCTION_PREAMBLE \
406 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
407 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
409 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
410 _zzq_default, _zzq_request, \
411 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
412 __extension__ \
413 ({ volatile unsigned long int _zzq_args[6]; \
414 volatile unsigned long int _zzq_result; \
415 _zzq_args[0] = (unsigned long int)(_zzq_request); \
416 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
417 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
418 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
419 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
420 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
421 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
422 /* %RDX = client_request ( %RAX ) */ \
423 "xchgq %%rbx,%%rbx" \
424 : "=d" (_zzq_result) \
425 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
426 : "cc", "memory" \
427 ); \
428 _zzq_result; \
431 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
432 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
433 volatile unsigned long int __addr; \
434 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
435 /* %RAX = guest_NRADDR */ \
436 "xchgq %%rcx,%%rcx" \
437 : "=a" (__addr) \
439 : "cc", "memory" \
440 ); \
441 _zzq_orig->nraddr = __addr; \
444 #define VALGRIND_CALL_NOREDIR_RAX \
445 __SPECIAL_INSTRUCTION_PREAMBLE \
446 /* call-noredir *%RAX */ \
447 "xchgq %%rdx,%%rdx\n\t"
449 #define VALGRIND_VEX_INJECT_IR() \
450 do { \
451 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
452 "xchgq %%rdi,%%rdi\n\t" \
453 : : : "cc", "memory" \
454 ); \
455 } while (0)
457 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
459 /* ------------------------- amd64-Win64 ------------------------- */
461 #if defined(PLAT_amd64_win64) && !defined(__GNUC__)
463 #error Unsupported compiler.
465 #endif /* PLAT_amd64_win64 */
467 /* ------------------------ ppc32-linux ------------------------ */
469 #if defined(PLAT_ppc32_linux)
471 typedef
472 struct {
473 unsigned int nraddr; /* where's the code? */
475 OrigFn;
477 #define __SPECIAL_INSTRUCTION_PREAMBLE \
478 "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \
479 "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
481 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
482 _zzq_default, _zzq_request, \
483 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
485 __extension__ \
486 ({ unsigned int _zzq_args[6]; \
487 unsigned int _zzq_result; \
488 unsigned int* _zzq_ptr; \
489 _zzq_args[0] = (unsigned int)(_zzq_request); \
490 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
491 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
492 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
493 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
494 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
495 _zzq_ptr = _zzq_args; \
496 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
497 "mr 4,%2\n\t" /*ptr*/ \
498 __SPECIAL_INSTRUCTION_PREAMBLE \
499 /* %R3 = client_request ( %R4 ) */ \
500 "or 1,1,1\n\t" \
501 "mr %0,3" /*result*/ \
502 : "=b" (_zzq_result) \
503 : "b" (_zzq_default), "b" (_zzq_ptr) \
504 : "cc", "memory", "r3", "r4"); \
505 _zzq_result; \
508 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
509 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
510 unsigned int __addr; \
511 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
512 /* %R3 = guest_NRADDR */ \
513 "or 2,2,2\n\t" \
514 "mr %0,3" \
515 : "=b" (__addr) \
517 : "cc", "memory", "r3" \
518 ); \
519 _zzq_orig->nraddr = __addr; \
522 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
523 __SPECIAL_INSTRUCTION_PREAMBLE \
524 /* branch-and-link-to-noredir *%R11 */ \
525 "or 3,3,3\n\t"
527 #define VALGRIND_VEX_INJECT_IR() \
528 do { \
529 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
530 "or 5,5,5\n\t" \
531 ); \
532 } while (0)
534 #endif /* PLAT_ppc32_linux */
536 /* ------------------------ ppc64-linux ------------------------ */
538 #if defined(PLAT_ppc64be_linux)
540 typedef
541 struct {
542 unsigned long int nraddr; /* where's the code? */
543 unsigned long int r2; /* what tocptr do we need? */
545 OrigFn;
547 #define __SPECIAL_INSTRUCTION_PREAMBLE \
548 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
549 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
551 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
552 _zzq_default, _zzq_request, \
553 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
555 __extension__ \
556 ({ unsigned long int _zzq_args[6]; \
557 unsigned long int _zzq_result; \
558 unsigned long int* _zzq_ptr; \
559 _zzq_args[0] = (unsigned long int)(_zzq_request); \
560 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
561 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
562 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
563 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
564 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
565 _zzq_ptr = _zzq_args; \
566 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
567 "mr 4,%2\n\t" /*ptr*/ \
568 __SPECIAL_INSTRUCTION_PREAMBLE \
569 /* %R3 = client_request ( %R4 ) */ \
570 "or 1,1,1\n\t" \
571 "mr %0,3" /*result*/ \
572 : "=b" (_zzq_result) \
573 : "b" (_zzq_default), "b" (_zzq_ptr) \
574 : "cc", "memory", "r3", "r4"); \
575 _zzq_result; \
578 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
579 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
580 unsigned long int __addr; \
581 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
582 /* %R3 = guest_NRADDR */ \
583 "or 2,2,2\n\t" \
584 "mr %0,3" \
585 : "=b" (__addr) \
587 : "cc", "memory", "r3" \
588 ); \
589 _zzq_orig->nraddr = __addr; \
590 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
591 /* %R3 = guest_NRADDR_GPR2 */ \
592 "or 4,4,4\n\t" \
593 "mr %0,3" \
594 : "=b" (__addr) \
596 : "cc", "memory", "r3" \
597 ); \
598 _zzq_orig->r2 = __addr; \
601 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
602 __SPECIAL_INSTRUCTION_PREAMBLE \
603 /* branch-and-link-to-noredir *%R11 */ \
604 "or 3,3,3\n\t"
606 #define VALGRIND_VEX_INJECT_IR() \
607 do { \
608 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
609 "or 5,5,5\n\t" \
610 ); \
611 } while (0)
613 #endif /* PLAT_ppc64be_linux */
615 #if defined(PLAT_ppc64le_linux)
617 typedef
618 struct {
619 unsigned long int nraddr; /* where's the code? */
620 unsigned long int r2; /* what tocptr do we need? */
622 OrigFn;
624 #define __SPECIAL_INSTRUCTION_PREAMBLE \
625 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
626 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
628 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
629 _zzq_default, _zzq_request, \
630 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
632 __extension__ \
633 ({ unsigned long int _zzq_args[6]; \
634 unsigned long int _zzq_result; \
635 unsigned long int* _zzq_ptr; \
636 _zzq_args[0] = (unsigned long int)(_zzq_request); \
637 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
638 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
639 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
640 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
641 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
642 _zzq_ptr = _zzq_args; \
643 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
644 "mr 4,%2\n\t" /*ptr*/ \
645 __SPECIAL_INSTRUCTION_PREAMBLE \
646 /* %R3 = client_request ( %R4 ) */ \
647 "or 1,1,1\n\t" \
648 "mr %0,3" /*result*/ \
649 : "=b" (_zzq_result) \
650 : "b" (_zzq_default), "b" (_zzq_ptr) \
651 : "cc", "memory", "r3", "r4"); \
652 _zzq_result; \
655 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
656 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
657 unsigned long int __addr; \
658 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
659 /* %R3 = guest_NRADDR */ \
660 "or 2,2,2\n\t" \
661 "mr %0,3" \
662 : "=b" (__addr) \
664 : "cc", "memory", "r3" \
665 ); \
666 _zzq_orig->nraddr = __addr; \
667 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
668 /* %R3 = guest_NRADDR_GPR2 */ \
669 "or 4,4,4\n\t" \
670 "mr %0,3" \
671 : "=b" (__addr) \
673 : "cc", "memory", "r3" \
674 ); \
675 _zzq_orig->r2 = __addr; \
678 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
679 __SPECIAL_INSTRUCTION_PREAMBLE \
680 /* branch-and-link-to-noredir *%R12 */ \
681 "or 3,3,3\n\t"
683 #define VALGRIND_VEX_INJECT_IR() \
684 do { \
685 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
686 "or 5,5,5\n\t" \
687 ); \
688 } while (0)
690 #endif /* PLAT_ppc64le_linux */
692 /* ------------------------- arm-linux ------------------------- */
694 #if defined(PLAT_arm_linux)
696 typedef
697 struct {
698 unsigned int nraddr; /* where's the code? */
700 OrigFn;
702 #define __SPECIAL_INSTRUCTION_PREAMBLE \
703 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
704 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
706 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
707 _zzq_default, _zzq_request, \
708 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
710 __extension__ \
711 ({volatile unsigned int _zzq_args[6]; \
712 volatile unsigned int _zzq_result; \
713 _zzq_args[0] = (unsigned int)(_zzq_request); \
714 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
715 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
716 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
717 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
718 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
719 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
720 "mov r4, %2\n\t" /*ptr*/ \
721 __SPECIAL_INSTRUCTION_PREAMBLE \
722 /* R3 = client_request ( R4 ) */ \
723 "orr r10, r10, r10\n\t" \
724 "mov %0, r3" /*result*/ \
725 : "=r" (_zzq_result) \
726 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
727 : "cc","memory", "r3", "r4"); \
728 _zzq_result; \
731 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
732 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
733 unsigned int __addr; \
734 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
735 /* R3 = guest_NRADDR */ \
736 "orr r11, r11, r11\n\t" \
737 "mov %0, r3" \
738 : "=r" (__addr) \
740 : "cc", "memory", "r3" \
741 ); \
742 _zzq_orig->nraddr = __addr; \
745 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
746 __SPECIAL_INSTRUCTION_PREAMBLE \
747 /* branch-and-link-to-noredir *%R4 */ \
748 "orr r12, r12, r12\n\t"
750 #define VALGRIND_VEX_INJECT_IR() \
751 do { \
752 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
753 "orr r9, r9, r9\n\t" \
754 : : : "cc", "memory" \
755 ); \
756 } while (0)
758 #endif /* PLAT_arm_linux */
760 /* ------------------------ arm64-linux ------------------------- */
762 #if defined(PLAT_arm64_linux)
764 typedef
765 struct {
766 unsigned long int nraddr; /* where's the code? */
768 OrigFn;
770 #define __SPECIAL_INSTRUCTION_PREAMBLE \
771 "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
772 "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
774 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
775 _zzq_default, _zzq_request, \
776 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
778 __extension__ \
779 ({volatile unsigned long int _zzq_args[6]; \
780 volatile unsigned long int _zzq_result; \
781 _zzq_args[0] = (unsigned long int)(_zzq_request); \
782 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
783 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
784 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
785 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
786 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
787 __asm__ volatile("mov x3, %1\n\t" /*default*/ \
788 "mov x4, %2\n\t" /*ptr*/ \
789 __SPECIAL_INSTRUCTION_PREAMBLE \
790 /* X3 = client_request ( X4 ) */ \
791 "orr x10, x10, x10\n\t" \
792 "mov %0, x3" /*result*/ \
793 : "=r" (_zzq_result) \
794 : "r" ((unsigned long int)(_zzq_default)), \
795 "r" (&_zzq_args[0]) \
796 : "cc","memory", "x3", "x4"); \
797 _zzq_result; \
800 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
801 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
802 unsigned long int __addr; \
803 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
804 /* X3 = guest_NRADDR */ \
805 "orr x11, x11, x11\n\t" \
806 "mov %0, x3" \
807 : "=r" (__addr) \
809 : "cc", "memory", "x3" \
810 ); \
811 _zzq_orig->nraddr = __addr; \
814 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
815 __SPECIAL_INSTRUCTION_PREAMBLE \
816 /* branch-and-link-to-noredir X8 */ \
817 "orr x12, x12, x12\n\t"
819 #define VALGRIND_VEX_INJECT_IR() \
820 do { \
821 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
822 "orr x9, x9, x9\n\t" \
823 : : : "cc", "memory" \
824 ); \
825 } while (0)
827 #endif /* PLAT_arm64_linux */
829 /* ------------------------ s390x-linux ------------------------ */
831 #if defined(PLAT_s390x_linux)
833 typedef
834 struct {
835 unsigned long int nraddr; /* where's the code? */
837 OrigFn;
839 /* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
840 * code. This detection is implemented in platform specific toIR.c
841 * (e.g. VEX/priv/guest_s390_decoder.c).
843 #define __SPECIAL_INSTRUCTION_PREAMBLE \
844 "lr 15,15\n\t" \
845 "lr 1,1\n\t" \
846 "lr 2,2\n\t" \
847 "lr 3,3\n\t"
849 #define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
850 #define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
851 #define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
852 #define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
854 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
855 _zzq_default, _zzq_request, \
856 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
857 __extension__ \
858 ({volatile unsigned long int _zzq_args[6]; \
859 volatile unsigned long int _zzq_result; \
860 _zzq_args[0] = (unsigned long int)(_zzq_request); \
861 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
862 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
863 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
864 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
865 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
866 __asm__ volatile(/* r2 = args */ \
867 "lgr 2,%1\n\t" \
868 /* r3 = default */ \
869 "lgr 3,%2\n\t" \
870 __SPECIAL_INSTRUCTION_PREAMBLE \
871 __CLIENT_REQUEST_CODE \
872 /* results = r3 */ \
873 "lgr %0, 3\n\t" \
874 : "=d" (_zzq_result) \
875 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
876 : "cc", "2", "3", "memory" \
877 ); \
878 _zzq_result; \
881 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
882 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
883 volatile unsigned long int __addr; \
884 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
885 __GET_NR_CONTEXT_CODE \
886 "lgr %0, 3\n\t" \
887 : "=a" (__addr) \
889 : "cc", "3", "memory" \
890 ); \
891 _zzq_orig->nraddr = __addr; \
894 #define VALGRIND_CALL_NOREDIR_R1 \
895 __SPECIAL_INSTRUCTION_PREAMBLE \
896 __CALL_NO_REDIR_CODE
898 #define VALGRIND_VEX_INJECT_IR() \
899 do { \
900 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
901 __VEX_INJECT_IR_CODE); \
902 } while (0)
904 #endif /* PLAT_s390x_linux */
906 /* ------------------------- mips32-linux ---------------- */
908 #if defined(PLAT_mips32_linux)
910 typedef
911 struct {
912 unsigned int nraddr; /* where's the code? */
914 OrigFn;
916 /* .word 0x342
917 * .word 0x742
918 * .word 0xC2
919 * .word 0x4C2*/
920 #define __SPECIAL_INSTRUCTION_PREAMBLE \
921 "srl $0, $0, 13\n\t" \
922 "srl $0, $0, 29\n\t" \
923 "srl $0, $0, 3\n\t" \
924 "srl $0, $0, 19\n\t"
926 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
927 _zzq_default, _zzq_request, \
928 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
929 __extension__ \
930 ({ volatile unsigned int _zzq_args[6]; \
931 volatile unsigned int _zzq_result; \
932 _zzq_args[0] = (unsigned int)(_zzq_request); \
933 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
934 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
935 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
936 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
937 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
938 __asm__ volatile("move $11, %1\n\t" /*default*/ \
939 "move $12, %2\n\t" /*ptr*/ \
940 __SPECIAL_INSTRUCTION_PREAMBLE \
941 /* T3 = client_request ( T4 ) */ \
942 "or $13, $13, $13\n\t" \
943 "move %0, $11\n\t" /*result*/ \
944 : "=r" (_zzq_result) \
945 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
946 : "$11", "$12", "memory"); \
947 _zzq_result; \
950 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
951 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
952 volatile unsigned int __addr; \
953 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
954 /* %t9 = guest_NRADDR */ \
955 "or $14, $14, $14\n\t" \
956 "move %0, $11" /*result*/ \
957 : "=r" (__addr) \
959 : "$11" \
960 ); \
961 _zzq_orig->nraddr = __addr; \
964 #define VALGRIND_CALL_NOREDIR_T9 \
965 __SPECIAL_INSTRUCTION_PREAMBLE \
966 /* call-noredir *%t9 */ \
967 "or $15, $15, $15\n\t"
969 #define VALGRIND_VEX_INJECT_IR() \
970 do { \
971 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
972 "or $11, $11, $11\n\t" \
973 ); \
974 } while (0)
977 #endif /* PLAT_mips32_linux */
979 /* ------------------------- mips64-linux ---------------- */
981 #if defined(PLAT_mips64_linux)
983 typedef
984 struct {
985 unsigned long nraddr; /* where's the code? */
987 OrigFn;
989 /* dsll $0,$0, 3
990 * dsll $0,$0, 13
991 * dsll $0,$0, 29
992 * dsll $0,$0, 19*/
993 #define __SPECIAL_INSTRUCTION_PREAMBLE \
994 "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \
995 "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
997 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
998 _zzq_default, _zzq_request, \
999 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1000 __extension__ \
1001 ({ volatile unsigned long int _zzq_args[6]; \
1002 volatile unsigned long int _zzq_result; \
1003 _zzq_args[0] = (unsigned long int)(_zzq_request); \
1004 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
1005 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
1006 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
1007 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
1008 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
1009 __asm__ volatile("move $11, %1\n\t" /*default*/ \
1010 "move $12, %2\n\t" /*ptr*/ \
1011 __SPECIAL_INSTRUCTION_PREAMBLE \
1012 /* $11 = client_request ( $12 ) */ \
1013 "or $13, $13, $13\n\t" \
1014 "move %0, $11\n\t" /*result*/ \
1015 : "=r" (_zzq_result) \
1016 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
1017 : "$11", "$12", "memory"); \
1018 _zzq_result; \
1021 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1022 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1023 volatile unsigned long int __addr; \
1024 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1025 /* $11 = guest_NRADDR */ \
1026 "or $14, $14, $14\n\t" \
1027 "move %0, $11" /*result*/ \
1028 : "=r" (__addr) \
1030 : "$11"); \
1031 _zzq_orig->nraddr = __addr; \
1034 #define VALGRIND_CALL_NOREDIR_T9 \
1035 __SPECIAL_INSTRUCTION_PREAMBLE \
1036 /* call-noredir $25 */ \
1037 "or $15, $15, $15\n\t"
1039 #define VALGRIND_VEX_INJECT_IR() \
1040 do { \
1041 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1042 "or $11, $11, $11\n\t" \
1043 ); \
1044 } while (0)
1046 #endif /* PLAT_mips64_linux */
1048 /* Insert assembly code for other platforms here... */
1050 #endif /* NVALGRIND */
1053 /* ------------------------------------------------------------------ */
1054 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
1055 /* ugly. It's the least-worst tradeoff I can think of. */
1056 /* ------------------------------------------------------------------ */
1058 /* This section defines magic (a.k.a appalling-hack) macros for doing
1059 guaranteed-no-redirection macros, so as to get from function
1060 wrappers to the functions they are wrapping. The whole point is to
1061 construct standard call sequences, but to do the call itself with a
1062 special no-redirect call pseudo-instruction that the JIT
1063 understands and handles specially. This section is long and
1064 repetitious, and I can't see a way to make it shorter.
1066 The naming scheme is as follows:
1068 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
1070 'W' stands for "word" and 'v' for "void". Hence there are
1071 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
1072 and for each, the possibility of returning a word-typed result, or
1073 no result.
1076 /* Use these to write the name of your wrapper. NOTE: duplicates
1077 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
1078 the default behaviour equivalance class tag "0000" into the name.
1079 See pub_tool_redir.h for details -- normally you don't need to
1080 think about this, though. */
1082 /* Use an extra level of macroisation so as to ensure the soname/fnname
1083 args are fully macro-expanded before pasting them together. */
1084 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
1086 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
1087 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
1089 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
1090 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
1092 /* Use this macro from within a wrapper function to collect the
1093 context (address and possibly other info) of the original function.
1094 Once you have that you can then use it in one of the CALL_FN_
1095 macros. The type of the argument _lval is OrigFn. */
1096 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
1098 /* Also provide end-user facilities for function replacement, rather
1099 than wrapping. A replacement function differs from a wrapper in
1100 that it has no way to get hold of the original function being
1101 called, and hence no way to call onwards to it. In a replacement
1102 function, VALGRIND_GET_ORIG_FN always returns zero. */
1104 #define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
1105 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1107 #define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
1108 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1110 /* Derivatives of the main macros below, for calling functions
1111 returning void. */
1113 #define CALL_FN_v_v(fnptr) \
1114 do { volatile unsigned long _junk; \
1115 CALL_FN_W_v(_junk,fnptr); } while (0)
1117 #define CALL_FN_v_W(fnptr, arg1) \
1118 do { volatile unsigned long _junk; \
1119 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1121 #define CALL_FN_v_WW(fnptr, arg1,arg2) \
1122 do { volatile unsigned long _junk; \
1123 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1125 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
1126 do { volatile unsigned long _junk; \
1127 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1129 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
1130 do { volatile unsigned long _junk; \
1131 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1133 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
1134 do { volatile unsigned long _junk; \
1135 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1137 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
1138 do { volatile unsigned long _junk; \
1139 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1141 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
1142 do { volatile unsigned long _junk; \
1143 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1145 /* ----------------- x86-{linux,darwin,solaris} ---------------- */
1147 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
1148 || defined(PLAT_x86_solaris)
1150 /* These regs are trashed by the hidden call. No need to mention eax
1151 as gcc can already see that, plus causes gcc to bomb. */
1152 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1154 /* Macros to save and align the stack before making a function
1155 call and restore it afterwards as gcc may not keep the stack
1156 pointer aligned if it doesn't realise calls are being made
1157 to other functions. */
1159 #define VALGRIND_ALIGN_STACK \
1160 "movl %%esp,%%edi\n\t" \
1161 "andl $0xfffffff0,%%esp\n\t"
1162 #define VALGRIND_RESTORE_STACK \
1163 "movl %%edi,%%esp\n\t"
1165 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1166 long) == 4. */
1168 #define CALL_FN_W_v(lval, orig) \
1169 do { \
1170 volatile OrigFn _orig = (orig); \
1171 volatile unsigned long _argvec[1]; \
1172 volatile unsigned long _res; \
1173 _argvec[0] = (unsigned long)_orig.nraddr; \
1174 __asm__ volatile( \
1175 VALGRIND_ALIGN_STACK \
1176 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1177 VALGRIND_CALL_NOREDIR_EAX \
1178 VALGRIND_RESTORE_STACK \
1179 : /*out*/ "=a" (_res) \
1180 : /*in*/ "a" (&_argvec[0]) \
1181 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1182 ); \
1183 lval = (__typeof__(lval)) _res; \
1184 } while (0)
1186 #define CALL_FN_W_W(lval, orig, arg1) \
1187 do { \
1188 volatile OrigFn _orig = (orig); \
1189 volatile unsigned long _argvec[2]; \
1190 volatile unsigned long _res; \
1191 _argvec[0] = (unsigned long)_orig.nraddr; \
1192 _argvec[1] = (unsigned long)(arg1); \
1193 __asm__ volatile( \
1194 VALGRIND_ALIGN_STACK \
1195 "subl $12, %%esp\n\t" \
1196 "pushl 4(%%eax)\n\t" \
1197 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1198 VALGRIND_CALL_NOREDIR_EAX \
1199 VALGRIND_RESTORE_STACK \
1200 : /*out*/ "=a" (_res) \
1201 : /*in*/ "a" (&_argvec[0]) \
1202 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1203 ); \
1204 lval = (__typeof__(lval)) _res; \
1205 } while (0)
1207 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1208 do { \
1209 volatile OrigFn _orig = (orig); \
1210 volatile unsigned long _argvec[3]; \
1211 volatile unsigned long _res; \
1212 _argvec[0] = (unsigned long)_orig.nraddr; \
1213 _argvec[1] = (unsigned long)(arg1); \
1214 _argvec[2] = (unsigned long)(arg2); \
1215 __asm__ volatile( \
1216 VALGRIND_ALIGN_STACK \
1217 "subl $8, %%esp\n\t" \
1218 "pushl 8(%%eax)\n\t" \
1219 "pushl 4(%%eax)\n\t" \
1220 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1221 VALGRIND_CALL_NOREDIR_EAX \
1222 VALGRIND_RESTORE_STACK \
1223 : /*out*/ "=a" (_res) \
1224 : /*in*/ "a" (&_argvec[0]) \
1225 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1226 ); \
1227 lval = (__typeof__(lval)) _res; \
1228 } while (0)
1230 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1231 do { \
1232 volatile OrigFn _orig = (orig); \
1233 volatile unsigned long _argvec[4]; \
1234 volatile unsigned long _res; \
1235 _argvec[0] = (unsigned long)_orig.nraddr; \
1236 _argvec[1] = (unsigned long)(arg1); \
1237 _argvec[2] = (unsigned long)(arg2); \
1238 _argvec[3] = (unsigned long)(arg3); \
1239 __asm__ volatile( \
1240 VALGRIND_ALIGN_STACK \
1241 "subl $4, %%esp\n\t" \
1242 "pushl 12(%%eax)\n\t" \
1243 "pushl 8(%%eax)\n\t" \
1244 "pushl 4(%%eax)\n\t" \
1245 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1246 VALGRIND_CALL_NOREDIR_EAX \
1247 VALGRIND_RESTORE_STACK \
1248 : /*out*/ "=a" (_res) \
1249 : /*in*/ "a" (&_argvec[0]) \
1250 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1251 ); \
1252 lval = (__typeof__(lval)) _res; \
1253 } while (0)
1255 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1256 do { \
1257 volatile OrigFn _orig = (orig); \
1258 volatile unsigned long _argvec[5]; \
1259 volatile unsigned long _res; \
1260 _argvec[0] = (unsigned long)_orig.nraddr; \
1261 _argvec[1] = (unsigned long)(arg1); \
1262 _argvec[2] = (unsigned long)(arg2); \
1263 _argvec[3] = (unsigned long)(arg3); \
1264 _argvec[4] = (unsigned long)(arg4); \
1265 __asm__ volatile( \
1266 VALGRIND_ALIGN_STACK \
1267 "pushl 16(%%eax)\n\t" \
1268 "pushl 12(%%eax)\n\t" \
1269 "pushl 8(%%eax)\n\t" \
1270 "pushl 4(%%eax)\n\t" \
1271 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1272 VALGRIND_CALL_NOREDIR_EAX \
1273 VALGRIND_RESTORE_STACK \
1274 : /*out*/ "=a" (_res) \
1275 : /*in*/ "a" (&_argvec[0]) \
1276 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1277 ); \
1278 lval = (__typeof__(lval)) _res; \
1279 } while (0)
1281 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1282 do { \
1283 volatile OrigFn _orig = (orig); \
1284 volatile unsigned long _argvec[6]; \
1285 volatile unsigned long _res; \
1286 _argvec[0] = (unsigned long)_orig.nraddr; \
1287 _argvec[1] = (unsigned long)(arg1); \
1288 _argvec[2] = (unsigned long)(arg2); \
1289 _argvec[3] = (unsigned long)(arg3); \
1290 _argvec[4] = (unsigned long)(arg4); \
1291 _argvec[5] = (unsigned long)(arg5); \
1292 __asm__ volatile( \
1293 VALGRIND_ALIGN_STACK \
1294 "subl $12, %%esp\n\t" \
1295 "pushl 20(%%eax)\n\t" \
1296 "pushl 16(%%eax)\n\t" \
1297 "pushl 12(%%eax)\n\t" \
1298 "pushl 8(%%eax)\n\t" \
1299 "pushl 4(%%eax)\n\t" \
1300 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1301 VALGRIND_CALL_NOREDIR_EAX \
1302 VALGRIND_RESTORE_STACK \
1303 : /*out*/ "=a" (_res) \
1304 : /*in*/ "a" (&_argvec[0]) \
1305 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1306 ); \
1307 lval = (__typeof__(lval)) _res; \
1308 } while (0)
1310 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1311 do { \
1312 volatile OrigFn _orig = (orig); \
1313 volatile unsigned long _argvec[7]; \
1314 volatile unsigned long _res; \
1315 _argvec[0] = (unsigned long)_orig.nraddr; \
1316 _argvec[1] = (unsigned long)(arg1); \
1317 _argvec[2] = (unsigned long)(arg2); \
1318 _argvec[3] = (unsigned long)(arg3); \
1319 _argvec[4] = (unsigned long)(arg4); \
1320 _argvec[5] = (unsigned long)(arg5); \
1321 _argvec[6] = (unsigned long)(arg6); \
1322 __asm__ volatile( \
1323 VALGRIND_ALIGN_STACK \
1324 "subl $8, %%esp\n\t" \
1325 "pushl 24(%%eax)\n\t" \
1326 "pushl 20(%%eax)\n\t" \
1327 "pushl 16(%%eax)\n\t" \
1328 "pushl 12(%%eax)\n\t" \
1329 "pushl 8(%%eax)\n\t" \
1330 "pushl 4(%%eax)\n\t" \
1331 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1332 VALGRIND_CALL_NOREDIR_EAX \
1333 VALGRIND_RESTORE_STACK \
1334 : /*out*/ "=a" (_res) \
1335 : /*in*/ "a" (&_argvec[0]) \
1336 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1337 ); \
1338 lval = (__typeof__(lval)) _res; \
1339 } while (0)
1341 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1342 arg7) \
1343 do { \
1344 volatile OrigFn _orig = (orig); \
1345 volatile unsigned long _argvec[8]; \
1346 volatile unsigned long _res; \
1347 _argvec[0] = (unsigned long)_orig.nraddr; \
1348 _argvec[1] = (unsigned long)(arg1); \
1349 _argvec[2] = (unsigned long)(arg2); \
1350 _argvec[3] = (unsigned long)(arg3); \
1351 _argvec[4] = (unsigned long)(arg4); \
1352 _argvec[5] = (unsigned long)(arg5); \
1353 _argvec[6] = (unsigned long)(arg6); \
1354 _argvec[7] = (unsigned long)(arg7); \
1355 __asm__ volatile( \
1356 VALGRIND_ALIGN_STACK \
1357 "subl $4, %%esp\n\t" \
1358 "pushl 28(%%eax)\n\t" \
1359 "pushl 24(%%eax)\n\t" \
1360 "pushl 20(%%eax)\n\t" \
1361 "pushl 16(%%eax)\n\t" \
1362 "pushl 12(%%eax)\n\t" \
1363 "pushl 8(%%eax)\n\t" \
1364 "pushl 4(%%eax)\n\t" \
1365 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1366 VALGRIND_CALL_NOREDIR_EAX \
1367 VALGRIND_RESTORE_STACK \
1368 : /*out*/ "=a" (_res) \
1369 : /*in*/ "a" (&_argvec[0]) \
1370 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1371 ); \
1372 lval = (__typeof__(lval)) _res; \
1373 } while (0)
1375 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1376 arg7,arg8) \
1377 do { \
1378 volatile OrigFn _orig = (orig); \
1379 volatile unsigned long _argvec[9]; \
1380 volatile unsigned long _res; \
1381 _argvec[0] = (unsigned long)_orig.nraddr; \
1382 _argvec[1] = (unsigned long)(arg1); \
1383 _argvec[2] = (unsigned long)(arg2); \
1384 _argvec[3] = (unsigned long)(arg3); \
1385 _argvec[4] = (unsigned long)(arg4); \
1386 _argvec[5] = (unsigned long)(arg5); \
1387 _argvec[6] = (unsigned long)(arg6); \
1388 _argvec[7] = (unsigned long)(arg7); \
1389 _argvec[8] = (unsigned long)(arg8); \
1390 __asm__ volatile( \
1391 VALGRIND_ALIGN_STACK \
1392 "pushl 32(%%eax)\n\t" \
1393 "pushl 28(%%eax)\n\t" \
1394 "pushl 24(%%eax)\n\t" \
1395 "pushl 20(%%eax)\n\t" \
1396 "pushl 16(%%eax)\n\t" \
1397 "pushl 12(%%eax)\n\t" \
1398 "pushl 8(%%eax)\n\t" \
1399 "pushl 4(%%eax)\n\t" \
1400 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1401 VALGRIND_CALL_NOREDIR_EAX \
1402 VALGRIND_RESTORE_STACK \
1403 : /*out*/ "=a" (_res) \
1404 : /*in*/ "a" (&_argvec[0]) \
1405 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1406 ); \
1407 lval = (__typeof__(lval)) _res; \
1408 } while (0)
1410 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1411 arg7,arg8,arg9) \
1412 do { \
1413 volatile OrigFn _orig = (orig); \
1414 volatile unsigned long _argvec[10]; \
1415 volatile unsigned long _res; \
1416 _argvec[0] = (unsigned long)_orig.nraddr; \
1417 _argvec[1] = (unsigned long)(arg1); \
1418 _argvec[2] = (unsigned long)(arg2); \
1419 _argvec[3] = (unsigned long)(arg3); \
1420 _argvec[4] = (unsigned long)(arg4); \
1421 _argvec[5] = (unsigned long)(arg5); \
1422 _argvec[6] = (unsigned long)(arg6); \
1423 _argvec[7] = (unsigned long)(arg7); \
1424 _argvec[8] = (unsigned long)(arg8); \
1425 _argvec[9] = (unsigned long)(arg9); \
1426 __asm__ volatile( \
1427 VALGRIND_ALIGN_STACK \
1428 "subl $12, %%esp\n\t" \
1429 "pushl 36(%%eax)\n\t" \
1430 "pushl 32(%%eax)\n\t" \
1431 "pushl 28(%%eax)\n\t" \
1432 "pushl 24(%%eax)\n\t" \
1433 "pushl 20(%%eax)\n\t" \
1434 "pushl 16(%%eax)\n\t" \
1435 "pushl 12(%%eax)\n\t" \
1436 "pushl 8(%%eax)\n\t" \
1437 "pushl 4(%%eax)\n\t" \
1438 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1439 VALGRIND_CALL_NOREDIR_EAX \
1440 VALGRIND_RESTORE_STACK \
1441 : /*out*/ "=a" (_res) \
1442 : /*in*/ "a" (&_argvec[0]) \
1443 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1444 ); \
1445 lval = (__typeof__(lval)) _res; \
1446 } while (0)
1448 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1449 arg7,arg8,arg9,arg10) \
1450 do { \
1451 volatile OrigFn _orig = (orig); \
1452 volatile unsigned long _argvec[11]; \
1453 volatile unsigned long _res; \
1454 _argvec[0] = (unsigned long)_orig.nraddr; \
1455 _argvec[1] = (unsigned long)(arg1); \
1456 _argvec[2] = (unsigned long)(arg2); \
1457 _argvec[3] = (unsigned long)(arg3); \
1458 _argvec[4] = (unsigned long)(arg4); \
1459 _argvec[5] = (unsigned long)(arg5); \
1460 _argvec[6] = (unsigned long)(arg6); \
1461 _argvec[7] = (unsigned long)(arg7); \
1462 _argvec[8] = (unsigned long)(arg8); \
1463 _argvec[9] = (unsigned long)(arg9); \
1464 _argvec[10] = (unsigned long)(arg10); \
1465 __asm__ volatile( \
1466 VALGRIND_ALIGN_STACK \
1467 "subl $8, %%esp\n\t" \
1468 "pushl 40(%%eax)\n\t" \
1469 "pushl 36(%%eax)\n\t" \
1470 "pushl 32(%%eax)\n\t" \
1471 "pushl 28(%%eax)\n\t" \
1472 "pushl 24(%%eax)\n\t" \
1473 "pushl 20(%%eax)\n\t" \
1474 "pushl 16(%%eax)\n\t" \
1475 "pushl 12(%%eax)\n\t" \
1476 "pushl 8(%%eax)\n\t" \
1477 "pushl 4(%%eax)\n\t" \
1478 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1479 VALGRIND_CALL_NOREDIR_EAX \
1480 VALGRIND_RESTORE_STACK \
1481 : /*out*/ "=a" (_res) \
1482 : /*in*/ "a" (&_argvec[0]) \
1483 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1484 ); \
1485 lval = (__typeof__(lval)) _res; \
1486 } while (0)
1488 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1489 arg6,arg7,arg8,arg9,arg10, \
1490 arg11) \
1491 do { \
1492 volatile OrigFn _orig = (orig); \
1493 volatile unsigned long _argvec[12]; \
1494 volatile unsigned long _res; \
1495 _argvec[0] = (unsigned long)_orig.nraddr; \
1496 _argvec[1] = (unsigned long)(arg1); \
1497 _argvec[2] = (unsigned long)(arg2); \
1498 _argvec[3] = (unsigned long)(arg3); \
1499 _argvec[4] = (unsigned long)(arg4); \
1500 _argvec[5] = (unsigned long)(arg5); \
1501 _argvec[6] = (unsigned long)(arg6); \
1502 _argvec[7] = (unsigned long)(arg7); \
1503 _argvec[8] = (unsigned long)(arg8); \
1504 _argvec[9] = (unsigned long)(arg9); \
1505 _argvec[10] = (unsigned long)(arg10); \
1506 _argvec[11] = (unsigned long)(arg11); \
1507 __asm__ volatile( \
1508 VALGRIND_ALIGN_STACK \
1509 "subl $4, %%esp\n\t" \
1510 "pushl 44(%%eax)\n\t" \
1511 "pushl 40(%%eax)\n\t" \
1512 "pushl 36(%%eax)\n\t" \
1513 "pushl 32(%%eax)\n\t" \
1514 "pushl 28(%%eax)\n\t" \
1515 "pushl 24(%%eax)\n\t" \
1516 "pushl 20(%%eax)\n\t" \
1517 "pushl 16(%%eax)\n\t" \
1518 "pushl 12(%%eax)\n\t" \
1519 "pushl 8(%%eax)\n\t" \
1520 "pushl 4(%%eax)\n\t" \
1521 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1522 VALGRIND_CALL_NOREDIR_EAX \
1523 VALGRIND_RESTORE_STACK \
1524 : /*out*/ "=a" (_res) \
1525 : /*in*/ "a" (&_argvec[0]) \
1526 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1527 ); \
1528 lval = (__typeof__(lval)) _res; \
1529 } while (0)
1531 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1532 arg6,arg7,arg8,arg9,arg10, \
1533 arg11,arg12) \
1534 do { \
1535 volatile OrigFn _orig = (orig); \
1536 volatile unsigned long _argvec[13]; \
1537 volatile unsigned long _res; \
1538 _argvec[0] = (unsigned long)_orig.nraddr; \
1539 _argvec[1] = (unsigned long)(arg1); \
1540 _argvec[2] = (unsigned long)(arg2); \
1541 _argvec[3] = (unsigned long)(arg3); \
1542 _argvec[4] = (unsigned long)(arg4); \
1543 _argvec[5] = (unsigned long)(arg5); \
1544 _argvec[6] = (unsigned long)(arg6); \
1545 _argvec[7] = (unsigned long)(arg7); \
1546 _argvec[8] = (unsigned long)(arg8); \
1547 _argvec[9] = (unsigned long)(arg9); \
1548 _argvec[10] = (unsigned long)(arg10); \
1549 _argvec[11] = (unsigned long)(arg11); \
1550 _argvec[12] = (unsigned long)(arg12); \
1551 __asm__ volatile( \
1552 VALGRIND_ALIGN_STACK \
1553 "pushl 48(%%eax)\n\t" \
1554 "pushl 44(%%eax)\n\t" \
1555 "pushl 40(%%eax)\n\t" \
1556 "pushl 36(%%eax)\n\t" \
1557 "pushl 32(%%eax)\n\t" \
1558 "pushl 28(%%eax)\n\t" \
1559 "pushl 24(%%eax)\n\t" \
1560 "pushl 20(%%eax)\n\t" \
1561 "pushl 16(%%eax)\n\t" \
1562 "pushl 12(%%eax)\n\t" \
1563 "pushl 8(%%eax)\n\t" \
1564 "pushl 4(%%eax)\n\t" \
1565 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1566 VALGRIND_CALL_NOREDIR_EAX \
1567 VALGRIND_RESTORE_STACK \
1568 : /*out*/ "=a" (_res) \
1569 : /*in*/ "a" (&_argvec[0]) \
1570 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
1571 ); \
1572 lval = (__typeof__(lval)) _res; \
1573 } while (0)
1575 #endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_solaris */
1577 /* ---------------- amd64-{linux,darwin,solaris} --------------- */
1579 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
1580 || defined(PLAT_amd64_solaris)
1582 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1584 /* These regs are trashed by the hidden call. */
1585 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1586 "rdi", "r8", "r9", "r10", "r11"
1588 /* This is all pretty complex. It's so as to make stack unwinding
1589 work reliably. See bug 243270. The basic problem is the sub and
1590 add of 128 of %rsp in all of the following macros. If gcc believes
1591 the CFA is in %rsp, then unwinding may fail, because what's at the
1592 CFA is not what gcc "expected" when it constructs the CFIs for the
1593 places where the macros are instantiated.
1595 But we can't just add a CFI annotation to increase the CFA offset
1596 by 128, to match the sub of 128 from %rsp, because we don't know
1597 whether gcc has chosen %rsp as the CFA at that point, or whether it
1598 has chosen some other register (eg, %rbp). In the latter case,
1599 adding a CFI annotation to change the CFA offset is simply wrong.
1601 So the solution is to get hold of the CFA using
1602 __builtin_dwarf_cfa(), put it in a known register, and add a
1603 CFI annotation to say what the register is. We choose %rbp for
1604 this (perhaps perversely), because:
1606 (1) %rbp is already subject to unwinding. If a new register was
1607 chosen then the unwinder would have to unwind it in all stack
1608 traces, which is expensive, and
1610 (2) %rbp is already subject to precise exception updates in the
1611 JIT. If a new register was chosen, we'd have to have precise
1612 exceptions for it too, which reduces performance of the
1613 generated code.
1615 However .. one extra complication. We can't just whack the result
1616 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
1617 list of trashed registers at the end of the inline assembly
1618 fragments; gcc won't allow %rbp to appear in that list. Hence
1619 instead we need to stash %rbp in %r15 for the duration of the asm,
1620 and say that %r15 is trashed instead. gcc seems happy to go with
1621 that.
1623 Oh .. and this all needs to be conditionalised so that it is
1624 unchanged from before this commit, when compiled with older gccs
1625 that don't support __builtin_dwarf_cfa. Furthermore, since
1626 this header file is freestanding, it has to be independent of
1627 config.h, and so the following conditionalisation cannot depend on
1628 configure time checks.
1630 Although it's not clear from
1631 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1632 this expression excludes Darwin.
1633 .cfi directives in Darwin assembly appear to be completely
1634 different and I haven't investigated how they work.
1636 For even more entertainment value, note we have to use the
1637 completely undocumented __builtin_dwarf_cfa(), which appears to
1638 really compute the CFA, whereas __builtin_frame_address(0) claims
1639 to but actually doesn't. See
1640 https://bugs.kde.org/show_bug.cgi?id=243270#c47
1642 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
1643 # define __FRAME_POINTER \
1644 ,"r"(__builtin_dwarf_cfa())
1645 # define VALGRIND_CFI_PROLOGUE \
1646 "movq %%rbp, %%r15\n\t" \
1647 "movq %2, %%rbp\n\t" \
1648 ".cfi_remember_state\n\t" \
1649 ".cfi_def_cfa rbp, 0\n\t"
1650 # define VALGRIND_CFI_EPILOGUE \
1651 "movq %%r15, %%rbp\n\t" \
1652 ".cfi_restore_state\n\t"
1653 #else
1654 # define __FRAME_POINTER
1655 # define VALGRIND_CFI_PROLOGUE
1656 # define VALGRIND_CFI_EPILOGUE
1657 #endif
1659 /* Macros to save and align the stack before making a function
1660 call and restore it afterwards as gcc may not keep the stack
1661 pointer aligned if it doesn't realise calls are being made
1662 to other functions. */
1664 #define VALGRIND_ALIGN_STACK \
1665 "movq %%rsp,%%r14\n\t" \
1666 "andq $0xfffffffffffffff0,%%rsp\n\t"
1667 #define VALGRIND_RESTORE_STACK \
1668 "movq %%r14,%%rsp\n\t"
1670 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1671 long) == 8. */
1673 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1674 macros. In order not to trash the stack redzone, we need to drop
1675 %rsp by 128 before the hidden call, and restore afterwards. The
1676 nastyness is that it is only by luck that the stack still appears
1677 to be unwindable during the hidden call - since then the behaviour
1678 of any routine using this macro does not match what the CFI data
1679 says. Sigh.
1681 Why is this important? Imagine that a wrapper has a stack
1682 allocated local, and passes to the hidden call, a pointer to it.
1683 Because gcc does not know about the hidden call, it may allocate
1684 that local in the redzone. Unfortunately the hidden call may then
1685 trash it before it comes to use it. So we must step clear of the
1686 redzone, for the duration of the hidden call, to make it safe.
1688 Probably the same problem afflicts the other redzone-style ABIs too
1689 (ppc64-linux); but for those, the stack is
1690 self describing (none of this CFI nonsense) so at least messing
1691 with the stack pointer doesn't give a danger of non-unwindable
1692 stack. */
1694 #define CALL_FN_W_v(lval, orig) \
1695 do { \
1696 volatile OrigFn _orig = (orig); \
1697 volatile unsigned long _argvec[1]; \
1698 volatile unsigned long _res; \
1699 _argvec[0] = (unsigned long)_orig.nraddr; \
1700 __asm__ volatile( \
1701 VALGRIND_CFI_PROLOGUE \
1702 VALGRIND_ALIGN_STACK \
1703 "subq $128,%%rsp\n\t" \
1704 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1705 VALGRIND_CALL_NOREDIR_RAX \
1706 VALGRIND_RESTORE_STACK \
1707 VALGRIND_CFI_EPILOGUE \
1708 : /*out*/ "=a" (_res) \
1709 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1710 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1711 ); \
1712 lval = (__typeof__(lval)) _res; \
1713 } while (0)
1715 #define CALL_FN_W_W(lval, orig, arg1) \
1716 do { \
1717 volatile OrigFn _orig = (orig); \
1718 volatile unsigned long _argvec[2]; \
1719 volatile unsigned long _res; \
1720 _argvec[0] = (unsigned long)_orig.nraddr; \
1721 _argvec[1] = (unsigned long)(arg1); \
1722 __asm__ volatile( \
1723 VALGRIND_CFI_PROLOGUE \
1724 VALGRIND_ALIGN_STACK \
1725 "subq $128,%%rsp\n\t" \
1726 "movq 8(%%rax), %%rdi\n\t" \
1727 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1728 VALGRIND_CALL_NOREDIR_RAX \
1729 VALGRIND_RESTORE_STACK \
1730 VALGRIND_CFI_EPILOGUE \
1731 : /*out*/ "=a" (_res) \
1732 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1733 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1734 ); \
1735 lval = (__typeof__(lval)) _res; \
1736 } while (0)
1738 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1739 do { \
1740 volatile OrigFn _orig = (orig); \
1741 volatile unsigned long _argvec[3]; \
1742 volatile unsigned long _res; \
1743 _argvec[0] = (unsigned long)_orig.nraddr; \
1744 _argvec[1] = (unsigned long)(arg1); \
1745 _argvec[2] = (unsigned long)(arg2); \
1746 __asm__ volatile( \
1747 VALGRIND_CFI_PROLOGUE \
1748 VALGRIND_ALIGN_STACK \
1749 "subq $128,%%rsp\n\t" \
1750 "movq 16(%%rax), %%rsi\n\t" \
1751 "movq 8(%%rax), %%rdi\n\t" \
1752 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1753 VALGRIND_CALL_NOREDIR_RAX \
1754 VALGRIND_RESTORE_STACK \
1755 VALGRIND_CFI_EPILOGUE \
1756 : /*out*/ "=a" (_res) \
1757 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1758 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1759 ); \
1760 lval = (__typeof__(lval)) _res; \
1761 } while (0)
1763 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1764 do { \
1765 volatile OrigFn _orig = (orig); \
1766 volatile unsigned long _argvec[4]; \
1767 volatile unsigned long _res; \
1768 _argvec[0] = (unsigned long)_orig.nraddr; \
1769 _argvec[1] = (unsigned long)(arg1); \
1770 _argvec[2] = (unsigned long)(arg2); \
1771 _argvec[3] = (unsigned long)(arg3); \
1772 __asm__ volatile( \
1773 VALGRIND_CFI_PROLOGUE \
1774 VALGRIND_ALIGN_STACK \
1775 "subq $128,%%rsp\n\t" \
1776 "movq 24(%%rax), %%rdx\n\t" \
1777 "movq 16(%%rax), %%rsi\n\t" \
1778 "movq 8(%%rax), %%rdi\n\t" \
1779 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1780 VALGRIND_CALL_NOREDIR_RAX \
1781 VALGRIND_RESTORE_STACK \
1782 VALGRIND_CFI_EPILOGUE \
1783 : /*out*/ "=a" (_res) \
1784 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1785 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1786 ); \
1787 lval = (__typeof__(lval)) _res; \
1788 } while (0)
1790 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1791 do { \
1792 volatile OrigFn _orig = (orig); \
1793 volatile unsigned long _argvec[5]; \
1794 volatile unsigned long _res; \
1795 _argvec[0] = (unsigned long)_orig.nraddr; \
1796 _argvec[1] = (unsigned long)(arg1); \
1797 _argvec[2] = (unsigned long)(arg2); \
1798 _argvec[3] = (unsigned long)(arg3); \
1799 _argvec[4] = (unsigned long)(arg4); \
1800 __asm__ volatile( \
1801 VALGRIND_CFI_PROLOGUE \
1802 VALGRIND_ALIGN_STACK \
1803 "subq $128,%%rsp\n\t" \
1804 "movq 32(%%rax), %%rcx\n\t" \
1805 "movq 24(%%rax), %%rdx\n\t" \
1806 "movq 16(%%rax), %%rsi\n\t" \
1807 "movq 8(%%rax), %%rdi\n\t" \
1808 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1809 VALGRIND_CALL_NOREDIR_RAX \
1810 VALGRIND_RESTORE_STACK \
1811 VALGRIND_CFI_EPILOGUE \
1812 : /*out*/ "=a" (_res) \
1813 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1814 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1815 ); \
1816 lval = (__typeof__(lval)) _res; \
1817 } while (0)
1819 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1820 do { \
1821 volatile OrigFn _orig = (orig); \
1822 volatile unsigned long _argvec[6]; \
1823 volatile unsigned long _res; \
1824 _argvec[0] = (unsigned long)_orig.nraddr; \
1825 _argvec[1] = (unsigned long)(arg1); \
1826 _argvec[2] = (unsigned long)(arg2); \
1827 _argvec[3] = (unsigned long)(arg3); \
1828 _argvec[4] = (unsigned long)(arg4); \
1829 _argvec[5] = (unsigned long)(arg5); \
1830 __asm__ volatile( \
1831 VALGRIND_CFI_PROLOGUE \
1832 VALGRIND_ALIGN_STACK \
1833 "subq $128,%%rsp\n\t" \
1834 "movq 40(%%rax), %%r8\n\t" \
1835 "movq 32(%%rax), %%rcx\n\t" \
1836 "movq 24(%%rax), %%rdx\n\t" \
1837 "movq 16(%%rax), %%rsi\n\t" \
1838 "movq 8(%%rax), %%rdi\n\t" \
1839 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1840 VALGRIND_CALL_NOREDIR_RAX \
1841 VALGRIND_RESTORE_STACK \
1842 VALGRIND_CFI_EPILOGUE \
1843 : /*out*/ "=a" (_res) \
1844 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1845 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1846 ); \
1847 lval = (__typeof__(lval)) _res; \
1848 } while (0)
1850 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1851 do { \
1852 volatile OrigFn _orig = (orig); \
1853 volatile unsigned long _argvec[7]; \
1854 volatile unsigned long _res; \
1855 _argvec[0] = (unsigned long)_orig.nraddr; \
1856 _argvec[1] = (unsigned long)(arg1); \
1857 _argvec[2] = (unsigned long)(arg2); \
1858 _argvec[3] = (unsigned long)(arg3); \
1859 _argvec[4] = (unsigned long)(arg4); \
1860 _argvec[5] = (unsigned long)(arg5); \
1861 _argvec[6] = (unsigned long)(arg6); \
1862 __asm__ volatile( \
1863 VALGRIND_CFI_PROLOGUE \
1864 VALGRIND_ALIGN_STACK \
1865 "subq $128,%%rsp\n\t" \
1866 "movq 48(%%rax), %%r9\n\t" \
1867 "movq 40(%%rax), %%r8\n\t" \
1868 "movq 32(%%rax), %%rcx\n\t" \
1869 "movq 24(%%rax), %%rdx\n\t" \
1870 "movq 16(%%rax), %%rsi\n\t" \
1871 "movq 8(%%rax), %%rdi\n\t" \
1872 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1873 VALGRIND_CALL_NOREDIR_RAX \
1874 VALGRIND_RESTORE_STACK \
1875 VALGRIND_CFI_EPILOGUE \
1876 : /*out*/ "=a" (_res) \
1877 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1878 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1879 ); \
1880 lval = (__typeof__(lval)) _res; \
1881 } while (0)
1883 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1884 arg7) \
1885 do { \
1886 volatile OrigFn _orig = (orig); \
1887 volatile unsigned long _argvec[8]; \
1888 volatile unsigned long _res; \
1889 _argvec[0] = (unsigned long)_orig.nraddr; \
1890 _argvec[1] = (unsigned long)(arg1); \
1891 _argvec[2] = (unsigned long)(arg2); \
1892 _argvec[3] = (unsigned long)(arg3); \
1893 _argvec[4] = (unsigned long)(arg4); \
1894 _argvec[5] = (unsigned long)(arg5); \
1895 _argvec[6] = (unsigned long)(arg6); \
1896 _argvec[7] = (unsigned long)(arg7); \
1897 __asm__ volatile( \
1898 VALGRIND_CFI_PROLOGUE \
1899 VALGRIND_ALIGN_STACK \
1900 "subq $136,%%rsp\n\t" \
1901 "pushq 56(%%rax)\n\t" \
1902 "movq 48(%%rax), %%r9\n\t" \
1903 "movq 40(%%rax), %%r8\n\t" \
1904 "movq 32(%%rax), %%rcx\n\t" \
1905 "movq 24(%%rax), %%rdx\n\t" \
1906 "movq 16(%%rax), %%rsi\n\t" \
1907 "movq 8(%%rax), %%rdi\n\t" \
1908 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1909 VALGRIND_CALL_NOREDIR_RAX \
1910 VALGRIND_RESTORE_STACK \
1911 VALGRIND_CFI_EPILOGUE \
1912 : /*out*/ "=a" (_res) \
1913 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1914 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1915 ); \
1916 lval = (__typeof__(lval)) _res; \
1917 } while (0)
1919 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1920 arg7,arg8) \
1921 do { \
1922 volatile OrigFn _orig = (orig); \
1923 volatile unsigned long _argvec[9]; \
1924 volatile unsigned long _res; \
1925 _argvec[0] = (unsigned long)_orig.nraddr; \
1926 _argvec[1] = (unsigned long)(arg1); \
1927 _argvec[2] = (unsigned long)(arg2); \
1928 _argvec[3] = (unsigned long)(arg3); \
1929 _argvec[4] = (unsigned long)(arg4); \
1930 _argvec[5] = (unsigned long)(arg5); \
1931 _argvec[6] = (unsigned long)(arg6); \
1932 _argvec[7] = (unsigned long)(arg7); \
1933 _argvec[8] = (unsigned long)(arg8); \
1934 __asm__ volatile( \
1935 VALGRIND_CFI_PROLOGUE \
1936 VALGRIND_ALIGN_STACK \
1937 "subq $128,%%rsp\n\t" \
1938 "pushq 64(%%rax)\n\t" \
1939 "pushq 56(%%rax)\n\t" \
1940 "movq 48(%%rax), %%r9\n\t" \
1941 "movq 40(%%rax), %%r8\n\t" \
1942 "movq 32(%%rax), %%rcx\n\t" \
1943 "movq 24(%%rax), %%rdx\n\t" \
1944 "movq 16(%%rax), %%rsi\n\t" \
1945 "movq 8(%%rax), %%rdi\n\t" \
1946 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1947 VALGRIND_CALL_NOREDIR_RAX \
1948 VALGRIND_RESTORE_STACK \
1949 VALGRIND_CFI_EPILOGUE \
1950 : /*out*/ "=a" (_res) \
1951 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1952 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1953 ); \
1954 lval = (__typeof__(lval)) _res; \
1955 } while (0)
1957 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1958 arg7,arg8,arg9) \
1959 do { \
1960 volatile OrigFn _orig = (orig); \
1961 volatile unsigned long _argvec[10]; \
1962 volatile unsigned long _res; \
1963 _argvec[0] = (unsigned long)_orig.nraddr; \
1964 _argvec[1] = (unsigned long)(arg1); \
1965 _argvec[2] = (unsigned long)(arg2); \
1966 _argvec[3] = (unsigned long)(arg3); \
1967 _argvec[4] = (unsigned long)(arg4); \
1968 _argvec[5] = (unsigned long)(arg5); \
1969 _argvec[6] = (unsigned long)(arg6); \
1970 _argvec[7] = (unsigned long)(arg7); \
1971 _argvec[8] = (unsigned long)(arg8); \
1972 _argvec[9] = (unsigned long)(arg9); \
1973 __asm__ volatile( \
1974 VALGRIND_CFI_PROLOGUE \
1975 VALGRIND_ALIGN_STACK \
1976 "subq $136,%%rsp\n\t" \
1977 "pushq 72(%%rax)\n\t" \
1978 "pushq 64(%%rax)\n\t" \
1979 "pushq 56(%%rax)\n\t" \
1980 "movq 48(%%rax), %%r9\n\t" \
1981 "movq 40(%%rax), %%r8\n\t" \
1982 "movq 32(%%rax), %%rcx\n\t" \
1983 "movq 24(%%rax), %%rdx\n\t" \
1984 "movq 16(%%rax), %%rsi\n\t" \
1985 "movq 8(%%rax), %%rdi\n\t" \
1986 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1987 VALGRIND_CALL_NOREDIR_RAX \
1988 VALGRIND_RESTORE_STACK \
1989 VALGRIND_CFI_EPILOGUE \
1990 : /*out*/ "=a" (_res) \
1991 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1992 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1993 ); \
1994 lval = (__typeof__(lval)) _res; \
1995 } while (0)
1997 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1998 arg7,arg8,arg9,arg10) \
1999 do { \
2000 volatile OrigFn _orig = (orig); \
2001 volatile unsigned long _argvec[11]; \
2002 volatile unsigned long _res; \
2003 _argvec[0] = (unsigned long)_orig.nraddr; \
2004 _argvec[1] = (unsigned long)(arg1); \
2005 _argvec[2] = (unsigned long)(arg2); \
2006 _argvec[3] = (unsigned long)(arg3); \
2007 _argvec[4] = (unsigned long)(arg4); \
2008 _argvec[5] = (unsigned long)(arg5); \
2009 _argvec[6] = (unsigned long)(arg6); \
2010 _argvec[7] = (unsigned long)(arg7); \
2011 _argvec[8] = (unsigned long)(arg8); \
2012 _argvec[9] = (unsigned long)(arg9); \
2013 _argvec[10] = (unsigned long)(arg10); \
2014 __asm__ volatile( \
2015 VALGRIND_CFI_PROLOGUE \
2016 VALGRIND_ALIGN_STACK \
2017 "subq $128,%%rsp\n\t" \
2018 "pushq 80(%%rax)\n\t" \
2019 "pushq 72(%%rax)\n\t" \
2020 "pushq 64(%%rax)\n\t" \
2021 "pushq 56(%%rax)\n\t" \
2022 "movq 48(%%rax), %%r9\n\t" \
2023 "movq 40(%%rax), %%r8\n\t" \
2024 "movq 32(%%rax), %%rcx\n\t" \
2025 "movq 24(%%rax), %%rdx\n\t" \
2026 "movq 16(%%rax), %%rsi\n\t" \
2027 "movq 8(%%rax), %%rdi\n\t" \
2028 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2029 VALGRIND_CALL_NOREDIR_RAX \
2030 VALGRIND_RESTORE_STACK \
2031 VALGRIND_CFI_EPILOGUE \
2032 : /*out*/ "=a" (_res) \
2033 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2034 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2035 ); \
2036 lval = (__typeof__(lval)) _res; \
2037 } while (0)
2039 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2040 arg7,arg8,arg9,arg10,arg11) \
2041 do { \
2042 volatile OrigFn _orig = (orig); \
2043 volatile unsigned long _argvec[12]; \
2044 volatile unsigned long _res; \
2045 _argvec[0] = (unsigned long)_orig.nraddr; \
2046 _argvec[1] = (unsigned long)(arg1); \
2047 _argvec[2] = (unsigned long)(arg2); \
2048 _argvec[3] = (unsigned long)(arg3); \
2049 _argvec[4] = (unsigned long)(arg4); \
2050 _argvec[5] = (unsigned long)(arg5); \
2051 _argvec[6] = (unsigned long)(arg6); \
2052 _argvec[7] = (unsigned long)(arg7); \
2053 _argvec[8] = (unsigned long)(arg8); \
2054 _argvec[9] = (unsigned long)(arg9); \
2055 _argvec[10] = (unsigned long)(arg10); \
2056 _argvec[11] = (unsigned long)(arg11); \
2057 __asm__ volatile( \
2058 VALGRIND_CFI_PROLOGUE \
2059 VALGRIND_ALIGN_STACK \
2060 "subq $136,%%rsp\n\t" \
2061 "pushq 88(%%rax)\n\t" \
2062 "pushq 80(%%rax)\n\t" \
2063 "pushq 72(%%rax)\n\t" \
2064 "pushq 64(%%rax)\n\t" \
2065 "pushq 56(%%rax)\n\t" \
2066 "movq 48(%%rax), %%r9\n\t" \
2067 "movq 40(%%rax), %%r8\n\t" \
2068 "movq 32(%%rax), %%rcx\n\t" \
2069 "movq 24(%%rax), %%rdx\n\t" \
2070 "movq 16(%%rax), %%rsi\n\t" \
2071 "movq 8(%%rax), %%rdi\n\t" \
2072 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2073 VALGRIND_CALL_NOREDIR_RAX \
2074 VALGRIND_RESTORE_STACK \
2075 VALGRIND_CFI_EPILOGUE \
2076 : /*out*/ "=a" (_res) \
2077 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2078 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2079 ); \
2080 lval = (__typeof__(lval)) _res; \
2081 } while (0)
2083 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2084 arg7,arg8,arg9,arg10,arg11,arg12) \
2085 do { \
2086 volatile OrigFn _orig = (orig); \
2087 volatile unsigned long _argvec[13]; \
2088 volatile unsigned long _res; \
2089 _argvec[0] = (unsigned long)_orig.nraddr; \
2090 _argvec[1] = (unsigned long)(arg1); \
2091 _argvec[2] = (unsigned long)(arg2); \
2092 _argvec[3] = (unsigned long)(arg3); \
2093 _argvec[4] = (unsigned long)(arg4); \
2094 _argvec[5] = (unsigned long)(arg5); \
2095 _argvec[6] = (unsigned long)(arg6); \
2096 _argvec[7] = (unsigned long)(arg7); \
2097 _argvec[8] = (unsigned long)(arg8); \
2098 _argvec[9] = (unsigned long)(arg9); \
2099 _argvec[10] = (unsigned long)(arg10); \
2100 _argvec[11] = (unsigned long)(arg11); \
2101 _argvec[12] = (unsigned long)(arg12); \
2102 __asm__ volatile( \
2103 VALGRIND_CFI_PROLOGUE \
2104 VALGRIND_ALIGN_STACK \
2105 "subq $128,%%rsp\n\t" \
2106 "pushq 96(%%rax)\n\t" \
2107 "pushq 88(%%rax)\n\t" \
2108 "pushq 80(%%rax)\n\t" \
2109 "pushq 72(%%rax)\n\t" \
2110 "pushq 64(%%rax)\n\t" \
2111 "pushq 56(%%rax)\n\t" \
2112 "movq 48(%%rax), %%r9\n\t" \
2113 "movq 40(%%rax), %%r8\n\t" \
2114 "movq 32(%%rax), %%rcx\n\t" \
2115 "movq 24(%%rax), %%rdx\n\t" \
2116 "movq 16(%%rax), %%rsi\n\t" \
2117 "movq 8(%%rax), %%rdi\n\t" \
2118 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2119 VALGRIND_CALL_NOREDIR_RAX \
2120 VALGRIND_RESTORE_STACK \
2121 VALGRIND_CFI_EPILOGUE \
2122 : /*out*/ "=a" (_res) \
2123 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2124 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2125 ); \
2126 lval = (__typeof__(lval)) _res; \
2127 } while (0)
2129 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
2131 /* ------------------------ ppc32-linux ------------------------ */
2133 #if defined(PLAT_ppc32_linux)
2135 /* This is useful for finding out about the on-stack stuff:
2137 extern int f9 ( int,int,int,int,int,int,int,int,int );
2138 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2139 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2140 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2142 int g9 ( void ) {
2143 return f9(11,22,33,44,55,66,77,88,99);
2145 int g10 ( void ) {
2146 return f10(11,22,33,44,55,66,77,88,99,110);
2148 int g11 ( void ) {
2149 return f11(11,22,33,44,55,66,77,88,99,110,121);
2151 int g12 ( void ) {
2152 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2156 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2158 /* These regs are trashed by the hidden call. */
2159 #define __CALLER_SAVED_REGS \
2160 "lr", "ctr", "xer", \
2161 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2162 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2163 "r11", "r12", "r13"
2165 /* Macros to save and align the stack before making a function
2166 call and restore it afterwards as gcc may not keep the stack
2167 pointer aligned if it doesn't realise calls are being made
2168 to other functions. */
2170 #define VALGRIND_ALIGN_STACK \
2171 "mr 28,1\n\t" \
2172 "rlwinm 1,1,0,0,27\n\t"
2173 #define VALGRIND_RESTORE_STACK \
2174 "mr 1,28\n\t"
2176 /* These CALL_FN_ macros assume that on ppc32-linux,
2177 sizeof(unsigned long) == 4. */
2179 #define CALL_FN_W_v(lval, orig) \
2180 do { \
2181 volatile OrigFn _orig = (orig); \
2182 volatile unsigned long _argvec[1]; \
2183 volatile unsigned long _res; \
2184 _argvec[0] = (unsigned long)_orig.nraddr; \
2185 __asm__ volatile( \
2186 VALGRIND_ALIGN_STACK \
2187 "mr 11,%1\n\t" \
2188 "lwz 11,0(11)\n\t" /* target->r11 */ \
2189 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2190 VALGRIND_RESTORE_STACK \
2191 "mr %0,3" \
2192 : /*out*/ "=r" (_res) \
2193 : /*in*/ "r" (&_argvec[0]) \
2194 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2195 ); \
2196 lval = (__typeof__(lval)) _res; \
2197 } while (0)
2199 #define CALL_FN_W_W(lval, orig, arg1) \
2200 do { \
2201 volatile OrigFn _orig = (orig); \
2202 volatile unsigned long _argvec[2]; \
2203 volatile unsigned long _res; \
2204 _argvec[0] = (unsigned long)_orig.nraddr; \
2205 _argvec[1] = (unsigned long)arg1; \
2206 __asm__ volatile( \
2207 VALGRIND_ALIGN_STACK \
2208 "mr 11,%1\n\t" \
2209 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2210 "lwz 11,0(11)\n\t" /* target->r11 */ \
2211 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2212 VALGRIND_RESTORE_STACK \
2213 "mr %0,3" \
2214 : /*out*/ "=r" (_res) \
2215 : /*in*/ "r" (&_argvec[0]) \
2216 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2217 ); \
2218 lval = (__typeof__(lval)) _res; \
2219 } while (0)
2221 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2222 do { \
2223 volatile OrigFn _orig = (orig); \
2224 volatile unsigned long _argvec[3]; \
2225 volatile unsigned long _res; \
2226 _argvec[0] = (unsigned long)_orig.nraddr; \
2227 _argvec[1] = (unsigned long)arg1; \
2228 _argvec[2] = (unsigned long)arg2; \
2229 __asm__ volatile( \
2230 VALGRIND_ALIGN_STACK \
2231 "mr 11,%1\n\t" \
2232 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2233 "lwz 4,8(11)\n\t" \
2234 "lwz 11,0(11)\n\t" /* target->r11 */ \
2235 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2236 VALGRIND_RESTORE_STACK \
2237 "mr %0,3" \
2238 : /*out*/ "=r" (_res) \
2239 : /*in*/ "r" (&_argvec[0]) \
2240 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2241 ); \
2242 lval = (__typeof__(lval)) _res; \
2243 } while (0)
2245 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2246 do { \
2247 volatile OrigFn _orig = (orig); \
2248 volatile unsigned long _argvec[4]; \
2249 volatile unsigned long _res; \
2250 _argvec[0] = (unsigned long)_orig.nraddr; \
2251 _argvec[1] = (unsigned long)arg1; \
2252 _argvec[2] = (unsigned long)arg2; \
2253 _argvec[3] = (unsigned long)arg3; \
2254 __asm__ volatile( \
2255 VALGRIND_ALIGN_STACK \
2256 "mr 11,%1\n\t" \
2257 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2258 "lwz 4,8(11)\n\t" \
2259 "lwz 5,12(11)\n\t" \
2260 "lwz 11,0(11)\n\t" /* target->r11 */ \
2261 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2262 VALGRIND_RESTORE_STACK \
2263 "mr %0,3" \
2264 : /*out*/ "=r" (_res) \
2265 : /*in*/ "r" (&_argvec[0]) \
2266 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2267 ); \
2268 lval = (__typeof__(lval)) _res; \
2269 } while (0)
2271 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2272 do { \
2273 volatile OrigFn _orig = (orig); \
2274 volatile unsigned long _argvec[5]; \
2275 volatile unsigned long _res; \
2276 _argvec[0] = (unsigned long)_orig.nraddr; \
2277 _argvec[1] = (unsigned long)arg1; \
2278 _argvec[2] = (unsigned long)arg2; \
2279 _argvec[3] = (unsigned long)arg3; \
2280 _argvec[4] = (unsigned long)arg4; \
2281 __asm__ volatile( \
2282 VALGRIND_ALIGN_STACK \
2283 "mr 11,%1\n\t" \
2284 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2285 "lwz 4,8(11)\n\t" \
2286 "lwz 5,12(11)\n\t" \
2287 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2288 "lwz 11,0(11)\n\t" /* target->r11 */ \
2289 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2290 VALGRIND_RESTORE_STACK \
2291 "mr %0,3" \
2292 : /*out*/ "=r" (_res) \
2293 : /*in*/ "r" (&_argvec[0]) \
2294 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2295 ); \
2296 lval = (__typeof__(lval)) _res; \
2297 } while (0)
2299 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2300 do { \
2301 volatile OrigFn _orig = (orig); \
2302 volatile unsigned long _argvec[6]; \
2303 volatile unsigned long _res; \
2304 _argvec[0] = (unsigned long)_orig.nraddr; \
2305 _argvec[1] = (unsigned long)arg1; \
2306 _argvec[2] = (unsigned long)arg2; \
2307 _argvec[3] = (unsigned long)arg3; \
2308 _argvec[4] = (unsigned long)arg4; \
2309 _argvec[5] = (unsigned long)arg5; \
2310 __asm__ volatile( \
2311 VALGRIND_ALIGN_STACK \
2312 "mr 11,%1\n\t" \
2313 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2314 "lwz 4,8(11)\n\t" \
2315 "lwz 5,12(11)\n\t" \
2316 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2317 "lwz 7,20(11)\n\t" \
2318 "lwz 11,0(11)\n\t" /* target->r11 */ \
2319 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2320 VALGRIND_RESTORE_STACK \
2321 "mr %0,3" \
2322 : /*out*/ "=r" (_res) \
2323 : /*in*/ "r" (&_argvec[0]) \
2324 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2325 ); \
2326 lval = (__typeof__(lval)) _res; \
2327 } while (0)
2329 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2330 do { \
2331 volatile OrigFn _orig = (orig); \
2332 volatile unsigned long _argvec[7]; \
2333 volatile unsigned long _res; \
2334 _argvec[0] = (unsigned long)_orig.nraddr; \
2335 _argvec[1] = (unsigned long)arg1; \
2336 _argvec[2] = (unsigned long)arg2; \
2337 _argvec[3] = (unsigned long)arg3; \
2338 _argvec[4] = (unsigned long)arg4; \
2339 _argvec[5] = (unsigned long)arg5; \
2340 _argvec[6] = (unsigned long)arg6; \
2341 __asm__ volatile( \
2342 VALGRIND_ALIGN_STACK \
2343 "mr 11,%1\n\t" \
2344 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2345 "lwz 4,8(11)\n\t" \
2346 "lwz 5,12(11)\n\t" \
2347 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2348 "lwz 7,20(11)\n\t" \
2349 "lwz 8,24(11)\n\t" \
2350 "lwz 11,0(11)\n\t" /* target->r11 */ \
2351 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2352 VALGRIND_RESTORE_STACK \
2353 "mr %0,3" \
2354 : /*out*/ "=r" (_res) \
2355 : /*in*/ "r" (&_argvec[0]) \
2356 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2357 ); \
2358 lval = (__typeof__(lval)) _res; \
2359 } while (0)
2361 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2362 arg7) \
2363 do { \
2364 volatile OrigFn _orig = (orig); \
2365 volatile unsigned long _argvec[8]; \
2366 volatile unsigned long _res; \
2367 _argvec[0] = (unsigned long)_orig.nraddr; \
2368 _argvec[1] = (unsigned long)arg1; \
2369 _argvec[2] = (unsigned long)arg2; \
2370 _argvec[3] = (unsigned long)arg3; \
2371 _argvec[4] = (unsigned long)arg4; \
2372 _argvec[5] = (unsigned long)arg5; \
2373 _argvec[6] = (unsigned long)arg6; \
2374 _argvec[7] = (unsigned long)arg7; \
2375 __asm__ volatile( \
2376 VALGRIND_ALIGN_STACK \
2377 "mr 11,%1\n\t" \
2378 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2379 "lwz 4,8(11)\n\t" \
2380 "lwz 5,12(11)\n\t" \
2381 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2382 "lwz 7,20(11)\n\t" \
2383 "lwz 8,24(11)\n\t" \
2384 "lwz 9,28(11)\n\t" \
2385 "lwz 11,0(11)\n\t" /* target->r11 */ \
2386 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2387 VALGRIND_RESTORE_STACK \
2388 "mr %0,3" \
2389 : /*out*/ "=r" (_res) \
2390 : /*in*/ "r" (&_argvec[0]) \
2391 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2392 ); \
2393 lval = (__typeof__(lval)) _res; \
2394 } while (0)
2396 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2397 arg7,arg8) \
2398 do { \
2399 volatile OrigFn _orig = (orig); \
2400 volatile unsigned long _argvec[9]; \
2401 volatile unsigned long _res; \
2402 _argvec[0] = (unsigned long)_orig.nraddr; \
2403 _argvec[1] = (unsigned long)arg1; \
2404 _argvec[2] = (unsigned long)arg2; \
2405 _argvec[3] = (unsigned long)arg3; \
2406 _argvec[4] = (unsigned long)arg4; \
2407 _argvec[5] = (unsigned long)arg5; \
2408 _argvec[6] = (unsigned long)arg6; \
2409 _argvec[7] = (unsigned long)arg7; \
2410 _argvec[8] = (unsigned long)arg8; \
2411 __asm__ volatile( \
2412 VALGRIND_ALIGN_STACK \
2413 "mr 11,%1\n\t" \
2414 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2415 "lwz 4,8(11)\n\t" \
2416 "lwz 5,12(11)\n\t" \
2417 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2418 "lwz 7,20(11)\n\t" \
2419 "lwz 8,24(11)\n\t" \
2420 "lwz 9,28(11)\n\t" \
2421 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2422 "lwz 11,0(11)\n\t" /* target->r11 */ \
2423 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2424 VALGRIND_RESTORE_STACK \
2425 "mr %0,3" \
2426 : /*out*/ "=r" (_res) \
2427 : /*in*/ "r" (&_argvec[0]) \
2428 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2429 ); \
2430 lval = (__typeof__(lval)) _res; \
2431 } while (0)
2433 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2434 arg7,arg8,arg9) \
2435 do { \
2436 volatile OrigFn _orig = (orig); \
2437 volatile unsigned long _argvec[10]; \
2438 volatile unsigned long _res; \
2439 _argvec[0] = (unsigned long)_orig.nraddr; \
2440 _argvec[1] = (unsigned long)arg1; \
2441 _argvec[2] = (unsigned long)arg2; \
2442 _argvec[3] = (unsigned long)arg3; \
2443 _argvec[4] = (unsigned long)arg4; \
2444 _argvec[5] = (unsigned long)arg5; \
2445 _argvec[6] = (unsigned long)arg6; \
2446 _argvec[7] = (unsigned long)arg7; \
2447 _argvec[8] = (unsigned long)arg8; \
2448 _argvec[9] = (unsigned long)arg9; \
2449 __asm__ volatile( \
2450 VALGRIND_ALIGN_STACK \
2451 "mr 11,%1\n\t" \
2452 "addi 1,1,-16\n\t" \
2453 /* arg9 */ \
2454 "lwz 3,36(11)\n\t" \
2455 "stw 3,8(1)\n\t" \
2456 /* args1-8 */ \
2457 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2458 "lwz 4,8(11)\n\t" \
2459 "lwz 5,12(11)\n\t" \
2460 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2461 "lwz 7,20(11)\n\t" \
2462 "lwz 8,24(11)\n\t" \
2463 "lwz 9,28(11)\n\t" \
2464 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2465 "lwz 11,0(11)\n\t" /* target->r11 */ \
2466 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2467 VALGRIND_RESTORE_STACK \
2468 "mr %0,3" \
2469 : /*out*/ "=r" (_res) \
2470 : /*in*/ "r" (&_argvec[0]) \
2471 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2472 ); \
2473 lval = (__typeof__(lval)) _res; \
2474 } while (0)
2476 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2477 arg7,arg8,arg9,arg10) \
2478 do { \
2479 volatile OrigFn _orig = (orig); \
2480 volatile unsigned long _argvec[11]; \
2481 volatile unsigned long _res; \
2482 _argvec[0] = (unsigned long)_orig.nraddr; \
2483 _argvec[1] = (unsigned long)arg1; \
2484 _argvec[2] = (unsigned long)arg2; \
2485 _argvec[3] = (unsigned long)arg3; \
2486 _argvec[4] = (unsigned long)arg4; \
2487 _argvec[5] = (unsigned long)arg5; \
2488 _argvec[6] = (unsigned long)arg6; \
2489 _argvec[7] = (unsigned long)arg7; \
2490 _argvec[8] = (unsigned long)arg8; \
2491 _argvec[9] = (unsigned long)arg9; \
2492 _argvec[10] = (unsigned long)arg10; \
2493 __asm__ volatile( \
2494 VALGRIND_ALIGN_STACK \
2495 "mr 11,%1\n\t" \
2496 "addi 1,1,-16\n\t" \
2497 /* arg10 */ \
2498 "lwz 3,40(11)\n\t" \
2499 "stw 3,12(1)\n\t" \
2500 /* arg9 */ \
2501 "lwz 3,36(11)\n\t" \
2502 "stw 3,8(1)\n\t" \
2503 /* args1-8 */ \
2504 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2505 "lwz 4,8(11)\n\t" \
2506 "lwz 5,12(11)\n\t" \
2507 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2508 "lwz 7,20(11)\n\t" \
2509 "lwz 8,24(11)\n\t" \
2510 "lwz 9,28(11)\n\t" \
2511 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2512 "lwz 11,0(11)\n\t" /* target->r11 */ \
2513 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2514 VALGRIND_RESTORE_STACK \
2515 "mr %0,3" \
2516 : /*out*/ "=r" (_res) \
2517 : /*in*/ "r" (&_argvec[0]) \
2518 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2519 ); \
2520 lval = (__typeof__(lval)) _res; \
2521 } while (0)
2523 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2524 arg7,arg8,arg9,arg10,arg11) \
2525 do { \
2526 volatile OrigFn _orig = (orig); \
2527 volatile unsigned long _argvec[12]; \
2528 volatile unsigned long _res; \
2529 _argvec[0] = (unsigned long)_orig.nraddr; \
2530 _argvec[1] = (unsigned long)arg1; \
2531 _argvec[2] = (unsigned long)arg2; \
2532 _argvec[3] = (unsigned long)arg3; \
2533 _argvec[4] = (unsigned long)arg4; \
2534 _argvec[5] = (unsigned long)arg5; \
2535 _argvec[6] = (unsigned long)arg6; \
2536 _argvec[7] = (unsigned long)arg7; \
2537 _argvec[8] = (unsigned long)arg8; \
2538 _argvec[9] = (unsigned long)arg9; \
2539 _argvec[10] = (unsigned long)arg10; \
2540 _argvec[11] = (unsigned long)arg11; \
2541 __asm__ volatile( \
2542 VALGRIND_ALIGN_STACK \
2543 "mr 11,%1\n\t" \
2544 "addi 1,1,-32\n\t" \
2545 /* arg11 */ \
2546 "lwz 3,44(11)\n\t" \
2547 "stw 3,16(1)\n\t" \
2548 /* arg10 */ \
2549 "lwz 3,40(11)\n\t" \
2550 "stw 3,12(1)\n\t" \
2551 /* arg9 */ \
2552 "lwz 3,36(11)\n\t" \
2553 "stw 3,8(1)\n\t" \
2554 /* args1-8 */ \
2555 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2556 "lwz 4,8(11)\n\t" \
2557 "lwz 5,12(11)\n\t" \
2558 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2559 "lwz 7,20(11)\n\t" \
2560 "lwz 8,24(11)\n\t" \
2561 "lwz 9,28(11)\n\t" \
2562 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2563 "lwz 11,0(11)\n\t" /* target->r11 */ \
2564 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2565 VALGRIND_RESTORE_STACK \
2566 "mr %0,3" \
2567 : /*out*/ "=r" (_res) \
2568 : /*in*/ "r" (&_argvec[0]) \
2569 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2570 ); \
2571 lval = (__typeof__(lval)) _res; \
2572 } while (0)
2574 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2575 arg7,arg8,arg9,arg10,arg11,arg12) \
2576 do { \
2577 volatile OrigFn _orig = (orig); \
2578 volatile unsigned long _argvec[13]; \
2579 volatile unsigned long _res; \
2580 _argvec[0] = (unsigned long)_orig.nraddr; \
2581 _argvec[1] = (unsigned long)arg1; \
2582 _argvec[2] = (unsigned long)arg2; \
2583 _argvec[3] = (unsigned long)arg3; \
2584 _argvec[4] = (unsigned long)arg4; \
2585 _argvec[5] = (unsigned long)arg5; \
2586 _argvec[6] = (unsigned long)arg6; \
2587 _argvec[7] = (unsigned long)arg7; \
2588 _argvec[8] = (unsigned long)arg8; \
2589 _argvec[9] = (unsigned long)arg9; \
2590 _argvec[10] = (unsigned long)arg10; \
2591 _argvec[11] = (unsigned long)arg11; \
2592 _argvec[12] = (unsigned long)arg12; \
2593 __asm__ volatile( \
2594 VALGRIND_ALIGN_STACK \
2595 "mr 11,%1\n\t" \
2596 "addi 1,1,-32\n\t" \
2597 /* arg12 */ \
2598 "lwz 3,48(11)\n\t" \
2599 "stw 3,20(1)\n\t" \
2600 /* arg11 */ \
2601 "lwz 3,44(11)\n\t" \
2602 "stw 3,16(1)\n\t" \
2603 /* arg10 */ \
2604 "lwz 3,40(11)\n\t" \
2605 "stw 3,12(1)\n\t" \
2606 /* arg9 */ \
2607 "lwz 3,36(11)\n\t" \
2608 "stw 3,8(1)\n\t" \
2609 /* args1-8 */ \
2610 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2611 "lwz 4,8(11)\n\t" \
2612 "lwz 5,12(11)\n\t" \
2613 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2614 "lwz 7,20(11)\n\t" \
2615 "lwz 8,24(11)\n\t" \
2616 "lwz 9,28(11)\n\t" \
2617 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2618 "lwz 11,0(11)\n\t" /* target->r11 */ \
2619 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2620 VALGRIND_RESTORE_STACK \
2621 "mr %0,3" \
2622 : /*out*/ "=r" (_res) \
2623 : /*in*/ "r" (&_argvec[0]) \
2624 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2625 ); \
2626 lval = (__typeof__(lval)) _res; \
2627 } while (0)
2629 #endif /* PLAT_ppc32_linux */
2631 /* ------------------------ ppc64-linux ------------------------ */
2633 #if defined(PLAT_ppc64be_linux)
2635 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2637 /* These regs are trashed by the hidden call. */
2638 #define __CALLER_SAVED_REGS \
2639 "lr", "ctr", "xer", \
2640 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2641 "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2642 "r11", "r12", "r13"
2644 /* Macros to save and align the stack before making a function
2645 call and restore it afterwards as gcc may not keep the stack
2646 pointer aligned if it doesn't realise calls are being made
2647 to other functions. */
2649 #define VALGRIND_ALIGN_STACK \
2650 "mr 28,1\n\t" \
2651 "rldicr 1,1,0,59\n\t"
2652 #define VALGRIND_RESTORE_STACK \
2653 "mr 1,28\n\t"
2655 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2656 long) == 8. */
2658 #define CALL_FN_W_v(lval, orig) \
2659 do { \
2660 volatile OrigFn _orig = (orig); \
2661 volatile unsigned long _argvec[3+0]; \
2662 volatile unsigned long _res; \
2663 /* _argvec[0] holds current r2 across the call */ \
2664 _argvec[1] = (unsigned long)_orig.r2; \
2665 _argvec[2] = (unsigned long)_orig.nraddr; \
2666 __asm__ volatile( \
2667 VALGRIND_ALIGN_STACK \
2668 "mr 11,%1\n\t" \
2669 "std 2,-16(11)\n\t" /* save tocptr */ \
2670 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2671 "ld 11, 0(11)\n\t" /* target->r11 */ \
2672 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2673 "mr 11,%1\n\t" \
2674 "mr %0,3\n\t" \
2675 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2676 VALGRIND_RESTORE_STACK \
2677 : /*out*/ "=r" (_res) \
2678 : /*in*/ "r" (&_argvec[2]) \
2679 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2680 ); \
2681 lval = (__typeof__(lval)) _res; \
2682 } while (0)
2684 #define CALL_FN_W_W(lval, orig, arg1) \
2685 do { \
2686 volatile OrigFn _orig = (orig); \
2687 volatile unsigned long _argvec[3+1]; \
2688 volatile unsigned long _res; \
2689 /* _argvec[0] holds current r2 across the call */ \
2690 _argvec[1] = (unsigned long)_orig.r2; \
2691 _argvec[2] = (unsigned long)_orig.nraddr; \
2692 _argvec[2+1] = (unsigned long)arg1; \
2693 __asm__ volatile( \
2694 VALGRIND_ALIGN_STACK \
2695 "mr 11,%1\n\t" \
2696 "std 2,-16(11)\n\t" /* save tocptr */ \
2697 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2698 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2699 "ld 11, 0(11)\n\t" /* target->r11 */ \
2700 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2701 "mr 11,%1\n\t" \
2702 "mr %0,3\n\t" \
2703 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2704 VALGRIND_RESTORE_STACK \
2705 : /*out*/ "=r" (_res) \
2706 : /*in*/ "r" (&_argvec[2]) \
2707 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2708 ); \
2709 lval = (__typeof__(lval)) _res; \
2710 } while (0)
2712 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2713 do { \
2714 volatile OrigFn _orig = (orig); \
2715 volatile unsigned long _argvec[3+2]; \
2716 volatile unsigned long _res; \
2717 /* _argvec[0] holds current r2 across the call */ \
2718 _argvec[1] = (unsigned long)_orig.r2; \
2719 _argvec[2] = (unsigned long)_orig.nraddr; \
2720 _argvec[2+1] = (unsigned long)arg1; \
2721 _argvec[2+2] = (unsigned long)arg2; \
2722 __asm__ volatile( \
2723 VALGRIND_ALIGN_STACK \
2724 "mr 11,%1\n\t" \
2725 "std 2,-16(11)\n\t" /* save tocptr */ \
2726 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2727 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2728 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2729 "ld 11, 0(11)\n\t" /* target->r11 */ \
2730 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2731 "mr 11,%1\n\t" \
2732 "mr %0,3\n\t" \
2733 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2734 VALGRIND_RESTORE_STACK \
2735 : /*out*/ "=r" (_res) \
2736 : /*in*/ "r" (&_argvec[2]) \
2737 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2738 ); \
2739 lval = (__typeof__(lval)) _res; \
2740 } while (0)
2742 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2743 do { \
2744 volatile OrigFn _orig = (orig); \
2745 volatile unsigned long _argvec[3+3]; \
2746 volatile unsigned long _res; \
2747 /* _argvec[0] holds current r2 across the call */ \
2748 _argvec[1] = (unsigned long)_orig.r2; \
2749 _argvec[2] = (unsigned long)_orig.nraddr; \
2750 _argvec[2+1] = (unsigned long)arg1; \
2751 _argvec[2+2] = (unsigned long)arg2; \
2752 _argvec[2+3] = (unsigned long)arg3; \
2753 __asm__ volatile( \
2754 VALGRIND_ALIGN_STACK \
2755 "mr 11,%1\n\t" \
2756 "std 2,-16(11)\n\t" /* save tocptr */ \
2757 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2758 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2759 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2760 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2761 "ld 11, 0(11)\n\t" /* target->r11 */ \
2762 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2763 "mr 11,%1\n\t" \
2764 "mr %0,3\n\t" \
2765 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2766 VALGRIND_RESTORE_STACK \
2767 : /*out*/ "=r" (_res) \
2768 : /*in*/ "r" (&_argvec[2]) \
2769 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2770 ); \
2771 lval = (__typeof__(lval)) _res; \
2772 } while (0)
2774 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2775 do { \
2776 volatile OrigFn _orig = (orig); \
2777 volatile unsigned long _argvec[3+4]; \
2778 volatile unsigned long _res; \
2779 /* _argvec[0] holds current r2 across the call */ \
2780 _argvec[1] = (unsigned long)_orig.r2; \
2781 _argvec[2] = (unsigned long)_orig.nraddr; \
2782 _argvec[2+1] = (unsigned long)arg1; \
2783 _argvec[2+2] = (unsigned long)arg2; \
2784 _argvec[2+3] = (unsigned long)arg3; \
2785 _argvec[2+4] = (unsigned long)arg4; \
2786 __asm__ volatile( \
2787 VALGRIND_ALIGN_STACK \
2788 "mr 11,%1\n\t" \
2789 "std 2,-16(11)\n\t" /* save tocptr */ \
2790 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2791 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2792 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2793 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2794 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2795 "ld 11, 0(11)\n\t" /* target->r11 */ \
2796 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2797 "mr 11,%1\n\t" \
2798 "mr %0,3\n\t" \
2799 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2800 VALGRIND_RESTORE_STACK \
2801 : /*out*/ "=r" (_res) \
2802 : /*in*/ "r" (&_argvec[2]) \
2803 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2804 ); \
2805 lval = (__typeof__(lval)) _res; \
2806 } while (0)
2808 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2809 do { \
2810 volatile OrigFn _orig = (orig); \
2811 volatile unsigned long _argvec[3+5]; \
2812 volatile unsigned long _res; \
2813 /* _argvec[0] holds current r2 across the call */ \
2814 _argvec[1] = (unsigned long)_orig.r2; \
2815 _argvec[2] = (unsigned long)_orig.nraddr; \
2816 _argvec[2+1] = (unsigned long)arg1; \
2817 _argvec[2+2] = (unsigned long)arg2; \
2818 _argvec[2+3] = (unsigned long)arg3; \
2819 _argvec[2+4] = (unsigned long)arg4; \
2820 _argvec[2+5] = (unsigned long)arg5; \
2821 __asm__ volatile( \
2822 VALGRIND_ALIGN_STACK \
2823 "mr 11,%1\n\t" \
2824 "std 2,-16(11)\n\t" /* save tocptr */ \
2825 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2826 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2827 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2828 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2829 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2830 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2831 "ld 11, 0(11)\n\t" /* target->r11 */ \
2832 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2833 "mr 11,%1\n\t" \
2834 "mr %0,3\n\t" \
2835 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2836 VALGRIND_RESTORE_STACK \
2837 : /*out*/ "=r" (_res) \
2838 : /*in*/ "r" (&_argvec[2]) \
2839 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2840 ); \
2841 lval = (__typeof__(lval)) _res; \
2842 } while (0)
2844 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2845 do { \
2846 volatile OrigFn _orig = (orig); \
2847 volatile unsigned long _argvec[3+6]; \
2848 volatile unsigned long _res; \
2849 /* _argvec[0] holds current r2 across the call */ \
2850 _argvec[1] = (unsigned long)_orig.r2; \
2851 _argvec[2] = (unsigned long)_orig.nraddr; \
2852 _argvec[2+1] = (unsigned long)arg1; \
2853 _argvec[2+2] = (unsigned long)arg2; \
2854 _argvec[2+3] = (unsigned long)arg3; \
2855 _argvec[2+4] = (unsigned long)arg4; \
2856 _argvec[2+5] = (unsigned long)arg5; \
2857 _argvec[2+6] = (unsigned long)arg6; \
2858 __asm__ volatile( \
2859 VALGRIND_ALIGN_STACK \
2860 "mr 11,%1\n\t" \
2861 "std 2,-16(11)\n\t" /* save tocptr */ \
2862 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2863 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2864 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2865 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2866 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2867 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2868 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2869 "ld 11, 0(11)\n\t" /* target->r11 */ \
2870 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2871 "mr 11,%1\n\t" \
2872 "mr %0,3\n\t" \
2873 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2874 VALGRIND_RESTORE_STACK \
2875 : /*out*/ "=r" (_res) \
2876 : /*in*/ "r" (&_argvec[2]) \
2877 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2878 ); \
2879 lval = (__typeof__(lval)) _res; \
2880 } while (0)
2882 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2883 arg7) \
2884 do { \
2885 volatile OrigFn _orig = (orig); \
2886 volatile unsigned long _argvec[3+7]; \
2887 volatile unsigned long _res; \
2888 /* _argvec[0] holds current r2 across the call */ \
2889 _argvec[1] = (unsigned long)_orig.r2; \
2890 _argvec[2] = (unsigned long)_orig.nraddr; \
2891 _argvec[2+1] = (unsigned long)arg1; \
2892 _argvec[2+2] = (unsigned long)arg2; \
2893 _argvec[2+3] = (unsigned long)arg3; \
2894 _argvec[2+4] = (unsigned long)arg4; \
2895 _argvec[2+5] = (unsigned long)arg5; \
2896 _argvec[2+6] = (unsigned long)arg6; \
2897 _argvec[2+7] = (unsigned long)arg7; \
2898 __asm__ volatile( \
2899 VALGRIND_ALIGN_STACK \
2900 "mr 11,%1\n\t" \
2901 "std 2,-16(11)\n\t" /* save tocptr */ \
2902 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2903 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2904 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2905 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2906 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2907 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2908 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2909 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2910 "ld 11, 0(11)\n\t" /* target->r11 */ \
2911 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2912 "mr 11,%1\n\t" \
2913 "mr %0,3\n\t" \
2914 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2915 VALGRIND_RESTORE_STACK \
2916 : /*out*/ "=r" (_res) \
2917 : /*in*/ "r" (&_argvec[2]) \
2918 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2919 ); \
2920 lval = (__typeof__(lval)) _res; \
2921 } while (0)
2923 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2924 arg7,arg8) \
2925 do { \
2926 volatile OrigFn _orig = (orig); \
2927 volatile unsigned long _argvec[3+8]; \
2928 volatile unsigned long _res; \
2929 /* _argvec[0] holds current r2 across the call */ \
2930 _argvec[1] = (unsigned long)_orig.r2; \
2931 _argvec[2] = (unsigned long)_orig.nraddr; \
2932 _argvec[2+1] = (unsigned long)arg1; \
2933 _argvec[2+2] = (unsigned long)arg2; \
2934 _argvec[2+3] = (unsigned long)arg3; \
2935 _argvec[2+4] = (unsigned long)arg4; \
2936 _argvec[2+5] = (unsigned long)arg5; \
2937 _argvec[2+6] = (unsigned long)arg6; \
2938 _argvec[2+7] = (unsigned long)arg7; \
2939 _argvec[2+8] = (unsigned long)arg8; \
2940 __asm__ volatile( \
2941 VALGRIND_ALIGN_STACK \
2942 "mr 11,%1\n\t" \
2943 "std 2,-16(11)\n\t" /* save tocptr */ \
2944 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2945 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2946 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2947 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2948 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2949 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2950 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2951 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2952 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2953 "ld 11, 0(11)\n\t" /* target->r11 */ \
2954 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2955 "mr 11,%1\n\t" \
2956 "mr %0,3\n\t" \
2957 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2958 VALGRIND_RESTORE_STACK \
2959 : /*out*/ "=r" (_res) \
2960 : /*in*/ "r" (&_argvec[2]) \
2961 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
2962 ); \
2963 lval = (__typeof__(lval)) _res; \
2964 } while (0)
2966 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2967 arg7,arg8,arg9) \
2968 do { \
2969 volatile OrigFn _orig = (orig); \
2970 volatile unsigned long _argvec[3+9]; \
2971 volatile unsigned long _res; \
2972 /* _argvec[0] holds current r2 across the call */ \
2973 _argvec[1] = (unsigned long)_orig.r2; \
2974 _argvec[2] = (unsigned long)_orig.nraddr; \
2975 _argvec[2+1] = (unsigned long)arg1; \
2976 _argvec[2+2] = (unsigned long)arg2; \
2977 _argvec[2+3] = (unsigned long)arg3; \
2978 _argvec[2+4] = (unsigned long)arg4; \
2979 _argvec[2+5] = (unsigned long)arg5; \
2980 _argvec[2+6] = (unsigned long)arg6; \
2981 _argvec[2+7] = (unsigned long)arg7; \
2982 _argvec[2+8] = (unsigned long)arg8; \
2983 _argvec[2+9] = (unsigned long)arg9; \
2984 __asm__ volatile( \
2985 VALGRIND_ALIGN_STACK \
2986 "mr 11,%1\n\t" \
2987 "std 2,-16(11)\n\t" /* save tocptr */ \
2988 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2989 "addi 1,1,-128\n\t" /* expand stack frame */ \
2990 /* arg9 */ \
2991 "ld 3,72(11)\n\t" \
2992 "std 3,112(1)\n\t" \
2993 /* args1-8 */ \
2994 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2995 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2996 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2997 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2998 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2999 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3000 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3001 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3002 "ld 11, 0(11)\n\t" /* target->r11 */ \
3003 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3004 "mr 11,%1\n\t" \
3005 "mr %0,3\n\t" \
3006 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3007 VALGRIND_RESTORE_STACK \
3008 : /*out*/ "=r" (_res) \
3009 : /*in*/ "r" (&_argvec[2]) \
3010 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3011 ); \
3012 lval = (__typeof__(lval)) _res; \
3013 } while (0)
3015 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3016 arg7,arg8,arg9,arg10) \
3017 do { \
3018 volatile OrigFn _orig = (orig); \
3019 volatile unsigned long _argvec[3+10]; \
3020 volatile unsigned long _res; \
3021 /* _argvec[0] holds current r2 across the call */ \
3022 _argvec[1] = (unsigned long)_orig.r2; \
3023 _argvec[2] = (unsigned long)_orig.nraddr; \
3024 _argvec[2+1] = (unsigned long)arg1; \
3025 _argvec[2+2] = (unsigned long)arg2; \
3026 _argvec[2+3] = (unsigned long)arg3; \
3027 _argvec[2+4] = (unsigned long)arg4; \
3028 _argvec[2+5] = (unsigned long)arg5; \
3029 _argvec[2+6] = (unsigned long)arg6; \
3030 _argvec[2+7] = (unsigned long)arg7; \
3031 _argvec[2+8] = (unsigned long)arg8; \
3032 _argvec[2+9] = (unsigned long)arg9; \
3033 _argvec[2+10] = (unsigned long)arg10; \
3034 __asm__ volatile( \
3035 VALGRIND_ALIGN_STACK \
3036 "mr 11,%1\n\t" \
3037 "std 2,-16(11)\n\t" /* save tocptr */ \
3038 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3039 "addi 1,1,-128\n\t" /* expand stack frame */ \
3040 /* arg10 */ \
3041 "ld 3,80(11)\n\t" \
3042 "std 3,120(1)\n\t" \
3043 /* arg9 */ \
3044 "ld 3,72(11)\n\t" \
3045 "std 3,112(1)\n\t" \
3046 /* args1-8 */ \
3047 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3048 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3049 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3050 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3051 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3052 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3053 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3054 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3055 "ld 11, 0(11)\n\t" /* target->r11 */ \
3056 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3057 "mr 11,%1\n\t" \
3058 "mr %0,3\n\t" \
3059 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3060 VALGRIND_RESTORE_STACK \
3061 : /*out*/ "=r" (_res) \
3062 : /*in*/ "r" (&_argvec[2]) \
3063 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3064 ); \
3065 lval = (__typeof__(lval)) _res; \
3066 } while (0)
3068 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3069 arg7,arg8,arg9,arg10,arg11) \
3070 do { \
3071 volatile OrigFn _orig = (orig); \
3072 volatile unsigned long _argvec[3+11]; \
3073 volatile unsigned long _res; \
3074 /* _argvec[0] holds current r2 across the call */ \
3075 _argvec[1] = (unsigned long)_orig.r2; \
3076 _argvec[2] = (unsigned long)_orig.nraddr; \
3077 _argvec[2+1] = (unsigned long)arg1; \
3078 _argvec[2+2] = (unsigned long)arg2; \
3079 _argvec[2+3] = (unsigned long)arg3; \
3080 _argvec[2+4] = (unsigned long)arg4; \
3081 _argvec[2+5] = (unsigned long)arg5; \
3082 _argvec[2+6] = (unsigned long)arg6; \
3083 _argvec[2+7] = (unsigned long)arg7; \
3084 _argvec[2+8] = (unsigned long)arg8; \
3085 _argvec[2+9] = (unsigned long)arg9; \
3086 _argvec[2+10] = (unsigned long)arg10; \
3087 _argvec[2+11] = (unsigned long)arg11; \
3088 __asm__ volatile( \
3089 VALGRIND_ALIGN_STACK \
3090 "mr 11,%1\n\t" \
3091 "std 2,-16(11)\n\t" /* save tocptr */ \
3092 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3093 "addi 1,1,-144\n\t" /* expand stack frame */ \
3094 /* arg11 */ \
3095 "ld 3,88(11)\n\t" \
3096 "std 3,128(1)\n\t" \
3097 /* arg10 */ \
3098 "ld 3,80(11)\n\t" \
3099 "std 3,120(1)\n\t" \
3100 /* arg9 */ \
3101 "ld 3,72(11)\n\t" \
3102 "std 3,112(1)\n\t" \
3103 /* args1-8 */ \
3104 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3105 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3106 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3107 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3108 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3109 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3110 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3111 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3112 "ld 11, 0(11)\n\t" /* target->r11 */ \
3113 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3114 "mr 11,%1\n\t" \
3115 "mr %0,3\n\t" \
3116 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3117 VALGRIND_RESTORE_STACK \
3118 : /*out*/ "=r" (_res) \
3119 : /*in*/ "r" (&_argvec[2]) \
3120 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3121 ); \
3122 lval = (__typeof__(lval)) _res; \
3123 } while (0)
3125 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3126 arg7,arg8,arg9,arg10,arg11,arg12) \
3127 do { \
3128 volatile OrigFn _orig = (orig); \
3129 volatile unsigned long _argvec[3+12]; \
3130 volatile unsigned long _res; \
3131 /* _argvec[0] holds current r2 across the call */ \
3132 _argvec[1] = (unsigned long)_orig.r2; \
3133 _argvec[2] = (unsigned long)_orig.nraddr; \
3134 _argvec[2+1] = (unsigned long)arg1; \
3135 _argvec[2+2] = (unsigned long)arg2; \
3136 _argvec[2+3] = (unsigned long)arg3; \
3137 _argvec[2+4] = (unsigned long)arg4; \
3138 _argvec[2+5] = (unsigned long)arg5; \
3139 _argvec[2+6] = (unsigned long)arg6; \
3140 _argvec[2+7] = (unsigned long)arg7; \
3141 _argvec[2+8] = (unsigned long)arg8; \
3142 _argvec[2+9] = (unsigned long)arg9; \
3143 _argvec[2+10] = (unsigned long)arg10; \
3144 _argvec[2+11] = (unsigned long)arg11; \
3145 _argvec[2+12] = (unsigned long)arg12; \
3146 __asm__ volatile( \
3147 VALGRIND_ALIGN_STACK \
3148 "mr 11,%1\n\t" \
3149 "std 2,-16(11)\n\t" /* save tocptr */ \
3150 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3151 "addi 1,1,-144\n\t" /* expand stack frame */ \
3152 /* arg12 */ \
3153 "ld 3,96(11)\n\t" \
3154 "std 3,136(1)\n\t" \
3155 /* arg11 */ \
3156 "ld 3,88(11)\n\t" \
3157 "std 3,128(1)\n\t" \
3158 /* arg10 */ \
3159 "ld 3,80(11)\n\t" \
3160 "std 3,120(1)\n\t" \
3161 /* arg9 */ \
3162 "ld 3,72(11)\n\t" \
3163 "std 3,112(1)\n\t" \
3164 /* args1-8 */ \
3165 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3166 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3167 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3168 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3169 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3170 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3171 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3172 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3173 "ld 11, 0(11)\n\t" /* target->r11 */ \
3174 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3175 "mr 11,%1\n\t" \
3176 "mr %0,3\n\t" \
3177 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3178 VALGRIND_RESTORE_STACK \
3179 : /*out*/ "=r" (_res) \
3180 : /*in*/ "r" (&_argvec[2]) \
3181 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3182 ); \
3183 lval = (__typeof__(lval)) _res; \
3184 } while (0)
3186 #endif /* PLAT_ppc64be_linux */
3188 /* ------------------------- ppc64le-linux ----------------------- */
3189 #if defined(PLAT_ppc64le_linux)
3191 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3193 /* These regs are trashed by the hidden call. */
3194 #define __CALLER_SAVED_REGS \
3195 "lr", "ctr", "xer", \
3196 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3197 "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3198 "r11", "r12", "r13"
3200 /* Macros to save and align the stack before making a function
3201 call and restore it afterwards as gcc may not keep the stack
3202 pointer aligned if it doesn't realise calls are being made
3203 to other functions. */
3205 #define VALGRIND_ALIGN_STACK \
3206 "mr 28,1\n\t" \
3207 "rldicr 1,1,0,59\n\t"
3208 #define VALGRIND_RESTORE_STACK \
3209 "mr 1,28\n\t"
3211 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
3212 long) == 8. */
3214 #define CALL_FN_W_v(lval, orig) \
3215 do { \
3216 volatile OrigFn _orig = (orig); \
3217 volatile unsigned long _argvec[3+0]; \
3218 volatile unsigned long _res; \
3219 /* _argvec[0] holds current r2 across the call */ \
3220 _argvec[1] = (unsigned long)_orig.r2; \
3221 _argvec[2] = (unsigned long)_orig.nraddr; \
3222 __asm__ volatile( \
3223 VALGRIND_ALIGN_STACK \
3224 "mr 12,%1\n\t" \
3225 "std 2,-16(12)\n\t" /* save tocptr */ \
3226 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3227 "ld 12, 0(12)\n\t" /* target->r12 */ \
3228 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3229 "mr 12,%1\n\t" \
3230 "mr %0,3\n\t" \
3231 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3232 VALGRIND_RESTORE_STACK \
3233 : /*out*/ "=r" (_res) \
3234 : /*in*/ "r" (&_argvec[2]) \
3235 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3236 ); \
3237 lval = (__typeof__(lval)) _res; \
3238 } while (0)
3240 #define CALL_FN_W_W(lval, orig, arg1) \
3241 do { \
3242 volatile OrigFn _orig = (orig); \
3243 volatile unsigned long _argvec[3+1]; \
3244 volatile unsigned long _res; \
3245 /* _argvec[0] holds current r2 across the call */ \
3246 _argvec[1] = (unsigned long)_orig.r2; \
3247 _argvec[2] = (unsigned long)_orig.nraddr; \
3248 _argvec[2+1] = (unsigned long)arg1; \
3249 __asm__ volatile( \
3250 VALGRIND_ALIGN_STACK \
3251 "mr 12,%1\n\t" \
3252 "std 2,-16(12)\n\t" /* save tocptr */ \
3253 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3254 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3255 "ld 12, 0(12)\n\t" /* target->r12 */ \
3256 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3257 "mr 12,%1\n\t" \
3258 "mr %0,3\n\t" \
3259 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3260 VALGRIND_RESTORE_STACK \
3261 : /*out*/ "=r" (_res) \
3262 : /*in*/ "r" (&_argvec[2]) \
3263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3264 ); \
3265 lval = (__typeof__(lval)) _res; \
3266 } while (0)
3268 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3269 do { \
3270 volatile OrigFn _orig = (orig); \
3271 volatile unsigned long _argvec[3+2]; \
3272 volatile unsigned long _res; \
3273 /* _argvec[0] holds current r2 across the call */ \
3274 _argvec[1] = (unsigned long)_orig.r2; \
3275 _argvec[2] = (unsigned long)_orig.nraddr; \
3276 _argvec[2+1] = (unsigned long)arg1; \
3277 _argvec[2+2] = (unsigned long)arg2; \
3278 __asm__ volatile( \
3279 VALGRIND_ALIGN_STACK \
3280 "mr 12,%1\n\t" \
3281 "std 2,-16(12)\n\t" /* save tocptr */ \
3282 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3283 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3284 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3285 "ld 12, 0(12)\n\t" /* target->r12 */ \
3286 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3287 "mr 12,%1\n\t" \
3288 "mr %0,3\n\t" \
3289 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3290 VALGRIND_RESTORE_STACK \
3291 : /*out*/ "=r" (_res) \
3292 : /*in*/ "r" (&_argvec[2]) \
3293 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3294 ); \
3295 lval = (__typeof__(lval)) _res; \
3296 } while (0)
3298 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3299 do { \
3300 volatile OrigFn _orig = (orig); \
3301 volatile unsigned long _argvec[3+3]; \
3302 volatile unsigned long _res; \
3303 /* _argvec[0] holds current r2 across the call */ \
3304 _argvec[1] = (unsigned long)_orig.r2; \
3305 _argvec[2] = (unsigned long)_orig.nraddr; \
3306 _argvec[2+1] = (unsigned long)arg1; \
3307 _argvec[2+2] = (unsigned long)arg2; \
3308 _argvec[2+3] = (unsigned long)arg3; \
3309 __asm__ volatile( \
3310 VALGRIND_ALIGN_STACK \
3311 "mr 12,%1\n\t" \
3312 "std 2,-16(12)\n\t" /* save tocptr */ \
3313 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3314 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3315 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3316 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3317 "ld 12, 0(12)\n\t" /* target->r12 */ \
3318 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3319 "mr 12,%1\n\t" \
3320 "mr %0,3\n\t" \
3321 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3322 VALGRIND_RESTORE_STACK \
3323 : /*out*/ "=r" (_res) \
3324 : /*in*/ "r" (&_argvec[2]) \
3325 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3326 ); \
3327 lval = (__typeof__(lval)) _res; \
3328 } while (0)
3330 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3331 do { \
3332 volatile OrigFn _orig = (orig); \
3333 volatile unsigned long _argvec[3+4]; \
3334 volatile unsigned long _res; \
3335 /* _argvec[0] holds current r2 across the call */ \
3336 _argvec[1] = (unsigned long)_orig.r2; \
3337 _argvec[2] = (unsigned long)_orig.nraddr; \
3338 _argvec[2+1] = (unsigned long)arg1; \
3339 _argvec[2+2] = (unsigned long)arg2; \
3340 _argvec[2+3] = (unsigned long)arg3; \
3341 _argvec[2+4] = (unsigned long)arg4; \
3342 __asm__ volatile( \
3343 VALGRIND_ALIGN_STACK \
3344 "mr 12,%1\n\t" \
3345 "std 2,-16(12)\n\t" /* save tocptr */ \
3346 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3347 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3348 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3349 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3350 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3351 "ld 12, 0(12)\n\t" /* target->r12 */ \
3352 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3353 "mr 12,%1\n\t" \
3354 "mr %0,3\n\t" \
3355 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3356 VALGRIND_RESTORE_STACK \
3357 : /*out*/ "=r" (_res) \
3358 : /*in*/ "r" (&_argvec[2]) \
3359 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3360 ); \
3361 lval = (__typeof__(lval)) _res; \
3362 } while (0)
3364 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3365 do { \
3366 volatile OrigFn _orig = (orig); \
3367 volatile unsigned long _argvec[3+5]; \
3368 volatile unsigned long _res; \
3369 /* _argvec[0] holds current r2 across the call */ \
3370 _argvec[1] = (unsigned long)_orig.r2; \
3371 _argvec[2] = (unsigned long)_orig.nraddr; \
3372 _argvec[2+1] = (unsigned long)arg1; \
3373 _argvec[2+2] = (unsigned long)arg2; \
3374 _argvec[2+3] = (unsigned long)arg3; \
3375 _argvec[2+4] = (unsigned long)arg4; \
3376 _argvec[2+5] = (unsigned long)arg5; \
3377 __asm__ volatile( \
3378 VALGRIND_ALIGN_STACK \
3379 "mr 12,%1\n\t" \
3380 "std 2,-16(12)\n\t" /* save tocptr */ \
3381 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3382 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3383 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3384 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3385 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3386 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3387 "ld 12, 0(12)\n\t" /* target->r12 */ \
3388 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3389 "mr 12,%1\n\t" \
3390 "mr %0,3\n\t" \
3391 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3392 VALGRIND_RESTORE_STACK \
3393 : /*out*/ "=r" (_res) \
3394 : /*in*/ "r" (&_argvec[2]) \
3395 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3396 ); \
3397 lval = (__typeof__(lval)) _res; \
3398 } while (0)
3400 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3401 do { \
3402 volatile OrigFn _orig = (orig); \
3403 volatile unsigned long _argvec[3+6]; \
3404 volatile unsigned long _res; \
3405 /* _argvec[0] holds current r2 across the call */ \
3406 _argvec[1] = (unsigned long)_orig.r2; \
3407 _argvec[2] = (unsigned long)_orig.nraddr; \
3408 _argvec[2+1] = (unsigned long)arg1; \
3409 _argvec[2+2] = (unsigned long)arg2; \
3410 _argvec[2+3] = (unsigned long)arg3; \
3411 _argvec[2+4] = (unsigned long)arg4; \
3412 _argvec[2+5] = (unsigned long)arg5; \
3413 _argvec[2+6] = (unsigned long)arg6; \
3414 __asm__ volatile( \
3415 VALGRIND_ALIGN_STACK \
3416 "mr 12,%1\n\t" \
3417 "std 2,-16(12)\n\t" /* save tocptr */ \
3418 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3419 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3420 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3421 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3422 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3423 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3424 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3425 "ld 12, 0(12)\n\t" /* target->r12 */ \
3426 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3427 "mr 12,%1\n\t" \
3428 "mr %0,3\n\t" \
3429 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3430 VALGRIND_RESTORE_STACK \
3431 : /*out*/ "=r" (_res) \
3432 : /*in*/ "r" (&_argvec[2]) \
3433 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3434 ); \
3435 lval = (__typeof__(lval)) _res; \
3436 } while (0)
3438 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3439 arg7) \
3440 do { \
3441 volatile OrigFn _orig = (orig); \
3442 volatile unsigned long _argvec[3+7]; \
3443 volatile unsigned long _res; \
3444 /* _argvec[0] holds current r2 across the call */ \
3445 _argvec[1] = (unsigned long)_orig.r2; \
3446 _argvec[2] = (unsigned long)_orig.nraddr; \
3447 _argvec[2+1] = (unsigned long)arg1; \
3448 _argvec[2+2] = (unsigned long)arg2; \
3449 _argvec[2+3] = (unsigned long)arg3; \
3450 _argvec[2+4] = (unsigned long)arg4; \
3451 _argvec[2+5] = (unsigned long)arg5; \
3452 _argvec[2+6] = (unsigned long)arg6; \
3453 _argvec[2+7] = (unsigned long)arg7; \
3454 __asm__ volatile( \
3455 VALGRIND_ALIGN_STACK \
3456 "mr 12,%1\n\t" \
3457 "std 2,-16(12)\n\t" /* save tocptr */ \
3458 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3459 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3460 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3461 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3462 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3463 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3464 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3465 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3466 "ld 12, 0(12)\n\t" /* target->r12 */ \
3467 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3468 "mr 12,%1\n\t" \
3469 "mr %0,3\n\t" \
3470 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3471 VALGRIND_RESTORE_STACK \
3472 : /*out*/ "=r" (_res) \
3473 : /*in*/ "r" (&_argvec[2]) \
3474 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3475 ); \
3476 lval = (__typeof__(lval)) _res; \
3477 } while (0)
3479 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3480 arg7,arg8) \
3481 do { \
3482 volatile OrigFn _orig = (orig); \
3483 volatile unsigned long _argvec[3+8]; \
3484 volatile unsigned long _res; \
3485 /* _argvec[0] holds current r2 across the call */ \
3486 _argvec[1] = (unsigned long)_orig.r2; \
3487 _argvec[2] = (unsigned long)_orig.nraddr; \
3488 _argvec[2+1] = (unsigned long)arg1; \
3489 _argvec[2+2] = (unsigned long)arg2; \
3490 _argvec[2+3] = (unsigned long)arg3; \
3491 _argvec[2+4] = (unsigned long)arg4; \
3492 _argvec[2+5] = (unsigned long)arg5; \
3493 _argvec[2+6] = (unsigned long)arg6; \
3494 _argvec[2+7] = (unsigned long)arg7; \
3495 _argvec[2+8] = (unsigned long)arg8; \
3496 __asm__ volatile( \
3497 VALGRIND_ALIGN_STACK \
3498 "mr 12,%1\n\t" \
3499 "std 2,-16(12)\n\t" /* save tocptr */ \
3500 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3501 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3502 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3503 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3504 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3505 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3506 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3507 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3508 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3509 "ld 12, 0(12)\n\t" /* target->r12 */ \
3510 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3511 "mr 12,%1\n\t" \
3512 "mr %0,3\n\t" \
3513 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3514 VALGRIND_RESTORE_STACK \
3515 : /*out*/ "=r" (_res) \
3516 : /*in*/ "r" (&_argvec[2]) \
3517 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3518 ); \
3519 lval = (__typeof__(lval)) _res; \
3520 } while (0)
3522 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3523 arg7,arg8,arg9) \
3524 do { \
3525 volatile OrigFn _orig = (orig); \
3526 volatile unsigned long _argvec[3+9]; \
3527 volatile unsigned long _res; \
3528 /* _argvec[0] holds current r2 across the call */ \
3529 _argvec[1] = (unsigned long)_orig.r2; \
3530 _argvec[2] = (unsigned long)_orig.nraddr; \
3531 _argvec[2+1] = (unsigned long)arg1; \
3532 _argvec[2+2] = (unsigned long)arg2; \
3533 _argvec[2+3] = (unsigned long)arg3; \
3534 _argvec[2+4] = (unsigned long)arg4; \
3535 _argvec[2+5] = (unsigned long)arg5; \
3536 _argvec[2+6] = (unsigned long)arg6; \
3537 _argvec[2+7] = (unsigned long)arg7; \
3538 _argvec[2+8] = (unsigned long)arg8; \
3539 _argvec[2+9] = (unsigned long)arg9; \
3540 __asm__ volatile( \
3541 VALGRIND_ALIGN_STACK \
3542 "mr 12,%1\n\t" \
3543 "std 2,-16(12)\n\t" /* save tocptr */ \
3544 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3545 "addi 1,1,-128\n\t" /* expand stack frame */ \
3546 /* arg9 */ \
3547 "ld 3,72(12)\n\t" \
3548 "std 3,96(1)\n\t" \
3549 /* args1-8 */ \
3550 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3551 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3552 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3553 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3554 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3555 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3556 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3557 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3558 "ld 12, 0(12)\n\t" /* target->r12 */ \
3559 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3560 "mr 12,%1\n\t" \
3561 "mr %0,3\n\t" \
3562 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3563 VALGRIND_RESTORE_STACK \
3564 : /*out*/ "=r" (_res) \
3565 : /*in*/ "r" (&_argvec[2]) \
3566 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3567 ); \
3568 lval = (__typeof__(lval)) _res; \
3569 } while (0)
3571 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3572 arg7,arg8,arg9,arg10) \
3573 do { \
3574 volatile OrigFn _orig = (orig); \
3575 volatile unsigned long _argvec[3+10]; \
3576 volatile unsigned long _res; \
3577 /* _argvec[0] holds current r2 across the call */ \
3578 _argvec[1] = (unsigned long)_orig.r2; \
3579 _argvec[2] = (unsigned long)_orig.nraddr; \
3580 _argvec[2+1] = (unsigned long)arg1; \
3581 _argvec[2+2] = (unsigned long)arg2; \
3582 _argvec[2+3] = (unsigned long)arg3; \
3583 _argvec[2+4] = (unsigned long)arg4; \
3584 _argvec[2+5] = (unsigned long)arg5; \
3585 _argvec[2+6] = (unsigned long)arg6; \
3586 _argvec[2+7] = (unsigned long)arg7; \
3587 _argvec[2+8] = (unsigned long)arg8; \
3588 _argvec[2+9] = (unsigned long)arg9; \
3589 _argvec[2+10] = (unsigned long)arg10; \
3590 __asm__ volatile( \
3591 VALGRIND_ALIGN_STACK \
3592 "mr 12,%1\n\t" \
3593 "std 2,-16(12)\n\t" /* save tocptr */ \
3594 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3595 "addi 1,1,-128\n\t" /* expand stack frame */ \
3596 /* arg10 */ \
3597 "ld 3,80(12)\n\t" \
3598 "std 3,104(1)\n\t" \
3599 /* arg9 */ \
3600 "ld 3,72(12)\n\t" \
3601 "std 3,96(1)\n\t" \
3602 /* args1-8 */ \
3603 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3604 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3605 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3606 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3607 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3608 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3609 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3610 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3611 "ld 12, 0(12)\n\t" /* target->r12 */ \
3612 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3613 "mr 12,%1\n\t" \
3614 "mr %0,3\n\t" \
3615 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3616 VALGRIND_RESTORE_STACK \
3617 : /*out*/ "=r" (_res) \
3618 : /*in*/ "r" (&_argvec[2]) \
3619 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3620 ); \
3621 lval = (__typeof__(lval)) _res; \
3622 } while (0)
3624 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3625 arg7,arg8,arg9,arg10,arg11) \
3626 do { \
3627 volatile OrigFn _orig = (orig); \
3628 volatile unsigned long _argvec[3+11]; \
3629 volatile unsigned long _res; \
3630 /* _argvec[0] holds current r2 across the call */ \
3631 _argvec[1] = (unsigned long)_orig.r2; \
3632 _argvec[2] = (unsigned long)_orig.nraddr; \
3633 _argvec[2+1] = (unsigned long)arg1; \
3634 _argvec[2+2] = (unsigned long)arg2; \
3635 _argvec[2+3] = (unsigned long)arg3; \
3636 _argvec[2+4] = (unsigned long)arg4; \
3637 _argvec[2+5] = (unsigned long)arg5; \
3638 _argvec[2+6] = (unsigned long)arg6; \
3639 _argvec[2+7] = (unsigned long)arg7; \
3640 _argvec[2+8] = (unsigned long)arg8; \
3641 _argvec[2+9] = (unsigned long)arg9; \
3642 _argvec[2+10] = (unsigned long)arg10; \
3643 _argvec[2+11] = (unsigned long)arg11; \
3644 __asm__ volatile( \
3645 VALGRIND_ALIGN_STACK \
3646 "mr 12,%1\n\t" \
3647 "std 2,-16(12)\n\t" /* save tocptr */ \
3648 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3649 "addi 1,1,-144\n\t" /* expand stack frame */ \
3650 /* arg11 */ \
3651 "ld 3,88(12)\n\t" \
3652 "std 3,112(1)\n\t" \
3653 /* arg10 */ \
3654 "ld 3,80(12)\n\t" \
3655 "std 3,104(1)\n\t" \
3656 /* arg9 */ \
3657 "ld 3,72(12)\n\t" \
3658 "std 3,96(1)\n\t" \
3659 /* args1-8 */ \
3660 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3661 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3662 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3663 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3664 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3665 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3666 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3667 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3668 "ld 12, 0(12)\n\t" /* target->r12 */ \
3669 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3670 "mr 12,%1\n\t" \
3671 "mr %0,3\n\t" \
3672 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3673 VALGRIND_RESTORE_STACK \
3674 : /*out*/ "=r" (_res) \
3675 : /*in*/ "r" (&_argvec[2]) \
3676 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3677 ); \
3678 lval = (__typeof__(lval)) _res; \
3679 } while (0)
3681 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3682 arg7,arg8,arg9,arg10,arg11,arg12) \
3683 do { \
3684 volatile OrigFn _orig = (orig); \
3685 volatile unsigned long _argvec[3+12]; \
3686 volatile unsigned long _res; \
3687 /* _argvec[0] holds current r2 across the call */ \
3688 _argvec[1] = (unsigned long)_orig.r2; \
3689 _argvec[2] = (unsigned long)_orig.nraddr; \
3690 _argvec[2+1] = (unsigned long)arg1; \
3691 _argvec[2+2] = (unsigned long)arg2; \
3692 _argvec[2+3] = (unsigned long)arg3; \
3693 _argvec[2+4] = (unsigned long)arg4; \
3694 _argvec[2+5] = (unsigned long)arg5; \
3695 _argvec[2+6] = (unsigned long)arg6; \
3696 _argvec[2+7] = (unsigned long)arg7; \
3697 _argvec[2+8] = (unsigned long)arg8; \
3698 _argvec[2+9] = (unsigned long)arg9; \
3699 _argvec[2+10] = (unsigned long)arg10; \
3700 _argvec[2+11] = (unsigned long)arg11; \
3701 _argvec[2+12] = (unsigned long)arg12; \
3702 __asm__ volatile( \
3703 VALGRIND_ALIGN_STACK \
3704 "mr 12,%1\n\t" \
3705 "std 2,-16(12)\n\t" /* save tocptr */ \
3706 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3707 "addi 1,1,-144\n\t" /* expand stack frame */ \
3708 /* arg12 */ \
3709 "ld 3,96(12)\n\t" \
3710 "std 3,120(1)\n\t" \
3711 /* arg11 */ \
3712 "ld 3,88(12)\n\t" \
3713 "std 3,112(1)\n\t" \
3714 /* arg10 */ \
3715 "ld 3,80(12)\n\t" \
3716 "std 3,104(1)\n\t" \
3717 /* arg9 */ \
3718 "ld 3,72(12)\n\t" \
3719 "std 3,96(1)\n\t" \
3720 /* args1-8 */ \
3721 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3722 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3723 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3724 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3725 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3726 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3727 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3728 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3729 "ld 12, 0(12)\n\t" /* target->r12 */ \
3730 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3731 "mr 12,%1\n\t" \
3732 "mr %0,3\n\t" \
3733 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3734 VALGRIND_RESTORE_STACK \
3735 : /*out*/ "=r" (_res) \
3736 : /*in*/ "r" (&_argvec[2]) \
3737 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3738 ); \
3739 lval = (__typeof__(lval)) _res; \
3740 } while (0)
3742 #endif /* PLAT_ppc64le_linux */
3744 /* ------------------------- arm-linux ------------------------- */
3746 #if defined(PLAT_arm_linux)
3748 /* These regs are trashed by the hidden call. */
3749 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4", "r12", "r14"
3751 /* Macros to save and align the stack before making a function
3752 call and restore it afterwards as gcc may not keep the stack
3753 pointer aligned if it doesn't realise calls are being made
3754 to other functions. */
3756 /* This is a bit tricky. We store the original stack pointer in r10
3757 as it is callee-saves. gcc doesn't allow the use of r11 for some
3758 reason. Also, we can't directly "bic" the stack pointer in thumb
3759 mode since r13 isn't an allowed register number in that context.
3760 So use r4 as a temporary, since that is about to get trashed
3761 anyway, just after each use of this macro. Side effect is we need
3762 to be very careful about any future changes, since
3763 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
3764 #define VALGRIND_ALIGN_STACK \
3765 "mov r10, sp\n\t" \
3766 "mov r4, sp\n\t" \
3767 "bic r4, r4, #7\n\t" \
3768 "mov sp, r4\n\t"
3769 #define VALGRIND_RESTORE_STACK \
3770 "mov sp, r10\n\t"
3772 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3773 long) == 4. */
3775 #define CALL_FN_W_v(lval, orig) \
3776 do { \
3777 volatile OrigFn _orig = (orig); \
3778 volatile unsigned long _argvec[1]; \
3779 volatile unsigned long _res; \
3780 _argvec[0] = (unsigned long)_orig.nraddr; \
3781 __asm__ volatile( \
3782 VALGRIND_ALIGN_STACK \
3783 "ldr r4, [%1] \n\t" /* target->r4 */ \
3784 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3785 VALGRIND_RESTORE_STACK \
3786 "mov %0, r0\n" \
3787 : /*out*/ "=r" (_res) \
3788 : /*in*/ "0" (&_argvec[0]) \
3789 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3790 ); \
3791 lval = (__typeof__(lval)) _res; \
3792 } while (0)
3794 #define CALL_FN_W_W(lval, orig, arg1) \
3795 do { \
3796 volatile OrigFn _orig = (orig); \
3797 volatile unsigned long _argvec[2]; \
3798 volatile unsigned long _res; \
3799 _argvec[0] = (unsigned long)_orig.nraddr; \
3800 _argvec[1] = (unsigned long)(arg1); \
3801 __asm__ volatile( \
3802 VALGRIND_ALIGN_STACK \
3803 "ldr r0, [%1, #4] \n\t" \
3804 "ldr r4, [%1] \n\t" /* target->r4 */ \
3805 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3806 VALGRIND_RESTORE_STACK \
3807 "mov %0, r0\n" \
3808 : /*out*/ "=r" (_res) \
3809 : /*in*/ "0" (&_argvec[0]) \
3810 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3811 ); \
3812 lval = (__typeof__(lval)) _res; \
3813 } while (0)
3815 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3816 do { \
3817 volatile OrigFn _orig = (orig); \
3818 volatile unsigned long _argvec[3]; \
3819 volatile unsigned long _res; \
3820 _argvec[0] = (unsigned long)_orig.nraddr; \
3821 _argvec[1] = (unsigned long)(arg1); \
3822 _argvec[2] = (unsigned long)(arg2); \
3823 __asm__ volatile( \
3824 VALGRIND_ALIGN_STACK \
3825 "ldr r0, [%1, #4] \n\t" \
3826 "ldr r1, [%1, #8] \n\t" \
3827 "ldr r4, [%1] \n\t" /* target->r4 */ \
3828 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3829 VALGRIND_RESTORE_STACK \
3830 "mov %0, r0\n" \
3831 : /*out*/ "=r" (_res) \
3832 : /*in*/ "0" (&_argvec[0]) \
3833 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3834 ); \
3835 lval = (__typeof__(lval)) _res; \
3836 } while (0)
3838 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3839 do { \
3840 volatile OrigFn _orig = (orig); \
3841 volatile unsigned long _argvec[4]; \
3842 volatile unsigned long _res; \
3843 _argvec[0] = (unsigned long)_orig.nraddr; \
3844 _argvec[1] = (unsigned long)(arg1); \
3845 _argvec[2] = (unsigned long)(arg2); \
3846 _argvec[3] = (unsigned long)(arg3); \
3847 __asm__ volatile( \
3848 VALGRIND_ALIGN_STACK \
3849 "ldr r0, [%1, #4] \n\t" \
3850 "ldr r1, [%1, #8] \n\t" \
3851 "ldr r2, [%1, #12] \n\t" \
3852 "ldr r4, [%1] \n\t" /* target->r4 */ \
3853 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3854 VALGRIND_RESTORE_STACK \
3855 "mov %0, r0\n" \
3856 : /*out*/ "=r" (_res) \
3857 : /*in*/ "0" (&_argvec[0]) \
3858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3859 ); \
3860 lval = (__typeof__(lval)) _res; \
3861 } while (0)
3863 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3864 do { \
3865 volatile OrigFn _orig = (orig); \
3866 volatile unsigned long _argvec[5]; \
3867 volatile unsigned long _res; \
3868 _argvec[0] = (unsigned long)_orig.nraddr; \
3869 _argvec[1] = (unsigned long)(arg1); \
3870 _argvec[2] = (unsigned long)(arg2); \
3871 _argvec[3] = (unsigned long)(arg3); \
3872 _argvec[4] = (unsigned long)(arg4); \
3873 __asm__ volatile( \
3874 VALGRIND_ALIGN_STACK \
3875 "ldr r0, [%1, #4] \n\t" \
3876 "ldr r1, [%1, #8] \n\t" \
3877 "ldr r2, [%1, #12] \n\t" \
3878 "ldr r3, [%1, #16] \n\t" \
3879 "ldr r4, [%1] \n\t" /* target->r4 */ \
3880 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3881 VALGRIND_RESTORE_STACK \
3882 "mov %0, r0" \
3883 : /*out*/ "=r" (_res) \
3884 : /*in*/ "0" (&_argvec[0]) \
3885 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3886 ); \
3887 lval = (__typeof__(lval)) _res; \
3888 } while (0)
3890 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3891 do { \
3892 volatile OrigFn _orig = (orig); \
3893 volatile unsigned long _argvec[6]; \
3894 volatile unsigned long _res; \
3895 _argvec[0] = (unsigned long)_orig.nraddr; \
3896 _argvec[1] = (unsigned long)(arg1); \
3897 _argvec[2] = (unsigned long)(arg2); \
3898 _argvec[3] = (unsigned long)(arg3); \
3899 _argvec[4] = (unsigned long)(arg4); \
3900 _argvec[5] = (unsigned long)(arg5); \
3901 __asm__ volatile( \
3902 VALGRIND_ALIGN_STACK \
3903 "sub sp, sp, #4 \n\t" \
3904 "ldr r0, [%1, #20] \n\t" \
3905 "push {r0} \n\t" \
3906 "ldr r0, [%1, #4] \n\t" \
3907 "ldr r1, [%1, #8] \n\t" \
3908 "ldr r2, [%1, #12] \n\t" \
3909 "ldr r3, [%1, #16] \n\t" \
3910 "ldr r4, [%1] \n\t" /* target->r4 */ \
3911 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3912 VALGRIND_RESTORE_STACK \
3913 "mov %0, r0" \
3914 : /*out*/ "=r" (_res) \
3915 : /*in*/ "0" (&_argvec[0]) \
3916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3917 ); \
3918 lval = (__typeof__(lval)) _res; \
3919 } while (0)
3921 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3922 do { \
3923 volatile OrigFn _orig = (orig); \
3924 volatile unsigned long _argvec[7]; \
3925 volatile unsigned long _res; \
3926 _argvec[0] = (unsigned long)_orig.nraddr; \
3927 _argvec[1] = (unsigned long)(arg1); \
3928 _argvec[2] = (unsigned long)(arg2); \
3929 _argvec[3] = (unsigned long)(arg3); \
3930 _argvec[4] = (unsigned long)(arg4); \
3931 _argvec[5] = (unsigned long)(arg5); \
3932 _argvec[6] = (unsigned long)(arg6); \
3933 __asm__ volatile( \
3934 VALGRIND_ALIGN_STACK \
3935 "ldr r0, [%1, #20] \n\t" \
3936 "ldr r1, [%1, #24] \n\t" \
3937 "push {r0, r1} \n\t" \
3938 "ldr r0, [%1, #4] \n\t" \
3939 "ldr r1, [%1, #8] \n\t" \
3940 "ldr r2, [%1, #12] \n\t" \
3941 "ldr r3, [%1, #16] \n\t" \
3942 "ldr r4, [%1] \n\t" /* target->r4 */ \
3943 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3944 VALGRIND_RESTORE_STACK \
3945 "mov %0, r0" \
3946 : /*out*/ "=r" (_res) \
3947 : /*in*/ "0" (&_argvec[0]) \
3948 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3949 ); \
3950 lval = (__typeof__(lval)) _res; \
3951 } while (0)
3953 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3954 arg7) \
3955 do { \
3956 volatile OrigFn _orig = (orig); \
3957 volatile unsigned long _argvec[8]; \
3958 volatile unsigned long _res; \
3959 _argvec[0] = (unsigned long)_orig.nraddr; \
3960 _argvec[1] = (unsigned long)(arg1); \
3961 _argvec[2] = (unsigned long)(arg2); \
3962 _argvec[3] = (unsigned long)(arg3); \
3963 _argvec[4] = (unsigned long)(arg4); \
3964 _argvec[5] = (unsigned long)(arg5); \
3965 _argvec[6] = (unsigned long)(arg6); \
3966 _argvec[7] = (unsigned long)(arg7); \
3967 __asm__ volatile( \
3968 VALGRIND_ALIGN_STACK \
3969 "sub sp, sp, #4 \n\t" \
3970 "ldr r0, [%1, #20] \n\t" \
3971 "ldr r1, [%1, #24] \n\t" \
3972 "ldr r2, [%1, #28] \n\t" \
3973 "push {r0, r1, r2} \n\t" \
3974 "ldr r0, [%1, #4] \n\t" \
3975 "ldr r1, [%1, #8] \n\t" \
3976 "ldr r2, [%1, #12] \n\t" \
3977 "ldr r3, [%1, #16] \n\t" \
3978 "ldr r4, [%1] \n\t" /* target->r4 */ \
3979 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3980 VALGRIND_RESTORE_STACK \
3981 "mov %0, r0" \
3982 : /*out*/ "=r" (_res) \
3983 : /*in*/ "0" (&_argvec[0]) \
3984 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
3985 ); \
3986 lval = (__typeof__(lval)) _res; \
3987 } while (0)
3989 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3990 arg7,arg8) \
3991 do { \
3992 volatile OrigFn _orig = (orig); \
3993 volatile unsigned long _argvec[9]; \
3994 volatile unsigned long _res; \
3995 _argvec[0] = (unsigned long)_orig.nraddr; \
3996 _argvec[1] = (unsigned long)(arg1); \
3997 _argvec[2] = (unsigned long)(arg2); \
3998 _argvec[3] = (unsigned long)(arg3); \
3999 _argvec[4] = (unsigned long)(arg4); \
4000 _argvec[5] = (unsigned long)(arg5); \
4001 _argvec[6] = (unsigned long)(arg6); \
4002 _argvec[7] = (unsigned long)(arg7); \
4003 _argvec[8] = (unsigned long)(arg8); \
4004 __asm__ volatile( \
4005 VALGRIND_ALIGN_STACK \
4006 "ldr r0, [%1, #20] \n\t" \
4007 "ldr r1, [%1, #24] \n\t" \
4008 "ldr r2, [%1, #28] \n\t" \
4009 "ldr r3, [%1, #32] \n\t" \
4010 "push {r0, r1, r2, r3} \n\t" \
4011 "ldr r0, [%1, #4] \n\t" \
4012 "ldr r1, [%1, #8] \n\t" \
4013 "ldr r2, [%1, #12] \n\t" \
4014 "ldr r3, [%1, #16] \n\t" \
4015 "ldr r4, [%1] \n\t" /* target->r4 */ \
4016 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
4017 VALGRIND_RESTORE_STACK \
4018 "mov %0, r0" \
4019 : /*out*/ "=r" (_res) \
4020 : /*in*/ "0" (&_argvec[0]) \
4021 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
4022 ); \
4023 lval = (__typeof__(lval)) _res; \
4024 } while (0)
4026 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4027 arg7,arg8,arg9) \
4028 do { \
4029 volatile OrigFn _orig = (orig); \
4030 volatile unsigned long _argvec[10]; \
4031 volatile unsigned long _res; \
4032 _argvec[0] = (unsigned long)_orig.nraddr; \
4033 _argvec[1] = (unsigned long)(arg1); \
4034 _argvec[2] = (unsigned long)(arg2); \
4035 _argvec[3] = (unsigned long)(arg3); \
4036 _argvec[4] = (unsigned long)(arg4); \
4037 _argvec[5] = (unsigned long)(arg5); \
4038 _argvec[6] = (unsigned long)(arg6); \
4039 _argvec[7] = (unsigned long)(arg7); \
4040 _argvec[8] = (unsigned long)(arg8); \
4041 _argvec[9] = (unsigned long)(arg9); \
4042 __asm__ volatile( \
4043 VALGRIND_ALIGN_STACK \
4044 "sub sp, sp, #4 \n\t" \
4045 "ldr r0, [%1, #20] \n\t" \
4046 "ldr r1, [%1, #24] \n\t" \
4047 "ldr r2, [%1, #28] \n\t" \
4048 "ldr r3, [%1, #32] \n\t" \
4049 "ldr r4, [%1, #36] \n\t" \
4050 "push {r0, r1, r2, r3, r4} \n\t" \
4051 "ldr r0, [%1, #4] \n\t" \
4052 "ldr r1, [%1, #8] \n\t" \
4053 "ldr r2, [%1, #12] \n\t" \
4054 "ldr r3, [%1, #16] \n\t" \
4055 "ldr r4, [%1] \n\t" /* target->r4 */ \
4056 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
4057 VALGRIND_RESTORE_STACK \
4058 "mov %0, r0" \
4059 : /*out*/ "=r" (_res) \
4060 : /*in*/ "0" (&_argvec[0]) \
4061 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
4062 ); \
4063 lval = (__typeof__(lval)) _res; \
4064 } while (0)
4066 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4067 arg7,arg8,arg9,arg10) \
4068 do { \
4069 volatile OrigFn _orig = (orig); \
4070 volatile unsigned long _argvec[11]; \
4071 volatile unsigned long _res; \
4072 _argvec[0] = (unsigned long)_orig.nraddr; \
4073 _argvec[1] = (unsigned long)(arg1); \
4074 _argvec[2] = (unsigned long)(arg2); \
4075 _argvec[3] = (unsigned long)(arg3); \
4076 _argvec[4] = (unsigned long)(arg4); \
4077 _argvec[5] = (unsigned long)(arg5); \
4078 _argvec[6] = (unsigned long)(arg6); \
4079 _argvec[7] = (unsigned long)(arg7); \
4080 _argvec[8] = (unsigned long)(arg8); \
4081 _argvec[9] = (unsigned long)(arg9); \
4082 _argvec[10] = (unsigned long)(arg10); \
4083 __asm__ volatile( \
4084 VALGRIND_ALIGN_STACK \
4085 "ldr r0, [%1, #40] \n\t" \
4086 "push {r0} \n\t" \
4087 "ldr r0, [%1, #20] \n\t" \
4088 "ldr r1, [%1, #24] \n\t" \
4089 "ldr r2, [%1, #28] \n\t" \
4090 "ldr r3, [%1, #32] \n\t" \
4091 "ldr r4, [%1, #36] \n\t" \
4092 "push {r0, r1, r2, r3, r4} \n\t" \
4093 "ldr r0, [%1, #4] \n\t" \
4094 "ldr r1, [%1, #8] \n\t" \
4095 "ldr r2, [%1, #12] \n\t" \
4096 "ldr r3, [%1, #16] \n\t" \
4097 "ldr r4, [%1] \n\t" /* target->r4 */ \
4098 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
4099 VALGRIND_RESTORE_STACK \
4100 "mov %0, r0" \
4101 : /*out*/ "=r" (_res) \
4102 : /*in*/ "0" (&_argvec[0]) \
4103 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
4104 ); \
4105 lval = (__typeof__(lval)) _res; \
4106 } while (0)
4108 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4109 arg6,arg7,arg8,arg9,arg10, \
4110 arg11) \
4111 do { \
4112 volatile OrigFn _orig = (orig); \
4113 volatile unsigned long _argvec[12]; \
4114 volatile unsigned long _res; \
4115 _argvec[0] = (unsigned long)_orig.nraddr; \
4116 _argvec[1] = (unsigned long)(arg1); \
4117 _argvec[2] = (unsigned long)(arg2); \
4118 _argvec[3] = (unsigned long)(arg3); \
4119 _argvec[4] = (unsigned long)(arg4); \
4120 _argvec[5] = (unsigned long)(arg5); \
4121 _argvec[6] = (unsigned long)(arg6); \
4122 _argvec[7] = (unsigned long)(arg7); \
4123 _argvec[8] = (unsigned long)(arg8); \
4124 _argvec[9] = (unsigned long)(arg9); \
4125 _argvec[10] = (unsigned long)(arg10); \
4126 _argvec[11] = (unsigned long)(arg11); \
4127 __asm__ volatile( \
4128 VALGRIND_ALIGN_STACK \
4129 "sub sp, sp, #4 \n\t" \
4130 "ldr r0, [%1, #40] \n\t" \
4131 "ldr r1, [%1, #44] \n\t" \
4132 "push {r0, r1} \n\t" \
4133 "ldr r0, [%1, #20] \n\t" \
4134 "ldr r1, [%1, #24] \n\t" \
4135 "ldr r2, [%1, #28] \n\t" \
4136 "ldr r3, [%1, #32] \n\t" \
4137 "ldr r4, [%1, #36] \n\t" \
4138 "push {r0, r1, r2, r3, r4} \n\t" \
4139 "ldr r0, [%1, #4] \n\t" \
4140 "ldr r1, [%1, #8] \n\t" \
4141 "ldr r2, [%1, #12] \n\t" \
4142 "ldr r3, [%1, #16] \n\t" \
4143 "ldr r4, [%1] \n\t" /* target->r4 */ \
4144 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
4145 VALGRIND_RESTORE_STACK \
4146 "mov %0, r0" \
4147 : /*out*/ "=r" (_res) \
4148 : /*in*/ "0" (&_argvec[0]) \
4149 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
4150 ); \
4151 lval = (__typeof__(lval)) _res; \
4152 } while (0)
4154 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4155 arg6,arg7,arg8,arg9,arg10, \
4156 arg11,arg12) \
4157 do { \
4158 volatile OrigFn _orig = (orig); \
4159 volatile unsigned long _argvec[13]; \
4160 volatile unsigned long _res; \
4161 _argvec[0] = (unsigned long)_orig.nraddr; \
4162 _argvec[1] = (unsigned long)(arg1); \
4163 _argvec[2] = (unsigned long)(arg2); \
4164 _argvec[3] = (unsigned long)(arg3); \
4165 _argvec[4] = (unsigned long)(arg4); \
4166 _argvec[5] = (unsigned long)(arg5); \
4167 _argvec[6] = (unsigned long)(arg6); \
4168 _argvec[7] = (unsigned long)(arg7); \
4169 _argvec[8] = (unsigned long)(arg8); \
4170 _argvec[9] = (unsigned long)(arg9); \
4171 _argvec[10] = (unsigned long)(arg10); \
4172 _argvec[11] = (unsigned long)(arg11); \
4173 _argvec[12] = (unsigned long)(arg12); \
4174 __asm__ volatile( \
4175 VALGRIND_ALIGN_STACK \
4176 "ldr r0, [%1, #40] \n\t" \
4177 "ldr r1, [%1, #44] \n\t" \
4178 "ldr r2, [%1, #48] \n\t" \
4179 "push {r0, r1, r2} \n\t" \
4180 "ldr r0, [%1, #20] \n\t" \
4181 "ldr r1, [%1, #24] \n\t" \
4182 "ldr r2, [%1, #28] \n\t" \
4183 "ldr r3, [%1, #32] \n\t" \
4184 "ldr r4, [%1, #36] \n\t" \
4185 "push {r0, r1, r2, r3, r4} \n\t" \
4186 "ldr r0, [%1, #4] \n\t" \
4187 "ldr r1, [%1, #8] \n\t" \
4188 "ldr r2, [%1, #12] \n\t" \
4189 "ldr r3, [%1, #16] \n\t" \
4190 "ldr r4, [%1] \n\t" /* target->r4 */ \
4191 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
4192 VALGRIND_RESTORE_STACK \
4193 "mov %0, r0" \
4194 : /*out*/ "=r" (_res) \
4195 : /*in*/ "0" (&_argvec[0]) \
4196 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
4197 ); \
4198 lval = (__typeof__(lval)) _res; \
4199 } while (0)
4201 #endif /* PLAT_arm_linux */
4203 /* ------------------------ arm64-linux ------------------------ */
4205 #if defined(PLAT_arm64_linux)
4207 /* These regs are trashed by the hidden call. */
4208 #define __CALLER_SAVED_REGS \
4209 "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
4210 "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
4211 "x18", "x19", "x20", "x30", \
4212 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
4213 "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
4214 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
4215 "v26", "v27", "v28", "v29", "v30", "v31"
4217 /* x21 is callee-saved, so we can use it to save and restore SP around
4218 the hidden call. */
4219 #define VALGRIND_ALIGN_STACK \
4220 "mov x21, sp\n\t" \
4221 "bic sp, x21, #15\n\t"
4222 #define VALGRIND_RESTORE_STACK \
4223 "mov sp, x21\n\t"
4225 /* These CALL_FN_ macros assume that on arm64-linux,
4226 sizeof(unsigned long) == 8. */
4228 #define CALL_FN_W_v(lval, orig) \
4229 do { \
4230 volatile OrigFn _orig = (orig); \
4231 volatile unsigned long _argvec[1]; \
4232 volatile unsigned long _res; \
4233 _argvec[0] = (unsigned long)_orig.nraddr; \
4234 __asm__ volatile( \
4235 VALGRIND_ALIGN_STACK \
4236 "ldr x8, [%1] \n\t" /* target->x8 */ \
4237 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4238 VALGRIND_RESTORE_STACK \
4239 "mov %0, x0\n" \
4240 : /*out*/ "=r" (_res) \
4241 : /*in*/ "0" (&_argvec[0]) \
4242 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4243 ); \
4244 lval = (__typeof__(lval)) _res; \
4245 } while (0)
4247 #define CALL_FN_W_W(lval, orig, arg1) \
4248 do { \
4249 volatile OrigFn _orig = (orig); \
4250 volatile unsigned long _argvec[2]; \
4251 volatile unsigned long _res; \
4252 _argvec[0] = (unsigned long)_orig.nraddr; \
4253 _argvec[1] = (unsigned long)(arg1); \
4254 __asm__ volatile( \
4255 VALGRIND_ALIGN_STACK \
4256 "ldr x0, [%1, #8] \n\t" \
4257 "ldr x8, [%1] \n\t" /* target->x8 */ \
4258 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4259 VALGRIND_RESTORE_STACK \
4260 "mov %0, x0\n" \
4261 : /*out*/ "=r" (_res) \
4262 : /*in*/ "0" (&_argvec[0]) \
4263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4264 ); \
4265 lval = (__typeof__(lval)) _res; \
4266 } while (0)
4268 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
4269 do { \
4270 volatile OrigFn _orig = (orig); \
4271 volatile unsigned long _argvec[3]; \
4272 volatile unsigned long _res; \
4273 _argvec[0] = (unsigned long)_orig.nraddr; \
4274 _argvec[1] = (unsigned long)(arg1); \
4275 _argvec[2] = (unsigned long)(arg2); \
4276 __asm__ volatile( \
4277 VALGRIND_ALIGN_STACK \
4278 "ldr x0, [%1, #8] \n\t" \
4279 "ldr x1, [%1, #16] \n\t" \
4280 "ldr x8, [%1] \n\t" /* target->x8 */ \
4281 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4282 VALGRIND_RESTORE_STACK \
4283 "mov %0, x0\n" \
4284 : /*out*/ "=r" (_res) \
4285 : /*in*/ "0" (&_argvec[0]) \
4286 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4287 ); \
4288 lval = (__typeof__(lval)) _res; \
4289 } while (0)
4291 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
4292 do { \
4293 volatile OrigFn _orig = (orig); \
4294 volatile unsigned long _argvec[4]; \
4295 volatile unsigned long _res; \
4296 _argvec[0] = (unsigned long)_orig.nraddr; \
4297 _argvec[1] = (unsigned long)(arg1); \
4298 _argvec[2] = (unsigned long)(arg2); \
4299 _argvec[3] = (unsigned long)(arg3); \
4300 __asm__ volatile( \
4301 VALGRIND_ALIGN_STACK \
4302 "ldr x0, [%1, #8] \n\t" \
4303 "ldr x1, [%1, #16] \n\t" \
4304 "ldr x2, [%1, #24] \n\t" \
4305 "ldr x8, [%1] \n\t" /* target->x8 */ \
4306 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4307 VALGRIND_RESTORE_STACK \
4308 "mov %0, x0\n" \
4309 : /*out*/ "=r" (_res) \
4310 : /*in*/ "0" (&_argvec[0]) \
4311 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4312 ); \
4313 lval = (__typeof__(lval)) _res; \
4314 } while (0)
4316 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
4317 do { \
4318 volatile OrigFn _orig = (orig); \
4319 volatile unsigned long _argvec[5]; \
4320 volatile unsigned long _res; \
4321 _argvec[0] = (unsigned long)_orig.nraddr; \
4322 _argvec[1] = (unsigned long)(arg1); \
4323 _argvec[2] = (unsigned long)(arg2); \
4324 _argvec[3] = (unsigned long)(arg3); \
4325 _argvec[4] = (unsigned long)(arg4); \
4326 __asm__ volatile( \
4327 VALGRIND_ALIGN_STACK \
4328 "ldr x0, [%1, #8] \n\t" \
4329 "ldr x1, [%1, #16] \n\t" \
4330 "ldr x2, [%1, #24] \n\t" \
4331 "ldr x3, [%1, #32] \n\t" \
4332 "ldr x8, [%1] \n\t" /* target->x8 */ \
4333 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4334 VALGRIND_RESTORE_STACK \
4335 "mov %0, x0" \
4336 : /*out*/ "=r" (_res) \
4337 : /*in*/ "0" (&_argvec[0]) \
4338 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4339 ); \
4340 lval = (__typeof__(lval)) _res; \
4341 } while (0)
4343 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
4344 do { \
4345 volatile OrigFn _orig = (orig); \
4346 volatile unsigned long _argvec[6]; \
4347 volatile unsigned long _res; \
4348 _argvec[0] = (unsigned long)_orig.nraddr; \
4349 _argvec[1] = (unsigned long)(arg1); \
4350 _argvec[2] = (unsigned long)(arg2); \
4351 _argvec[3] = (unsigned long)(arg3); \
4352 _argvec[4] = (unsigned long)(arg4); \
4353 _argvec[5] = (unsigned long)(arg5); \
4354 __asm__ volatile( \
4355 VALGRIND_ALIGN_STACK \
4356 "ldr x0, [%1, #8] \n\t" \
4357 "ldr x1, [%1, #16] \n\t" \
4358 "ldr x2, [%1, #24] \n\t" \
4359 "ldr x3, [%1, #32] \n\t" \
4360 "ldr x4, [%1, #40] \n\t" \
4361 "ldr x8, [%1] \n\t" /* target->x8 */ \
4362 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4363 VALGRIND_RESTORE_STACK \
4364 "mov %0, x0" \
4365 : /*out*/ "=r" (_res) \
4366 : /*in*/ "0" (&_argvec[0]) \
4367 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4368 ); \
4369 lval = (__typeof__(lval)) _res; \
4370 } while (0)
4372 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
4373 do { \
4374 volatile OrigFn _orig = (orig); \
4375 volatile unsigned long _argvec[7]; \
4376 volatile unsigned long _res; \
4377 _argvec[0] = (unsigned long)_orig.nraddr; \
4378 _argvec[1] = (unsigned long)(arg1); \
4379 _argvec[2] = (unsigned long)(arg2); \
4380 _argvec[3] = (unsigned long)(arg3); \
4381 _argvec[4] = (unsigned long)(arg4); \
4382 _argvec[5] = (unsigned long)(arg5); \
4383 _argvec[6] = (unsigned long)(arg6); \
4384 __asm__ volatile( \
4385 VALGRIND_ALIGN_STACK \
4386 "ldr x0, [%1, #8] \n\t" \
4387 "ldr x1, [%1, #16] \n\t" \
4388 "ldr x2, [%1, #24] \n\t" \
4389 "ldr x3, [%1, #32] \n\t" \
4390 "ldr x4, [%1, #40] \n\t" \
4391 "ldr x5, [%1, #48] \n\t" \
4392 "ldr x8, [%1] \n\t" /* target->x8 */ \
4393 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4394 VALGRIND_RESTORE_STACK \
4395 "mov %0, x0" \
4396 : /*out*/ "=r" (_res) \
4397 : /*in*/ "0" (&_argvec[0]) \
4398 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4399 ); \
4400 lval = (__typeof__(lval)) _res; \
4401 } while (0)
4403 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4404 arg7) \
4405 do { \
4406 volatile OrigFn _orig = (orig); \
4407 volatile unsigned long _argvec[8]; \
4408 volatile unsigned long _res; \
4409 _argvec[0] = (unsigned long)_orig.nraddr; \
4410 _argvec[1] = (unsigned long)(arg1); \
4411 _argvec[2] = (unsigned long)(arg2); \
4412 _argvec[3] = (unsigned long)(arg3); \
4413 _argvec[4] = (unsigned long)(arg4); \
4414 _argvec[5] = (unsigned long)(arg5); \
4415 _argvec[6] = (unsigned long)(arg6); \
4416 _argvec[7] = (unsigned long)(arg7); \
4417 __asm__ volatile( \
4418 VALGRIND_ALIGN_STACK \
4419 "ldr x0, [%1, #8] \n\t" \
4420 "ldr x1, [%1, #16] \n\t" \
4421 "ldr x2, [%1, #24] \n\t" \
4422 "ldr x3, [%1, #32] \n\t" \
4423 "ldr x4, [%1, #40] \n\t" \
4424 "ldr x5, [%1, #48] \n\t" \
4425 "ldr x6, [%1, #56] \n\t" \
4426 "ldr x8, [%1] \n\t" /* target->x8 */ \
4427 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4428 VALGRIND_RESTORE_STACK \
4429 "mov %0, x0" \
4430 : /*out*/ "=r" (_res) \
4431 : /*in*/ "0" (&_argvec[0]) \
4432 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4433 ); \
4434 lval = (__typeof__(lval)) _res; \
4435 } while (0)
4437 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4438 arg7,arg8) \
4439 do { \
4440 volatile OrigFn _orig = (orig); \
4441 volatile unsigned long _argvec[9]; \
4442 volatile unsigned long _res; \
4443 _argvec[0] = (unsigned long)_orig.nraddr; \
4444 _argvec[1] = (unsigned long)(arg1); \
4445 _argvec[2] = (unsigned long)(arg2); \
4446 _argvec[3] = (unsigned long)(arg3); \
4447 _argvec[4] = (unsigned long)(arg4); \
4448 _argvec[5] = (unsigned long)(arg5); \
4449 _argvec[6] = (unsigned long)(arg6); \
4450 _argvec[7] = (unsigned long)(arg7); \
4451 _argvec[8] = (unsigned long)(arg8); \
4452 __asm__ volatile( \
4453 VALGRIND_ALIGN_STACK \
4454 "ldr x0, [%1, #8] \n\t" \
4455 "ldr x1, [%1, #16] \n\t" \
4456 "ldr x2, [%1, #24] \n\t" \
4457 "ldr x3, [%1, #32] \n\t" \
4458 "ldr x4, [%1, #40] \n\t" \
4459 "ldr x5, [%1, #48] \n\t" \
4460 "ldr x6, [%1, #56] \n\t" \
4461 "ldr x7, [%1, #64] \n\t" \
4462 "ldr x8, [%1] \n\t" /* target->x8 */ \
4463 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4464 VALGRIND_RESTORE_STACK \
4465 "mov %0, x0" \
4466 : /*out*/ "=r" (_res) \
4467 : /*in*/ "0" (&_argvec[0]) \
4468 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4469 ); \
4470 lval = (__typeof__(lval)) _res; \
4471 } while (0)
4473 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4474 arg7,arg8,arg9) \
4475 do { \
4476 volatile OrigFn _orig = (orig); \
4477 volatile unsigned long _argvec[10]; \
4478 volatile unsigned long _res; \
4479 _argvec[0] = (unsigned long)_orig.nraddr; \
4480 _argvec[1] = (unsigned long)(arg1); \
4481 _argvec[2] = (unsigned long)(arg2); \
4482 _argvec[3] = (unsigned long)(arg3); \
4483 _argvec[4] = (unsigned long)(arg4); \
4484 _argvec[5] = (unsigned long)(arg5); \
4485 _argvec[6] = (unsigned long)(arg6); \
4486 _argvec[7] = (unsigned long)(arg7); \
4487 _argvec[8] = (unsigned long)(arg8); \
4488 _argvec[9] = (unsigned long)(arg9); \
4489 __asm__ volatile( \
4490 VALGRIND_ALIGN_STACK \
4491 "sub sp, sp, #0x20 \n\t" \
4492 "ldr x0, [%1, #8] \n\t" \
4493 "ldr x1, [%1, #16] \n\t" \
4494 "ldr x2, [%1, #24] \n\t" \
4495 "ldr x3, [%1, #32] \n\t" \
4496 "ldr x4, [%1, #40] \n\t" \
4497 "ldr x5, [%1, #48] \n\t" \
4498 "ldr x6, [%1, #56] \n\t" \
4499 "ldr x7, [%1, #64] \n\t" \
4500 "ldr x8, [%1, #72] \n\t" \
4501 "str x8, [sp, #0] \n\t" \
4502 "ldr x8, [%1] \n\t" /* target->x8 */ \
4503 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4504 VALGRIND_RESTORE_STACK \
4505 "mov %0, x0" \
4506 : /*out*/ "=r" (_res) \
4507 : /*in*/ "0" (&_argvec[0]) \
4508 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4509 ); \
4510 lval = (__typeof__(lval)) _res; \
4511 } while (0)
4513 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4514 arg7,arg8,arg9,arg10) \
4515 do { \
4516 volatile OrigFn _orig = (orig); \
4517 volatile unsigned long _argvec[11]; \
4518 volatile unsigned long _res; \
4519 _argvec[0] = (unsigned long)_orig.nraddr; \
4520 _argvec[1] = (unsigned long)(arg1); \
4521 _argvec[2] = (unsigned long)(arg2); \
4522 _argvec[3] = (unsigned long)(arg3); \
4523 _argvec[4] = (unsigned long)(arg4); \
4524 _argvec[5] = (unsigned long)(arg5); \
4525 _argvec[6] = (unsigned long)(arg6); \
4526 _argvec[7] = (unsigned long)(arg7); \
4527 _argvec[8] = (unsigned long)(arg8); \
4528 _argvec[9] = (unsigned long)(arg9); \
4529 _argvec[10] = (unsigned long)(arg10); \
4530 __asm__ volatile( \
4531 VALGRIND_ALIGN_STACK \
4532 "sub sp, sp, #0x20 \n\t" \
4533 "ldr x0, [%1, #8] \n\t" \
4534 "ldr x1, [%1, #16] \n\t" \
4535 "ldr x2, [%1, #24] \n\t" \
4536 "ldr x3, [%1, #32] \n\t" \
4537 "ldr x4, [%1, #40] \n\t" \
4538 "ldr x5, [%1, #48] \n\t" \
4539 "ldr x6, [%1, #56] \n\t" \
4540 "ldr x7, [%1, #64] \n\t" \
4541 "ldr x8, [%1, #72] \n\t" \
4542 "str x8, [sp, #0] \n\t" \
4543 "ldr x8, [%1, #80] \n\t" \
4544 "str x8, [sp, #8] \n\t" \
4545 "ldr x8, [%1] \n\t" /* target->x8 */ \
4546 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4547 VALGRIND_RESTORE_STACK \
4548 "mov %0, x0" \
4549 : /*out*/ "=r" (_res) \
4550 : /*in*/ "0" (&_argvec[0]) \
4551 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4552 ); \
4553 lval = (__typeof__(lval)) _res; \
4554 } while (0)
4556 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4557 arg7,arg8,arg9,arg10,arg11) \
4558 do { \
4559 volatile OrigFn _orig = (orig); \
4560 volatile unsigned long _argvec[12]; \
4561 volatile unsigned long _res; \
4562 _argvec[0] = (unsigned long)_orig.nraddr; \
4563 _argvec[1] = (unsigned long)(arg1); \
4564 _argvec[2] = (unsigned long)(arg2); \
4565 _argvec[3] = (unsigned long)(arg3); \
4566 _argvec[4] = (unsigned long)(arg4); \
4567 _argvec[5] = (unsigned long)(arg5); \
4568 _argvec[6] = (unsigned long)(arg6); \
4569 _argvec[7] = (unsigned long)(arg7); \
4570 _argvec[8] = (unsigned long)(arg8); \
4571 _argvec[9] = (unsigned long)(arg9); \
4572 _argvec[10] = (unsigned long)(arg10); \
4573 _argvec[11] = (unsigned long)(arg11); \
4574 __asm__ volatile( \
4575 VALGRIND_ALIGN_STACK \
4576 "sub sp, sp, #0x30 \n\t" \
4577 "ldr x0, [%1, #8] \n\t" \
4578 "ldr x1, [%1, #16] \n\t" \
4579 "ldr x2, [%1, #24] \n\t" \
4580 "ldr x3, [%1, #32] \n\t" \
4581 "ldr x4, [%1, #40] \n\t" \
4582 "ldr x5, [%1, #48] \n\t" \
4583 "ldr x6, [%1, #56] \n\t" \
4584 "ldr x7, [%1, #64] \n\t" \
4585 "ldr x8, [%1, #72] \n\t" \
4586 "str x8, [sp, #0] \n\t" \
4587 "ldr x8, [%1, #80] \n\t" \
4588 "str x8, [sp, #8] \n\t" \
4589 "ldr x8, [%1, #88] \n\t" \
4590 "str x8, [sp, #16] \n\t" \
4591 "ldr x8, [%1] \n\t" /* target->x8 */ \
4592 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4593 VALGRIND_RESTORE_STACK \
4594 "mov %0, x0" \
4595 : /*out*/ "=r" (_res) \
4596 : /*in*/ "0" (&_argvec[0]) \
4597 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4598 ); \
4599 lval = (__typeof__(lval)) _res; \
4600 } while (0)
4602 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4603 arg7,arg8,arg9,arg10,arg11, \
4604 arg12) \
4605 do { \
4606 volatile OrigFn _orig = (orig); \
4607 volatile unsigned long _argvec[13]; \
4608 volatile unsigned long _res; \
4609 _argvec[0] = (unsigned long)_orig.nraddr; \
4610 _argvec[1] = (unsigned long)(arg1); \
4611 _argvec[2] = (unsigned long)(arg2); \
4612 _argvec[3] = (unsigned long)(arg3); \
4613 _argvec[4] = (unsigned long)(arg4); \
4614 _argvec[5] = (unsigned long)(arg5); \
4615 _argvec[6] = (unsigned long)(arg6); \
4616 _argvec[7] = (unsigned long)(arg7); \
4617 _argvec[8] = (unsigned long)(arg8); \
4618 _argvec[9] = (unsigned long)(arg9); \
4619 _argvec[10] = (unsigned long)(arg10); \
4620 _argvec[11] = (unsigned long)(arg11); \
4621 _argvec[12] = (unsigned long)(arg12); \
4622 __asm__ volatile( \
4623 VALGRIND_ALIGN_STACK \
4624 "sub sp, sp, #0x30 \n\t" \
4625 "ldr x0, [%1, #8] \n\t" \
4626 "ldr x1, [%1, #16] \n\t" \
4627 "ldr x2, [%1, #24] \n\t" \
4628 "ldr x3, [%1, #32] \n\t" \
4629 "ldr x4, [%1, #40] \n\t" \
4630 "ldr x5, [%1, #48] \n\t" \
4631 "ldr x6, [%1, #56] \n\t" \
4632 "ldr x7, [%1, #64] \n\t" \
4633 "ldr x8, [%1, #72] \n\t" \
4634 "str x8, [sp, #0] \n\t" \
4635 "ldr x8, [%1, #80] \n\t" \
4636 "str x8, [sp, #8] \n\t" \
4637 "ldr x8, [%1, #88] \n\t" \
4638 "str x8, [sp, #16] \n\t" \
4639 "ldr x8, [%1, #96] \n\t" \
4640 "str x8, [sp, #24] \n\t" \
4641 "ldr x8, [%1] \n\t" /* target->x8 */ \
4642 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4643 VALGRIND_RESTORE_STACK \
4644 "mov %0, x0" \
4645 : /*out*/ "=r" (_res) \
4646 : /*in*/ "0" (&_argvec[0]) \
4647 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4648 ); \
4649 lval = (__typeof__(lval)) _res; \
4650 } while (0)
4652 #endif /* PLAT_arm64_linux */
4654 /* ------------------------- s390x-linux ------------------------- */
4656 #if defined(PLAT_s390x_linux)
4658 /* Similar workaround as amd64 (see above), but we use r11 as frame
4659 pointer and save the old r11 in r7. r11 might be used for
4660 argvec, therefore we copy argvec in r1 since r1 is clobbered
4661 after the call anyway. */
4662 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4663 # define __FRAME_POINTER \
4664 ,"d"(__builtin_dwarf_cfa())
4665 # define VALGRIND_CFI_PROLOGUE \
4666 ".cfi_remember_state\n\t" \
4667 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
4668 "lgr 7,11\n\t" \
4669 "lgr 11,%2\n\t" \
4670 ".cfi_def_cfa r11, 0\n\t"
4671 # define VALGRIND_CFI_EPILOGUE \
4672 "lgr 11, 7\n\t" \
4673 ".cfi_restore_state\n\t"
4674 #else
4675 # define __FRAME_POINTER
4676 # define VALGRIND_CFI_PROLOGUE \
4677 "lgr 1,%1\n\t"
4678 # define VALGRIND_CFI_EPILOGUE
4679 #endif
4681 /* Nb: On s390 the stack pointer is properly aligned *at all times*
4682 according to the s390 GCC maintainer. (The ABI specification is not
4683 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4684 VALGRIND_RESTORE_STACK are not defined here. */
4686 /* These regs are trashed by the hidden call. Note that we overwrite
4687 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4688 function a proper return address. All others are ABI defined call
4689 clobbers. */
4690 #define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4691 "f0","f1","f2","f3","f4","f5","f6","f7"
4693 /* Nb: Although r11 is modified in the asm snippets below (inside
4694 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4695 two reasons:
4696 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4697 modified
4698 (2) GCC will complain that r11 cannot appear inside a clobber section,
4699 when compiled with -O -fno-omit-frame-pointer
4702 #define CALL_FN_W_v(lval, orig) \
4703 do { \
4704 volatile OrigFn _orig = (orig); \
4705 volatile unsigned long _argvec[1]; \
4706 volatile unsigned long _res; \
4707 _argvec[0] = (unsigned long)_orig.nraddr; \
4708 __asm__ volatile( \
4709 VALGRIND_CFI_PROLOGUE \
4710 "aghi 15,-160\n\t" \
4711 "lg 1, 0(1)\n\t" /* target->r1 */ \
4712 VALGRIND_CALL_NOREDIR_R1 \
4713 "lgr %0, 2\n\t" \
4714 "aghi 15,160\n\t" \
4715 VALGRIND_CFI_EPILOGUE \
4716 : /*out*/ "=d" (_res) \
4717 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
4718 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4719 ); \
4720 lval = (__typeof__(lval)) _res; \
4721 } while (0)
4723 /* The call abi has the arguments in r2-r6 and stack */
4724 #define CALL_FN_W_W(lval, orig, arg1) \
4725 do { \
4726 volatile OrigFn _orig = (orig); \
4727 volatile unsigned long _argvec[2]; \
4728 volatile unsigned long _res; \
4729 _argvec[0] = (unsigned long)_orig.nraddr; \
4730 _argvec[1] = (unsigned long)arg1; \
4731 __asm__ volatile( \
4732 VALGRIND_CFI_PROLOGUE \
4733 "aghi 15,-160\n\t" \
4734 "lg 2, 8(1)\n\t" \
4735 "lg 1, 0(1)\n\t" \
4736 VALGRIND_CALL_NOREDIR_R1 \
4737 "lgr %0, 2\n\t" \
4738 "aghi 15,160\n\t" \
4739 VALGRIND_CFI_EPILOGUE \
4740 : /*out*/ "=d" (_res) \
4741 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4742 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4743 ); \
4744 lval = (__typeof__(lval)) _res; \
4745 } while (0)
4747 #define CALL_FN_W_WW(lval, orig, arg1, arg2) \
4748 do { \
4749 volatile OrigFn _orig = (orig); \
4750 volatile unsigned long _argvec[3]; \
4751 volatile unsigned long _res; \
4752 _argvec[0] = (unsigned long)_orig.nraddr; \
4753 _argvec[1] = (unsigned long)arg1; \
4754 _argvec[2] = (unsigned long)arg2; \
4755 __asm__ volatile( \
4756 VALGRIND_CFI_PROLOGUE \
4757 "aghi 15,-160\n\t" \
4758 "lg 2, 8(1)\n\t" \
4759 "lg 3,16(1)\n\t" \
4760 "lg 1, 0(1)\n\t" \
4761 VALGRIND_CALL_NOREDIR_R1 \
4762 "lgr %0, 2\n\t" \
4763 "aghi 15,160\n\t" \
4764 VALGRIND_CFI_EPILOGUE \
4765 : /*out*/ "=d" (_res) \
4766 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4767 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4768 ); \
4769 lval = (__typeof__(lval)) _res; \
4770 } while (0)
4772 #define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
4773 do { \
4774 volatile OrigFn _orig = (orig); \
4775 volatile unsigned long _argvec[4]; \
4776 volatile unsigned long _res; \
4777 _argvec[0] = (unsigned long)_orig.nraddr; \
4778 _argvec[1] = (unsigned long)arg1; \
4779 _argvec[2] = (unsigned long)arg2; \
4780 _argvec[3] = (unsigned long)arg3; \
4781 __asm__ volatile( \
4782 VALGRIND_CFI_PROLOGUE \
4783 "aghi 15,-160\n\t" \
4784 "lg 2, 8(1)\n\t" \
4785 "lg 3,16(1)\n\t" \
4786 "lg 4,24(1)\n\t" \
4787 "lg 1, 0(1)\n\t" \
4788 VALGRIND_CALL_NOREDIR_R1 \
4789 "lgr %0, 2\n\t" \
4790 "aghi 15,160\n\t" \
4791 VALGRIND_CFI_EPILOGUE \
4792 : /*out*/ "=d" (_res) \
4793 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4794 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4795 ); \
4796 lval = (__typeof__(lval)) _res; \
4797 } while (0)
4799 #define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
4800 do { \
4801 volatile OrigFn _orig = (orig); \
4802 volatile unsigned long _argvec[5]; \
4803 volatile unsigned long _res; \
4804 _argvec[0] = (unsigned long)_orig.nraddr; \
4805 _argvec[1] = (unsigned long)arg1; \
4806 _argvec[2] = (unsigned long)arg2; \
4807 _argvec[3] = (unsigned long)arg3; \
4808 _argvec[4] = (unsigned long)arg4; \
4809 __asm__ volatile( \
4810 VALGRIND_CFI_PROLOGUE \
4811 "aghi 15,-160\n\t" \
4812 "lg 2, 8(1)\n\t" \
4813 "lg 3,16(1)\n\t" \
4814 "lg 4,24(1)\n\t" \
4815 "lg 5,32(1)\n\t" \
4816 "lg 1, 0(1)\n\t" \
4817 VALGRIND_CALL_NOREDIR_R1 \
4818 "lgr %0, 2\n\t" \
4819 "aghi 15,160\n\t" \
4820 VALGRIND_CFI_EPILOGUE \
4821 : /*out*/ "=d" (_res) \
4822 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4823 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4824 ); \
4825 lval = (__typeof__(lval)) _res; \
4826 } while (0)
4828 #define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
4829 do { \
4830 volatile OrigFn _orig = (orig); \
4831 volatile unsigned long _argvec[6]; \
4832 volatile unsigned long _res; \
4833 _argvec[0] = (unsigned long)_orig.nraddr; \
4834 _argvec[1] = (unsigned long)arg1; \
4835 _argvec[2] = (unsigned long)arg2; \
4836 _argvec[3] = (unsigned long)arg3; \
4837 _argvec[4] = (unsigned long)arg4; \
4838 _argvec[5] = (unsigned long)arg5; \
4839 __asm__ volatile( \
4840 VALGRIND_CFI_PROLOGUE \
4841 "aghi 15,-160\n\t" \
4842 "lg 2, 8(1)\n\t" \
4843 "lg 3,16(1)\n\t" \
4844 "lg 4,24(1)\n\t" \
4845 "lg 5,32(1)\n\t" \
4846 "lg 6,40(1)\n\t" \
4847 "lg 1, 0(1)\n\t" \
4848 VALGRIND_CALL_NOREDIR_R1 \
4849 "lgr %0, 2\n\t" \
4850 "aghi 15,160\n\t" \
4851 VALGRIND_CFI_EPILOGUE \
4852 : /*out*/ "=d" (_res) \
4853 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4854 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4855 ); \
4856 lval = (__typeof__(lval)) _res; \
4857 } while (0)
4859 #define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4860 arg6) \
4861 do { \
4862 volatile OrigFn _orig = (orig); \
4863 volatile unsigned long _argvec[7]; \
4864 volatile unsigned long _res; \
4865 _argvec[0] = (unsigned long)_orig.nraddr; \
4866 _argvec[1] = (unsigned long)arg1; \
4867 _argvec[2] = (unsigned long)arg2; \
4868 _argvec[3] = (unsigned long)arg3; \
4869 _argvec[4] = (unsigned long)arg4; \
4870 _argvec[5] = (unsigned long)arg5; \
4871 _argvec[6] = (unsigned long)arg6; \
4872 __asm__ volatile( \
4873 VALGRIND_CFI_PROLOGUE \
4874 "aghi 15,-168\n\t" \
4875 "lg 2, 8(1)\n\t" \
4876 "lg 3,16(1)\n\t" \
4877 "lg 4,24(1)\n\t" \
4878 "lg 5,32(1)\n\t" \
4879 "lg 6,40(1)\n\t" \
4880 "mvc 160(8,15), 48(1)\n\t" \
4881 "lg 1, 0(1)\n\t" \
4882 VALGRIND_CALL_NOREDIR_R1 \
4883 "lgr %0, 2\n\t" \
4884 "aghi 15,168\n\t" \
4885 VALGRIND_CFI_EPILOGUE \
4886 : /*out*/ "=d" (_res) \
4887 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4888 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4889 ); \
4890 lval = (__typeof__(lval)) _res; \
4891 } while (0)
4893 #define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4894 arg6, arg7) \
4895 do { \
4896 volatile OrigFn _orig = (orig); \
4897 volatile unsigned long _argvec[8]; \
4898 volatile unsigned long _res; \
4899 _argvec[0] = (unsigned long)_orig.nraddr; \
4900 _argvec[1] = (unsigned long)arg1; \
4901 _argvec[2] = (unsigned long)arg2; \
4902 _argvec[3] = (unsigned long)arg3; \
4903 _argvec[4] = (unsigned long)arg4; \
4904 _argvec[5] = (unsigned long)arg5; \
4905 _argvec[6] = (unsigned long)arg6; \
4906 _argvec[7] = (unsigned long)arg7; \
4907 __asm__ volatile( \
4908 VALGRIND_CFI_PROLOGUE \
4909 "aghi 15,-176\n\t" \
4910 "lg 2, 8(1)\n\t" \
4911 "lg 3,16(1)\n\t" \
4912 "lg 4,24(1)\n\t" \
4913 "lg 5,32(1)\n\t" \
4914 "lg 6,40(1)\n\t" \
4915 "mvc 160(8,15), 48(1)\n\t" \
4916 "mvc 168(8,15), 56(1)\n\t" \
4917 "lg 1, 0(1)\n\t" \
4918 VALGRIND_CALL_NOREDIR_R1 \
4919 "lgr %0, 2\n\t" \
4920 "aghi 15,176\n\t" \
4921 VALGRIND_CFI_EPILOGUE \
4922 : /*out*/ "=d" (_res) \
4923 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4924 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4925 ); \
4926 lval = (__typeof__(lval)) _res; \
4927 } while (0)
4929 #define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4930 arg6, arg7 ,arg8) \
4931 do { \
4932 volatile OrigFn _orig = (orig); \
4933 volatile unsigned long _argvec[9]; \
4934 volatile unsigned long _res; \
4935 _argvec[0] = (unsigned long)_orig.nraddr; \
4936 _argvec[1] = (unsigned long)arg1; \
4937 _argvec[2] = (unsigned long)arg2; \
4938 _argvec[3] = (unsigned long)arg3; \
4939 _argvec[4] = (unsigned long)arg4; \
4940 _argvec[5] = (unsigned long)arg5; \
4941 _argvec[6] = (unsigned long)arg6; \
4942 _argvec[7] = (unsigned long)arg7; \
4943 _argvec[8] = (unsigned long)arg8; \
4944 __asm__ volatile( \
4945 VALGRIND_CFI_PROLOGUE \
4946 "aghi 15,-184\n\t" \
4947 "lg 2, 8(1)\n\t" \
4948 "lg 3,16(1)\n\t" \
4949 "lg 4,24(1)\n\t" \
4950 "lg 5,32(1)\n\t" \
4951 "lg 6,40(1)\n\t" \
4952 "mvc 160(8,15), 48(1)\n\t" \
4953 "mvc 168(8,15), 56(1)\n\t" \
4954 "mvc 176(8,15), 64(1)\n\t" \
4955 "lg 1, 0(1)\n\t" \
4956 VALGRIND_CALL_NOREDIR_R1 \
4957 "lgr %0, 2\n\t" \
4958 "aghi 15,184\n\t" \
4959 VALGRIND_CFI_EPILOGUE \
4960 : /*out*/ "=d" (_res) \
4961 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4962 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4963 ); \
4964 lval = (__typeof__(lval)) _res; \
4965 } while (0)
4967 #define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4968 arg6, arg7 ,arg8, arg9) \
4969 do { \
4970 volatile OrigFn _orig = (orig); \
4971 volatile unsigned long _argvec[10]; \
4972 volatile unsigned long _res; \
4973 _argvec[0] = (unsigned long)_orig.nraddr; \
4974 _argvec[1] = (unsigned long)arg1; \
4975 _argvec[2] = (unsigned long)arg2; \
4976 _argvec[3] = (unsigned long)arg3; \
4977 _argvec[4] = (unsigned long)arg4; \
4978 _argvec[5] = (unsigned long)arg5; \
4979 _argvec[6] = (unsigned long)arg6; \
4980 _argvec[7] = (unsigned long)arg7; \
4981 _argvec[8] = (unsigned long)arg8; \
4982 _argvec[9] = (unsigned long)arg9; \
4983 __asm__ volatile( \
4984 VALGRIND_CFI_PROLOGUE \
4985 "aghi 15,-192\n\t" \
4986 "lg 2, 8(1)\n\t" \
4987 "lg 3,16(1)\n\t" \
4988 "lg 4,24(1)\n\t" \
4989 "lg 5,32(1)\n\t" \
4990 "lg 6,40(1)\n\t" \
4991 "mvc 160(8,15), 48(1)\n\t" \
4992 "mvc 168(8,15), 56(1)\n\t" \
4993 "mvc 176(8,15), 64(1)\n\t" \
4994 "mvc 184(8,15), 72(1)\n\t" \
4995 "lg 1, 0(1)\n\t" \
4996 VALGRIND_CALL_NOREDIR_R1 \
4997 "lgr %0, 2\n\t" \
4998 "aghi 15,192\n\t" \
4999 VALGRIND_CFI_EPILOGUE \
5000 : /*out*/ "=d" (_res) \
5001 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5002 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5003 ); \
5004 lval = (__typeof__(lval)) _res; \
5005 } while (0)
5007 #define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5008 arg6, arg7 ,arg8, arg9, arg10) \
5009 do { \
5010 volatile OrigFn _orig = (orig); \
5011 volatile unsigned long _argvec[11]; \
5012 volatile unsigned long _res; \
5013 _argvec[0] = (unsigned long)_orig.nraddr; \
5014 _argvec[1] = (unsigned long)arg1; \
5015 _argvec[2] = (unsigned long)arg2; \
5016 _argvec[3] = (unsigned long)arg3; \
5017 _argvec[4] = (unsigned long)arg4; \
5018 _argvec[5] = (unsigned long)arg5; \
5019 _argvec[6] = (unsigned long)arg6; \
5020 _argvec[7] = (unsigned long)arg7; \
5021 _argvec[8] = (unsigned long)arg8; \
5022 _argvec[9] = (unsigned long)arg9; \
5023 _argvec[10] = (unsigned long)arg10; \
5024 __asm__ volatile( \
5025 VALGRIND_CFI_PROLOGUE \
5026 "aghi 15,-200\n\t" \
5027 "lg 2, 8(1)\n\t" \
5028 "lg 3,16(1)\n\t" \
5029 "lg 4,24(1)\n\t" \
5030 "lg 5,32(1)\n\t" \
5031 "lg 6,40(1)\n\t" \
5032 "mvc 160(8,15), 48(1)\n\t" \
5033 "mvc 168(8,15), 56(1)\n\t" \
5034 "mvc 176(8,15), 64(1)\n\t" \
5035 "mvc 184(8,15), 72(1)\n\t" \
5036 "mvc 192(8,15), 80(1)\n\t" \
5037 "lg 1, 0(1)\n\t" \
5038 VALGRIND_CALL_NOREDIR_R1 \
5039 "lgr %0, 2\n\t" \
5040 "aghi 15,200\n\t" \
5041 VALGRIND_CFI_EPILOGUE \
5042 : /*out*/ "=d" (_res) \
5043 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5044 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5045 ); \
5046 lval = (__typeof__(lval)) _res; \
5047 } while (0)
5049 #define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5050 arg6, arg7 ,arg8, arg9, arg10, arg11) \
5051 do { \
5052 volatile OrigFn _orig = (orig); \
5053 volatile unsigned long _argvec[12]; \
5054 volatile unsigned long _res; \
5055 _argvec[0] = (unsigned long)_orig.nraddr; \
5056 _argvec[1] = (unsigned long)arg1; \
5057 _argvec[2] = (unsigned long)arg2; \
5058 _argvec[3] = (unsigned long)arg3; \
5059 _argvec[4] = (unsigned long)arg4; \
5060 _argvec[5] = (unsigned long)arg5; \
5061 _argvec[6] = (unsigned long)arg6; \
5062 _argvec[7] = (unsigned long)arg7; \
5063 _argvec[8] = (unsigned long)arg8; \
5064 _argvec[9] = (unsigned long)arg9; \
5065 _argvec[10] = (unsigned long)arg10; \
5066 _argvec[11] = (unsigned long)arg11; \
5067 __asm__ volatile( \
5068 VALGRIND_CFI_PROLOGUE \
5069 "aghi 15,-208\n\t" \
5070 "lg 2, 8(1)\n\t" \
5071 "lg 3,16(1)\n\t" \
5072 "lg 4,24(1)\n\t" \
5073 "lg 5,32(1)\n\t" \
5074 "lg 6,40(1)\n\t" \
5075 "mvc 160(8,15), 48(1)\n\t" \
5076 "mvc 168(8,15), 56(1)\n\t" \
5077 "mvc 176(8,15), 64(1)\n\t" \
5078 "mvc 184(8,15), 72(1)\n\t" \
5079 "mvc 192(8,15), 80(1)\n\t" \
5080 "mvc 200(8,15), 88(1)\n\t" \
5081 "lg 1, 0(1)\n\t" \
5082 VALGRIND_CALL_NOREDIR_R1 \
5083 "lgr %0, 2\n\t" \
5084 "aghi 15,208\n\t" \
5085 VALGRIND_CFI_EPILOGUE \
5086 : /*out*/ "=d" (_res) \
5087 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5088 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5089 ); \
5090 lval = (__typeof__(lval)) _res; \
5091 } while (0)
5093 #define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5094 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
5095 do { \
5096 volatile OrigFn _orig = (orig); \
5097 volatile unsigned long _argvec[13]; \
5098 volatile unsigned long _res; \
5099 _argvec[0] = (unsigned long)_orig.nraddr; \
5100 _argvec[1] = (unsigned long)arg1; \
5101 _argvec[2] = (unsigned long)arg2; \
5102 _argvec[3] = (unsigned long)arg3; \
5103 _argvec[4] = (unsigned long)arg4; \
5104 _argvec[5] = (unsigned long)arg5; \
5105 _argvec[6] = (unsigned long)arg6; \
5106 _argvec[7] = (unsigned long)arg7; \
5107 _argvec[8] = (unsigned long)arg8; \
5108 _argvec[9] = (unsigned long)arg9; \
5109 _argvec[10] = (unsigned long)arg10; \
5110 _argvec[11] = (unsigned long)arg11; \
5111 _argvec[12] = (unsigned long)arg12; \
5112 __asm__ volatile( \
5113 VALGRIND_CFI_PROLOGUE \
5114 "aghi 15,-216\n\t" \
5115 "lg 2, 8(1)\n\t" \
5116 "lg 3,16(1)\n\t" \
5117 "lg 4,24(1)\n\t" \
5118 "lg 5,32(1)\n\t" \
5119 "lg 6,40(1)\n\t" \
5120 "mvc 160(8,15), 48(1)\n\t" \
5121 "mvc 168(8,15), 56(1)\n\t" \
5122 "mvc 176(8,15), 64(1)\n\t" \
5123 "mvc 184(8,15), 72(1)\n\t" \
5124 "mvc 192(8,15), 80(1)\n\t" \
5125 "mvc 200(8,15), 88(1)\n\t" \
5126 "mvc 208(8,15), 96(1)\n\t" \
5127 "lg 1, 0(1)\n\t" \
5128 VALGRIND_CALL_NOREDIR_R1 \
5129 "lgr %0, 2\n\t" \
5130 "aghi 15,216\n\t" \
5131 VALGRIND_CFI_EPILOGUE \
5132 : /*out*/ "=d" (_res) \
5133 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5134 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5135 ); \
5136 lval = (__typeof__(lval)) _res; \
5137 } while (0)
5140 #endif /* PLAT_s390x_linux */
5142 /* ------------------------- mips32-linux ----------------------- */
5144 #if defined(PLAT_mips32_linux)
5146 /* These regs are trashed by the hidden call. */
5147 #define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5148 "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5149 "$25", "$31"
5151 /* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5152 long) == 4. */
5154 #define CALL_FN_W_v(lval, orig) \
5155 do { \
5156 volatile OrigFn _orig = (orig); \
5157 volatile unsigned long _argvec[1]; \
5158 volatile unsigned long _res; \
5159 _argvec[0] = (unsigned long)_orig.nraddr; \
5160 __asm__ volatile( \
5161 "subu $29, $29, 8 \n\t" \
5162 "sw $28, 0($29) \n\t" \
5163 "sw $31, 4($29) \n\t" \
5164 "subu $29, $29, 16 \n\t" \
5165 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5166 VALGRIND_CALL_NOREDIR_T9 \
5167 "addu $29, $29, 16\n\t" \
5168 "lw $28, 0($29) \n\t" \
5169 "lw $31, 4($29) \n\t" \
5170 "addu $29, $29, 8 \n\t" \
5171 "move %0, $2\n" \
5172 : /*out*/ "=r" (_res) \
5173 : /*in*/ "0" (&_argvec[0]) \
5174 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5175 ); \
5176 lval = (__typeof__(lval)) _res; \
5177 } while (0)
5179 #define CALL_FN_W_W(lval, orig, arg1) \
5180 do { \
5181 volatile OrigFn _orig = (orig); \
5182 volatile unsigned long _argvec[2]; \
5183 volatile unsigned long _res; \
5184 _argvec[0] = (unsigned long)_orig.nraddr; \
5185 _argvec[1] = (unsigned long)(arg1); \
5186 __asm__ volatile( \
5187 "subu $29, $29, 8 \n\t" \
5188 "sw $28, 0($29) \n\t" \
5189 "sw $31, 4($29) \n\t" \
5190 "subu $29, $29, 16 \n\t" \
5191 "lw $4, 4(%1) \n\t" /* arg1*/ \
5192 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5193 VALGRIND_CALL_NOREDIR_T9 \
5194 "addu $29, $29, 16 \n\t" \
5195 "lw $28, 0($29) \n\t" \
5196 "lw $31, 4($29) \n\t" \
5197 "addu $29, $29, 8 \n\t" \
5198 "move %0, $2\n" \
5199 : /*out*/ "=r" (_res) \
5200 : /*in*/ "0" (&_argvec[0]) \
5201 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5202 ); \
5203 lval = (__typeof__(lval)) _res; \
5204 } while (0)
5206 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5207 do { \
5208 volatile OrigFn _orig = (orig); \
5209 volatile unsigned long _argvec[3]; \
5210 volatile unsigned long _res; \
5211 _argvec[0] = (unsigned long)_orig.nraddr; \
5212 _argvec[1] = (unsigned long)(arg1); \
5213 _argvec[2] = (unsigned long)(arg2); \
5214 __asm__ volatile( \
5215 "subu $29, $29, 8 \n\t" \
5216 "sw $28, 0($29) \n\t" \
5217 "sw $31, 4($29) \n\t" \
5218 "subu $29, $29, 16 \n\t" \
5219 "lw $4, 4(%1) \n\t" \
5220 "lw $5, 8(%1) \n\t" \
5221 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5222 VALGRIND_CALL_NOREDIR_T9 \
5223 "addu $29, $29, 16 \n\t" \
5224 "lw $28, 0($29) \n\t" \
5225 "lw $31, 4($29) \n\t" \
5226 "addu $29, $29, 8 \n\t" \
5227 "move %0, $2\n" \
5228 : /*out*/ "=r" (_res) \
5229 : /*in*/ "0" (&_argvec[0]) \
5230 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5231 ); \
5232 lval = (__typeof__(lval)) _res; \
5233 } while (0)
5235 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5236 do { \
5237 volatile OrigFn _orig = (orig); \
5238 volatile unsigned long _argvec[4]; \
5239 volatile unsigned long _res; \
5240 _argvec[0] = (unsigned long)_orig.nraddr; \
5241 _argvec[1] = (unsigned long)(arg1); \
5242 _argvec[2] = (unsigned long)(arg2); \
5243 _argvec[3] = (unsigned long)(arg3); \
5244 __asm__ volatile( \
5245 "subu $29, $29, 8 \n\t" \
5246 "sw $28, 0($29) \n\t" \
5247 "sw $31, 4($29) \n\t" \
5248 "subu $29, $29, 16 \n\t" \
5249 "lw $4, 4(%1) \n\t" \
5250 "lw $5, 8(%1) \n\t" \
5251 "lw $6, 12(%1) \n\t" \
5252 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5253 VALGRIND_CALL_NOREDIR_T9 \
5254 "addu $29, $29, 16 \n\t" \
5255 "lw $28, 0($29) \n\t" \
5256 "lw $31, 4($29) \n\t" \
5257 "addu $29, $29, 8 \n\t" \
5258 "move %0, $2\n" \
5259 : /*out*/ "=r" (_res) \
5260 : /*in*/ "0" (&_argvec[0]) \
5261 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5262 ); \
5263 lval = (__typeof__(lval)) _res; \
5264 } while (0)
5266 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5267 do { \
5268 volatile OrigFn _orig = (orig); \
5269 volatile unsigned long _argvec[5]; \
5270 volatile unsigned long _res; \
5271 _argvec[0] = (unsigned long)_orig.nraddr; \
5272 _argvec[1] = (unsigned long)(arg1); \
5273 _argvec[2] = (unsigned long)(arg2); \
5274 _argvec[3] = (unsigned long)(arg3); \
5275 _argvec[4] = (unsigned long)(arg4); \
5276 __asm__ volatile( \
5277 "subu $29, $29, 8 \n\t" \
5278 "sw $28, 0($29) \n\t" \
5279 "sw $31, 4($29) \n\t" \
5280 "subu $29, $29, 16 \n\t" \
5281 "lw $4, 4(%1) \n\t" \
5282 "lw $5, 8(%1) \n\t" \
5283 "lw $6, 12(%1) \n\t" \
5284 "lw $7, 16(%1) \n\t" \
5285 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5286 VALGRIND_CALL_NOREDIR_T9 \
5287 "addu $29, $29, 16 \n\t" \
5288 "lw $28, 0($29) \n\t" \
5289 "lw $31, 4($29) \n\t" \
5290 "addu $29, $29, 8 \n\t" \
5291 "move %0, $2\n" \
5292 : /*out*/ "=r" (_res) \
5293 : /*in*/ "0" (&_argvec[0]) \
5294 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5295 ); \
5296 lval = (__typeof__(lval)) _res; \
5297 } while (0)
5299 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5300 do { \
5301 volatile OrigFn _orig = (orig); \
5302 volatile unsigned long _argvec[6]; \
5303 volatile unsigned long _res; \
5304 _argvec[0] = (unsigned long)_orig.nraddr; \
5305 _argvec[1] = (unsigned long)(arg1); \
5306 _argvec[2] = (unsigned long)(arg2); \
5307 _argvec[3] = (unsigned long)(arg3); \
5308 _argvec[4] = (unsigned long)(arg4); \
5309 _argvec[5] = (unsigned long)(arg5); \
5310 __asm__ volatile( \
5311 "subu $29, $29, 8 \n\t" \
5312 "sw $28, 0($29) \n\t" \
5313 "sw $31, 4($29) \n\t" \
5314 "lw $4, 20(%1) \n\t" \
5315 "subu $29, $29, 24\n\t" \
5316 "sw $4, 16($29) \n\t" \
5317 "lw $4, 4(%1) \n\t" \
5318 "lw $5, 8(%1) \n\t" \
5319 "lw $6, 12(%1) \n\t" \
5320 "lw $7, 16(%1) \n\t" \
5321 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5322 VALGRIND_CALL_NOREDIR_T9 \
5323 "addu $29, $29, 24 \n\t" \
5324 "lw $28, 0($29) \n\t" \
5325 "lw $31, 4($29) \n\t" \
5326 "addu $29, $29, 8 \n\t" \
5327 "move %0, $2\n" \
5328 : /*out*/ "=r" (_res) \
5329 : /*in*/ "0" (&_argvec[0]) \
5330 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5331 ); \
5332 lval = (__typeof__(lval)) _res; \
5333 } while (0)
5334 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5335 do { \
5336 volatile OrigFn _orig = (orig); \
5337 volatile unsigned long _argvec[7]; \
5338 volatile unsigned long _res; \
5339 _argvec[0] = (unsigned long)_orig.nraddr; \
5340 _argvec[1] = (unsigned long)(arg1); \
5341 _argvec[2] = (unsigned long)(arg2); \
5342 _argvec[3] = (unsigned long)(arg3); \
5343 _argvec[4] = (unsigned long)(arg4); \
5344 _argvec[5] = (unsigned long)(arg5); \
5345 _argvec[6] = (unsigned long)(arg6); \
5346 __asm__ volatile( \
5347 "subu $29, $29, 8 \n\t" \
5348 "sw $28, 0($29) \n\t" \
5349 "sw $31, 4($29) \n\t" \
5350 "lw $4, 20(%1) \n\t" \
5351 "subu $29, $29, 32\n\t" \
5352 "sw $4, 16($29) \n\t" \
5353 "lw $4, 24(%1) \n\t" \
5354 "nop\n\t" \
5355 "sw $4, 20($29) \n\t" \
5356 "lw $4, 4(%1) \n\t" \
5357 "lw $5, 8(%1) \n\t" \
5358 "lw $6, 12(%1) \n\t" \
5359 "lw $7, 16(%1) \n\t" \
5360 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5361 VALGRIND_CALL_NOREDIR_T9 \
5362 "addu $29, $29, 32 \n\t" \
5363 "lw $28, 0($29) \n\t" \
5364 "lw $31, 4($29) \n\t" \
5365 "addu $29, $29, 8 \n\t" \
5366 "move %0, $2\n" \
5367 : /*out*/ "=r" (_res) \
5368 : /*in*/ "0" (&_argvec[0]) \
5369 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5370 ); \
5371 lval = (__typeof__(lval)) _res; \
5372 } while (0)
5374 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5375 arg7) \
5376 do { \
5377 volatile OrigFn _orig = (orig); \
5378 volatile unsigned long _argvec[8]; \
5379 volatile unsigned long _res; \
5380 _argvec[0] = (unsigned long)_orig.nraddr; \
5381 _argvec[1] = (unsigned long)(arg1); \
5382 _argvec[2] = (unsigned long)(arg2); \
5383 _argvec[3] = (unsigned long)(arg3); \
5384 _argvec[4] = (unsigned long)(arg4); \
5385 _argvec[5] = (unsigned long)(arg5); \
5386 _argvec[6] = (unsigned long)(arg6); \
5387 _argvec[7] = (unsigned long)(arg7); \
5388 __asm__ volatile( \
5389 "subu $29, $29, 8 \n\t" \
5390 "sw $28, 0($29) \n\t" \
5391 "sw $31, 4($29) \n\t" \
5392 "lw $4, 20(%1) \n\t" \
5393 "subu $29, $29, 32\n\t" \
5394 "sw $4, 16($29) \n\t" \
5395 "lw $4, 24(%1) \n\t" \
5396 "sw $4, 20($29) \n\t" \
5397 "lw $4, 28(%1) \n\t" \
5398 "sw $4, 24($29) \n\t" \
5399 "lw $4, 4(%1) \n\t" \
5400 "lw $5, 8(%1) \n\t" \
5401 "lw $6, 12(%1) \n\t" \
5402 "lw $7, 16(%1) \n\t" \
5403 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5404 VALGRIND_CALL_NOREDIR_T9 \
5405 "addu $29, $29, 32 \n\t" \
5406 "lw $28, 0($29) \n\t" \
5407 "lw $31, 4($29) \n\t" \
5408 "addu $29, $29, 8 \n\t" \
5409 "move %0, $2\n" \
5410 : /*out*/ "=r" (_res) \
5411 : /*in*/ "0" (&_argvec[0]) \
5412 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5413 ); \
5414 lval = (__typeof__(lval)) _res; \
5415 } while (0)
5417 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5418 arg7,arg8) \
5419 do { \
5420 volatile OrigFn _orig = (orig); \
5421 volatile unsigned long _argvec[9]; \
5422 volatile unsigned long _res; \
5423 _argvec[0] = (unsigned long)_orig.nraddr; \
5424 _argvec[1] = (unsigned long)(arg1); \
5425 _argvec[2] = (unsigned long)(arg2); \
5426 _argvec[3] = (unsigned long)(arg3); \
5427 _argvec[4] = (unsigned long)(arg4); \
5428 _argvec[5] = (unsigned long)(arg5); \
5429 _argvec[6] = (unsigned long)(arg6); \
5430 _argvec[7] = (unsigned long)(arg7); \
5431 _argvec[8] = (unsigned long)(arg8); \
5432 __asm__ volatile( \
5433 "subu $29, $29, 8 \n\t" \
5434 "sw $28, 0($29) \n\t" \
5435 "sw $31, 4($29) \n\t" \
5436 "lw $4, 20(%1) \n\t" \
5437 "subu $29, $29, 40\n\t" \
5438 "sw $4, 16($29) \n\t" \
5439 "lw $4, 24(%1) \n\t" \
5440 "sw $4, 20($29) \n\t" \
5441 "lw $4, 28(%1) \n\t" \
5442 "sw $4, 24($29) \n\t" \
5443 "lw $4, 32(%1) \n\t" \
5444 "sw $4, 28($29) \n\t" \
5445 "lw $4, 4(%1) \n\t" \
5446 "lw $5, 8(%1) \n\t" \
5447 "lw $6, 12(%1) \n\t" \
5448 "lw $7, 16(%1) \n\t" \
5449 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5450 VALGRIND_CALL_NOREDIR_T9 \
5451 "addu $29, $29, 40 \n\t" \
5452 "lw $28, 0($29) \n\t" \
5453 "lw $31, 4($29) \n\t" \
5454 "addu $29, $29, 8 \n\t" \
5455 "move %0, $2\n" \
5456 : /*out*/ "=r" (_res) \
5457 : /*in*/ "0" (&_argvec[0]) \
5458 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5459 ); \
5460 lval = (__typeof__(lval)) _res; \
5461 } while (0)
5463 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5464 arg7,arg8,arg9) \
5465 do { \
5466 volatile OrigFn _orig = (orig); \
5467 volatile unsigned long _argvec[10]; \
5468 volatile unsigned long _res; \
5469 _argvec[0] = (unsigned long)_orig.nraddr; \
5470 _argvec[1] = (unsigned long)(arg1); \
5471 _argvec[2] = (unsigned long)(arg2); \
5472 _argvec[3] = (unsigned long)(arg3); \
5473 _argvec[4] = (unsigned long)(arg4); \
5474 _argvec[5] = (unsigned long)(arg5); \
5475 _argvec[6] = (unsigned long)(arg6); \
5476 _argvec[7] = (unsigned long)(arg7); \
5477 _argvec[8] = (unsigned long)(arg8); \
5478 _argvec[9] = (unsigned long)(arg9); \
5479 __asm__ volatile( \
5480 "subu $29, $29, 8 \n\t" \
5481 "sw $28, 0($29) \n\t" \
5482 "sw $31, 4($29) \n\t" \
5483 "lw $4, 20(%1) \n\t" \
5484 "subu $29, $29, 40\n\t" \
5485 "sw $4, 16($29) \n\t" \
5486 "lw $4, 24(%1) \n\t" \
5487 "sw $4, 20($29) \n\t" \
5488 "lw $4, 28(%1) \n\t" \
5489 "sw $4, 24($29) \n\t" \
5490 "lw $4, 32(%1) \n\t" \
5491 "sw $4, 28($29) \n\t" \
5492 "lw $4, 36(%1) \n\t" \
5493 "sw $4, 32($29) \n\t" \
5494 "lw $4, 4(%1) \n\t" \
5495 "lw $5, 8(%1) \n\t" \
5496 "lw $6, 12(%1) \n\t" \
5497 "lw $7, 16(%1) \n\t" \
5498 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5499 VALGRIND_CALL_NOREDIR_T9 \
5500 "addu $29, $29, 40 \n\t" \
5501 "lw $28, 0($29) \n\t" \
5502 "lw $31, 4($29) \n\t" \
5503 "addu $29, $29, 8 \n\t" \
5504 "move %0, $2\n" \
5505 : /*out*/ "=r" (_res) \
5506 : /*in*/ "0" (&_argvec[0]) \
5507 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5508 ); \
5509 lval = (__typeof__(lval)) _res; \
5510 } while (0)
5512 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5513 arg7,arg8,arg9,arg10) \
5514 do { \
5515 volatile OrigFn _orig = (orig); \
5516 volatile unsigned long _argvec[11]; \
5517 volatile unsigned long _res; \
5518 _argvec[0] = (unsigned long)_orig.nraddr; \
5519 _argvec[1] = (unsigned long)(arg1); \
5520 _argvec[2] = (unsigned long)(arg2); \
5521 _argvec[3] = (unsigned long)(arg3); \
5522 _argvec[4] = (unsigned long)(arg4); \
5523 _argvec[5] = (unsigned long)(arg5); \
5524 _argvec[6] = (unsigned long)(arg6); \
5525 _argvec[7] = (unsigned long)(arg7); \
5526 _argvec[8] = (unsigned long)(arg8); \
5527 _argvec[9] = (unsigned long)(arg9); \
5528 _argvec[10] = (unsigned long)(arg10); \
5529 __asm__ volatile( \
5530 "subu $29, $29, 8 \n\t" \
5531 "sw $28, 0($29) \n\t" \
5532 "sw $31, 4($29) \n\t" \
5533 "lw $4, 20(%1) \n\t" \
5534 "subu $29, $29, 48\n\t" \
5535 "sw $4, 16($29) \n\t" \
5536 "lw $4, 24(%1) \n\t" \
5537 "sw $4, 20($29) \n\t" \
5538 "lw $4, 28(%1) \n\t" \
5539 "sw $4, 24($29) \n\t" \
5540 "lw $4, 32(%1) \n\t" \
5541 "sw $4, 28($29) \n\t" \
5542 "lw $4, 36(%1) \n\t" \
5543 "sw $4, 32($29) \n\t" \
5544 "lw $4, 40(%1) \n\t" \
5545 "sw $4, 36($29) \n\t" \
5546 "lw $4, 4(%1) \n\t" \
5547 "lw $5, 8(%1) \n\t" \
5548 "lw $6, 12(%1) \n\t" \
5549 "lw $7, 16(%1) \n\t" \
5550 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5551 VALGRIND_CALL_NOREDIR_T9 \
5552 "addu $29, $29, 48 \n\t" \
5553 "lw $28, 0($29) \n\t" \
5554 "lw $31, 4($29) \n\t" \
5555 "addu $29, $29, 8 \n\t" \
5556 "move %0, $2\n" \
5557 : /*out*/ "=r" (_res) \
5558 : /*in*/ "0" (&_argvec[0]) \
5559 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5560 ); \
5561 lval = (__typeof__(lval)) _res; \
5562 } while (0)
5564 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5565 arg6,arg7,arg8,arg9,arg10, \
5566 arg11) \
5567 do { \
5568 volatile OrigFn _orig = (orig); \
5569 volatile unsigned long _argvec[12]; \
5570 volatile unsigned long _res; \
5571 _argvec[0] = (unsigned long)_orig.nraddr; \
5572 _argvec[1] = (unsigned long)(arg1); \
5573 _argvec[2] = (unsigned long)(arg2); \
5574 _argvec[3] = (unsigned long)(arg3); \
5575 _argvec[4] = (unsigned long)(arg4); \
5576 _argvec[5] = (unsigned long)(arg5); \
5577 _argvec[6] = (unsigned long)(arg6); \
5578 _argvec[7] = (unsigned long)(arg7); \
5579 _argvec[8] = (unsigned long)(arg8); \
5580 _argvec[9] = (unsigned long)(arg9); \
5581 _argvec[10] = (unsigned long)(arg10); \
5582 _argvec[11] = (unsigned long)(arg11); \
5583 __asm__ volatile( \
5584 "subu $29, $29, 8 \n\t" \
5585 "sw $28, 0($29) \n\t" \
5586 "sw $31, 4($29) \n\t" \
5587 "lw $4, 20(%1) \n\t" \
5588 "subu $29, $29, 48\n\t" \
5589 "sw $4, 16($29) \n\t" \
5590 "lw $4, 24(%1) \n\t" \
5591 "sw $4, 20($29) \n\t" \
5592 "lw $4, 28(%1) \n\t" \
5593 "sw $4, 24($29) \n\t" \
5594 "lw $4, 32(%1) \n\t" \
5595 "sw $4, 28($29) \n\t" \
5596 "lw $4, 36(%1) \n\t" \
5597 "sw $4, 32($29) \n\t" \
5598 "lw $4, 40(%1) \n\t" \
5599 "sw $4, 36($29) \n\t" \
5600 "lw $4, 44(%1) \n\t" \
5601 "sw $4, 40($29) \n\t" \
5602 "lw $4, 4(%1) \n\t" \
5603 "lw $5, 8(%1) \n\t" \
5604 "lw $6, 12(%1) \n\t" \
5605 "lw $7, 16(%1) \n\t" \
5606 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5607 VALGRIND_CALL_NOREDIR_T9 \
5608 "addu $29, $29, 48 \n\t" \
5609 "lw $28, 0($29) \n\t" \
5610 "lw $31, 4($29) \n\t" \
5611 "addu $29, $29, 8 \n\t" \
5612 "move %0, $2\n" \
5613 : /*out*/ "=r" (_res) \
5614 : /*in*/ "0" (&_argvec[0]) \
5615 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5616 ); \
5617 lval = (__typeof__(lval)) _res; \
5618 } while (0)
5620 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5621 arg6,arg7,arg8,arg9,arg10, \
5622 arg11,arg12) \
5623 do { \
5624 volatile OrigFn _orig = (orig); \
5625 volatile unsigned long _argvec[13]; \
5626 volatile unsigned long _res; \
5627 _argvec[0] = (unsigned long)_orig.nraddr; \
5628 _argvec[1] = (unsigned long)(arg1); \
5629 _argvec[2] = (unsigned long)(arg2); \
5630 _argvec[3] = (unsigned long)(arg3); \
5631 _argvec[4] = (unsigned long)(arg4); \
5632 _argvec[5] = (unsigned long)(arg5); \
5633 _argvec[6] = (unsigned long)(arg6); \
5634 _argvec[7] = (unsigned long)(arg7); \
5635 _argvec[8] = (unsigned long)(arg8); \
5636 _argvec[9] = (unsigned long)(arg9); \
5637 _argvec[10] = (unsigned long)(arg10); \
5638 _argvec[11] = (unsigned long)(arg11); \
5639 _argvec[12] = (unsigned long)(arg12); \
5640 __asm__ volatile( \
5641 "subu $29, $29, 8 \n\t" \
5642 "sw $28, 0($29) \n\t" \
5643 "sw $31, 4($29) \n\t" \
5644 "lw $4, 20(%1) \n\t" \
5645 "subu $29, $29, 56\n\t" \
5646 "sw $4, 16($29) \n\t" \
5647 "lw $4, 24(%1) \n\t" \
5648 "sw $4, 20($29) \n\t" \
5649 "lw $4, 28(%1) \n\t" \
5650 "sw $4, 24($29) \n\t" \
5651 "lw $4, 32(%1) \n\t" \
5652 "sw $4, 28($29) \n\t" \
5653 "lw $4, 36(%1) \n\t" \
5654 "sw $4, 32($29) \n\t" \
5655 "lw $4, 40(%1) \n\t" \
5656 "sw $4, 36($29) \n\t" \
5657 "lw $4, 44(%1) \n\t" \
5658 "sw $4, 40($29) \n\t" \
5659 "lw $4, 48(%1) \n\t" \
5660 "sw $4, 44($29) \n\t" \
5661 "lw $4, 4(%1) \n\t" \
5662 "lw $5, 8(%1) \n\t" \
5663 "lw $6, 12(%1) \n\t" \
5664 "lw $7, 16(%1) \n\t" \
5665 "lw $25, 0(%1) \n\t" /* target->t9 */ \
5666 VALGRIND_CALL_NOREDIR_T9 \
5667 "addu $29, $29, 56 \n\t" \
5668 "lw $28, 0($29) \n\t" \
5669 "lw $31, 4($29) \n\t" \
5670 "addu $29, $29, 8 \n\t" \
5671 "move %0, $2\n" \
5672 : /*out*/ "=r" (_res) \
5673 : /*in*/ "r" (&_argvec[0]) \
5674 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5675 ); \
5676 lval = (__typeof__(lval)) _res; \
5677 } while (0)
5679 #endif /* PLAT_mips32_linux */
5681 /* ------------------------- mips64-linux ------------------------- */
5683 #if defined(PLAT_mips64_linux)
5685 /* These regs are trashed by the hidden call. */
5686 #define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5687 "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5688 "$25", "$31"
5690 /* These CALL_FN_ macros assume that on mips64-linux,
5691 sizeof(long long) == 8. */
5693 #define MIPS64_LONG2REG_CAST(x) ((long long)(long)x)
5695 #define CALL_FN_W_v(lval, orig) \
5696 do { \
5697 volatile OrigFn _orig = (orig); \
5698 volatile unsigned long long _argvec[1]; \
5699 volatile unsigned long long _res; \
5700 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5701 __asm__ volatile( \
5702 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5703 VALGRIND_CALL_NOREDIR_T9 \
5704 "move %0, $2\n" \
5705 : /*out*/ "=r" (_res) \
5706 : /*in*/ "0" (&_argvec[0]) \
5707 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5708 ); \
5709 lval = (__typeof__(lval)) (long)_res; \
5710 } while (0)
5712 #define CALL_FN_W_W(lval, orig, arg1) \
5713 do { \
5714 volatile OrigFn _orig = (orig); \
5715 volatile unsigned long long _argvec[2]; \
5716 volatile unsigned long long _res; \
5717 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5718 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5719 __asm__ volatile( \
5720 "ld $4, 8(%1)\n\t" /* arg1*/ \
5721 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5722 VALGRIND_CALL_NOREDIR_T9 \
5723 "move %0, $2\n" \
5724 : /*out*/ "=r" (_res) \
5725 : /*in*/ "r" (&_argvec[0]) \
5726 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5727 ); \
5728 lval = (__typeof__(lval)) (long)_res; \
5729 } while (0)
5731 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5732 do { \
5733 volatile OrigFn _orig = (orig); \
5734 volatile unsigned long long _argvec[3]; \
5735 volatile unsigned long long _res; \
5736 _argvec[0] = _orig.nraddr; \
5737 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5738 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5739 __asm__ volatile( \
5740 "ld $4, 8(%1)\n\t" \
5741 "ld $5, 16(%1)\n\t" \
5742 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5743 VALGRIND_CALL_NOREDIR_T9 \
5744 "move %0, $2\n" \
5745 : /*out*/ "=r" (_res) \
5746 : /*in*/ "r" (&_argvec[0]) \
5747 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5748 ); \
5749 lval = (__typeof__(lval)) (long)_res; \
5750 } while (0)
5753 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5754 do { \
5755 volatile OrigFn _orig = (orig); \
5756 volatile unsigned long long _argvec[4]; \
5757 volatile unsigned long long _res; \
5758 _argvec[0] = _orig.nraddr; \
5759 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5760 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5761 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5762 __asm__ volatile( \
5763 "ld $4, 8(%1)\n\t" \
5764 "ld $5, 16(%1)\n\t" \
5765 "ld $6, 24(%1)\n\t" \
5766 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5767 VALGRIND_CALL_NOREDIR_T9 \
5768 "move %0, $2\n" \
5769 : /*out*/ "=r" (_res) \
5770 : /*in*/ "r" (&_argvec[0]) \
5771 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5772 ); \
5773 lval = (__typeof__(lval)) (long)_res; \
5774 } while (0)
5776 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5777 do { \
5778 volatile OrigFn _orig = (orig); \
5779 volatile unsigned long long _argvec[5]; \
5780 volatile unsigned long long _res; \
5781 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5782 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5783 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5784 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5785 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
5786 __asm__ volatile( \
5787 "ld $4, 8(%1)\n\t" \
5788 "ld $5, 16(%1)\n\t" \
5789 "ld $6, 24(%1)\n\t" \
5790 "ld $7, 32(%1)\n\t" \
5791 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5792 VALGRIND_CALL_NOREDIR_T9 \
5793 "move %0, $2\n" \
5794 : /*out*/ "=r" (_res) \
5795 : /*in*/ "r" (&_argvec[0]) \
5796 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5797 ); \
5798 lval = (__typeof__(lval)) (long)_res; \
5799 } while (0)
5801 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5802 do { \
5803 volatile OrigFn _orig = (orig); \
5804 volatile unsigned long long _argvec[6]; \
5805 volatile unsigned long long _res; \
5806 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5807 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5808 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5809 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5810 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
5811 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
5812 __asm__ volatile( \
5813 "ld $4, 8(%1)\n\t" \
5814 "ld $5, 16(%1)\n\t" \
5815 "ld $6, 24(%1)\n\t" \
5816 "ld $7, 32(%1)\n\t" \
5817 "ld $8, 40(%1)\n\t" \
5818 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5819 VALGRIND_CALL_NOREDIR_T9 \
5820 "move %0, $2\n" \
5821 : /*out*/ "=r" (_res) \
5822 : /*in*/ "r" (&_argvec[0]) \
5823 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5824 ); \
5825 lval = (__typeof__(lval)) (long)_res; \
5826 } while (0)
5828 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5829 do { \
5830 volatile OrigFn _orig = (orig); \
5831 volatile unsigned long long _argvec[7]; \
5832 volatile unsigned long long _res; \
5833 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5834 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5835 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5836 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5837 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
5838 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
5839 _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
5840 __asm__ volatile( \
5841 "ld $4, 8(%1)\n\t" \
5842 "ld $5, 16(%1)\n\t" \
5843 "ld $6, 24(%1)\n\t" \
5844 "ld $7, 32(%1)\n\t" \
5845 "ld $8, 40(%1)\n\t" \
5846 "ld $9, 48(%1)\n\t" \
5847 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5848 VALGRIND_CALL_NOREDIR_T9 \
5849 "move %0, $2\n" \
5850 : /*out*/ "=r" (_res) \
5851 : /*in*/ "r" (&_argvec[0]) \
5852 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5853 ); \
5854 lval = (__typeof__(lval)) (long)_res; \
5855 } while (0)
5857 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5858 arg7) \
5859 do { \
5860 volatile OrigFn _orig = (orig); \
5861 volatile unsigned long long _argvec[8]; \
5862 volatile unsigned long long _res; \
5863 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5864 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5865 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5866 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5867 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
5868 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
5869 _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
5870 _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
5871 __asm__ volatile( \
5872 "ld $4, 8(%1)\n\t" \
5873 "ld $5, 16(%1)\n\t" \
5874 "ld $6, 24(%1)\n\t" \
5875 "ld $7, 32(%1)\n\t" \
5876 "ld $8, 40(%1)\n\t" \
5877 "ld $9, 48(%1)\n\t" \
5878 "ld $10, 56(%1)\n\t" \
5879 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5880 VALGRIND_CALL_NOREDIR_T9 \
5881 "move %0, $2\n" \
5882 : /*out*/ "=r" (_res) \
5883 : /*in*/ "r" (&_argvec[0]) \
5884 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5885 ); \
5886 lval = (__typeof__(lval)) (long)_res; \
5887 } while (0)
5889 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5890 arg7,arg8) \
5891 do { \
5892 volatile OrigFn _orig = (orig); \
5893 volatile unsigned long long _argvec[9]; \
5894 volatile unsigned long long _res; \
5895 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5896 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5897 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5898 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5899 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
5900 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
5901 _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
5902 _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
5903 _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
5904 __asm__ volatile( \
5905 "ld $4, 8(%1)\n\t" \
5906 "ld $5, 16(%1)\n\t" \
5907 "ld $6, 24(%1)\n\t" \
5908 "ld $7, 32(%1)\n\t" \
5909 "ld $8, 40(%1)\n\t" \
5910 "ld $9, 48(%1)\n\t" \
5911 "ld $10, 56(%1)\n\t" \
5912 "ld $11, 64(%1)\n\t" \
5913 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5914 VALGRIND_CALL_NOREDIR_T9 \
5915 "move %0, $2\n" \
5916 : /*out*/ "=r" (_res) \
5917 : /*in*/ "r" (&_argvec[0]) \
5918 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5919 ); \
5920 lval = (__typeof__(lval)) (long)_res; \
5921 } while (0)
5923 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5924 arg7,arg8,arg9) \
5925 do { \
5926 volatile OrigFn _orig = (orig); \
5927 volatile unsigned long long _argvec[10]; \
5928 volatile unsigned long long _res; \
5929 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5930 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5931 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5932 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5933 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
5934 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
5935 _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
5936 _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
5937 _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
5938 _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
5939 __asm__ volatile( \
5940 "dsubu $29, $29, 8\n\t" \
5941 "ld $4, 72(%1)\n\t" \
5942 "sd $4, 0($29)\n\t" \
5943 "ld $4, 8(%1)\n\t" \
5944 "ld $5, 16(%1)\n\t" \
5945 "ld $6, 24(%1)\n\t" \
5946 "ld $7, 32(%1)\n\t" \
5947 "ld $8, 40(%1)\n\t" \
5948 "ld $9, 48(%1)\n\t" \
5949 "ld $10, 56(%1)\n\t" \
5950 "ld $11, 64(%1)\n\t" \
5951 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5952 VALGRIND_CALL_NOREDIR_T9 \
5953 "daddu $29, $29, 8\n\t" \
5954 "move %0, $2\n" \
5955 : /*out*/ "=r" (_res) \
5956 : /*in*/ "r" (&_argvec[0]) \
5957 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5958 ); \
5959 lval = (__typeof__(lval)) (long)_res; \
5960 } while (0)
5962 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5963 arg7,arg8,arg9,arg10) \
5964 do { \
5965 volatile OrigFn _orig = (orig); \
5966 volatile unsigned long long _argvec[11]; \
5967 volatile unsigned long long _res; \
5968 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
5969 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
5970 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
5971 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
5972 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
5973 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
5974 _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
5975 _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
5976 _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
5977 _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
5978 _argvec[10] = MIPS64_LONG2REG_CAST(arg10); \
5979 __asm__ volatile( \
5980 "dsubu $29, $29, 16\n\t" \
5981 "ld $4, 72(%1)\n\t" \
5982 "sd $4, 0($29)\n\t" \
5983 "ld $4, 80(%1)\n\t" \
5984 "sd $4, 8($29)\n\t" \
5985 "ld $4, 8(%1)\n\t" \
5986 "ld $5, 16(%1)\n\t" \
5987 "ld $6, 24(%1)\n\t" \
5988 "ld $7, 32(%1)\n\t" \
5989 "ld $8, 40(%1)\n\t" \
5990 "ld $9, 48(%1)\n\t" \
5991 "ld $10, 56(%1)\n\t" \
5992 "ld $11, 64(%1)\n\t" \
5993 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5994 VALGRIND_CALL_NOREDIR_T9 \
5995 "daddu $29, $29, 16\n\t" \
5996 "move %0, $2\n" \
5997 : /*out*/ "=r" (_res) \
5998 : /*in*/ "r" (&_argvec[0]) \
5999 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6000 ); \
6001 lval = (__typeof__(lval)) (long)_res; \
6002 } while (0)
6004 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
6005 arg6,arg7,arg8,arg9,arg10, \
6006 arg11) \
6007 do { \
6008 volatile OrigFn _orig = (orig); \
6009 volatile unsigned long long _argvec[12]; \
6010 volatile unsigned long long _res; \
6011 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
6012 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
6013 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
6014 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
6015 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
6016 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
6017 _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
6018 _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
6019 _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
6020 _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
6021 _argvec[10] = MIPS64_LONG2REG_CAST(arg10); \
6022 _argvec[11] = MIPS64_LONG2REG_CAST(arg11); \
6023 __asm__ volatile( \
6024 "dsubu $29, $29, 24\n\t" \
6025 "ld $4, 72(%1)\n\t" \
6026 "sd $4, 0($29)\n\t" \
6027 "ld $4, 80(%1)\n\t" \
6028 "sd $4, 8($29)\n\t" \
6029 "ld $4, 88(%1)\n\t" \
6030 "sd $4, 16($29)\n\t" \
6031 "ld $4, 8(%1)\n\t" \
6032 "ld $5, 16(%1)\n\t" \
6033 "ld $6, 24(%1)\n\t" \
6034 "ld $7, 32(%1)\n\t" \
6035 "ld $8, 40(%1)\n\t" \
6036 "ld $9, 48(%1)\n\t" \
6037 "ld $10, 56(%1)\n\t" \
6038 "ld $11, 64(%1)\n\t" \
6039 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6040 VALGRIND_CALL_NOREDIR_T9 \
6041 "daddu $29, $29, 24\n\t" \
6042 "move %0, $2\n" \
6043 : /*out*/ "=r" (_res) \
6044 : /*in*/ "r" (&_argvec[0]) \
6045 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6046 ); \
6047 lval = (__typeof__(lval)) (long)_res; \
6048 } while (0)
6050 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
6051 arg6,arg7,arg8,arg9,arg10, \
6052 arg11,arg12) \
6053 do { \
6054 volatile OrigFn _orig = (orig); \
6055 volatile unsigned long long _argvec[13]; \
6056 volatile unsigned long long _res; \
6057 _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
6058 _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
6059 _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
6060 _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
6061 _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
6062 _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
6063 _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
6064 _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
6065 _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
6066 _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
6067 _argvec[10] = MIPS64_LONG2REG_CAST(arg10); \
6068 _argvec[11] = MIPS64_LONG2REG_CAST(arg11); \
6069 _argvec[12] = MIPS64_LONG2REG_CAST(arg12); \
6070 __asm__ volatile( \
6071 "dsubu $29, $29, 32\n\t" \
6072 "ld $4, 72(%1)\n\t" \
6073 "sd $4, 0($29)\n\t" \
6074 "ld $4, 80(%1)\n\t" \
6075 "sd $4, 8($29)\n\t" \
6076 "ld $4, 88(%1)\n\t" \
6077 "sd $4, 16($29)\n\t" \
6078 "ld $4, 96(%1)\n\t" \
6079 "sd $4, 24($29)\n\t" \
6080 "ld $4, 8(%1)\n\t" \
6081 "ld $5, 16(%1)\n\t" \
6082 "ld $6, 24(%1)\n\t" \
6083 "ld $7, 32(%1)\n\t" \
6084 "ld $8, 40(%1)\n\t" \
6085 "ld $9, 48(%1)\n\t" \
6086 "ld $10, 56(%1)\n\t" \
6087 "ld $11, 64(%1)\n\t" \
6088 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6089 VALGRIND_CALL_NOREDIR_T9 \
6090 "daddu $29, $29, 32\n\t" \
6091 "move %0, $2\n" \
6092 : /*out*/ "=r" (_res) \
6093 : /*in*/ "r" (&_argvec[0]) \
6094 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6095 ); \
6096 lval = (__typeof__(lval)) (long)_res; \
6097 } while (0)
6099 #endif /* PLAT_mips64_linux */
6101 /* ------------------------------------------------------------------ */
6102 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
6103 /* */
6104 /* ------------------------------------------------------------------ */
6106 /* Some request codes. There are many more of these, but most are not
6107 exposed to end-user view. These are the public ones, all of the
6108 form 0x1000 + small_number.
6110 Core ones are in the range 0x00000000--0x0000ffff. The non-public
6111 ones start at 0x2000.
6114 /* These macros are used by tools -- they must be public, but don't
6115 embed them into other programs. */
6116 #define VG_USERREQ_TOOL_BASE(a,b) \
6117 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
6118 #define VG_IS_TOOL_USERREQ(a, b, v) \
6119 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
6121 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
6122 This enum comprises an ABI exported by Valgrind to programs
6123 which use client requests. DO NOT CHANGE THE NUMERIC VALUES OF THESE
6124 ENTRIES, NOR DELETE ANY -- add new ones at the end of the most
6125 relevant group. */
6126 typedef
6127 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
6128 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
6130 /* These allow any function to be called from the simulated
6131 CPU but run on the real CPU. Nb: the first arg passed to
6132 the function is always the ThreadId of the running
6133 thread! So CLIENT_CALL0 actually requires a 1 arg
6134 function, etc. */
6135 VG_USERREQ__CLIENT_CALL0 = 0x1101,
6136 VG_USERREQ__CLIENT_CALL1 = 0x1102,
6137 VG_USERREQ__CLIENT_CALL2 = 0x1103,
6138 VG_USERREQ__CLIENT_CALL3 = 0x1104,
6140 /* Can be useful in regression testing suites -- eg. can
6141 send Valgrind's output to /dev/null and still count
6142 errors. */
6143 VG_USERREQ__COUNT_ERRORS = 0x1201,
6145 /* Allows the client program and/or gdbserver to execute a monitor
6146 command. */
6147 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
6149 /* These are useful and can be interpreted by any tool that
6150 tracks malloc() et al, by using vg_replace_malloc.c. */
6151 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
6152 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
6153 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
6154 /* Memory pool support. */
6155 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
6156 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
6157 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
6158 VG_USERREQ__MEMPOOL_FREE = 0x1306,
6159 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
6160 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
6161 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
6162 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
6164 /* Allow printfs to valgrind log. */
6165 /* The first two pass the va_list argument by value, which
6166 assumes it is the same size as or smaller than a UWord,
6167 which generally isn't the case. Hence are deprecated.
6168 The second two pass the vargs by reference and so are
6169 immune to this problem. */
6170 /* both :: char* fmt, va_list vargs (DEPRECATED) */
6171 VG_USERREQ__PRINTF = 0x1401,
6172 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
6173 /* both :: char* fmt, va_list* vargs */
6174 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
6175 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
6177 /* Stack support. */
6178 VG_USERREQ__STACK_REGISTER = 0x1501,
6179 VG_USERREQ__STACK_DEREGISTER = 0x1502,
6180 VG_USERREQ__STACK_CHANGE = 0x1503,
6182 /* Wine support */
6183 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
6185 /* Querying of debug info. */
6186 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
6188 /* Disable/enable error reporting level. Takes a single
6189 Word arg which is the delta to this thread's error
6190 disablement indicator. Hence 1 disables or further
6191 disables errors, and -1 moves back towards enablement.
6192 Other values are not allowed. */
6193 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
6195 /* Some requests used for Valgrind internal, such as
6196 self-test or self-hosting. */
6197 /* Initialise IR injection */
6198 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901,
6199 /* Used by Inner Valgrind to inform Outer Valgrind where to
6200 find the list of inner guest threads */
6201 VG_USERREQ__INNER_THREADS = 0x1902
6202 } Vg_ClientRequest;
6204 #if !defined(__GNUC__)
6205 # define __extension__ /* */
6206 #endif
6209 /* Returns the number of Valgrinds this code is running under. That
6210 is, 0 if running natively, 1 if running under Valgrind, 2 if
6211 running under Valgrind which is running under another Valgrind,
6212 etc. */
6213 #define RUNNING_ON_VALGRIND \
6214 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
6215 VG_USERREQ__RUNNING_ON_VALGRIND, \
6216 0, 0, 0, 0, 0) \
6219 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
6220 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
6221 since it provides a way to make sure valgrind will retranslate the
6222 invalidated area. Returns no value. */
6223 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
6224 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
6225 _qzz_addr, _qzz_len, 0, 0, 0)
6227 #define VALGRIND_INNER_THREADS(_qzz_addr) \
6228 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__INNER_THREADS, \
6229 _qzz_addr, 0, 0, 0, 0)
6232 /* These requests are for getting Valgrind itself to print something.
6233 Possibly with a backtrace. This is a really ugly hack. The return value
6234 is the number of characters printed, excluding the "**<pid>** " part at the
6235 start and the backtrace (if present). */
6237 #if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6238 /* Modern GCC will optimize the static routine out if unused,
6239 and unused attribute will shut down warnings about it. */
6240 static int VALGRIND_PRINTF(const char *format, ...)
6241 __attribute__((format(__printf__, 1, 2), __unused__));
6242 #endif
6243 static int
6244 #if defined(_MSC_VER)
6245 __inline
6246 #endif
6247 VALGRIND_PRINTF(const char *format, ...)
6249 #if defined(NVALGRIND)
6250 (void)format;
6251 return 0;
6252 #else /* NVALGRIND */
6253 #if defined(_MSC_VER) || defined(__MINGW64__)
6254 uintptr_t _qzz_res;
6255 #else
6256 unsigned long _qzz_res;
6257 #endif
6258 va_list vargs;
6259 va_start(vargs, format);
6260 #if defined(_MSC_VER) || defined(__MINGW64__)
6261 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6262 VG_USERREQ__PRINTF_VALIST_BY_REF,
6263 (uintptr_t)format,
6264 (uintptr_t)&vargs,
6265 0, 0, 0);
6266 #else
6267 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6268 VG_USERREQ__PRINTF_VALIST_BY_REF,
6269 (unsigned long)format,
6270 (unsigned long)&vargs,
6271 0, 0, 0);
6272 #endif
6273 va_end(vargs);
6274 return (int)_qzz_res;
6275 #endif /* NVALGRIND */
6278 #if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6279 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6280 __attribute__((format(__printf__, 1, 2), __unused__));
6281 #endif
6282 static int
6283 #if defined(_MSC_VER)
6284 __inline
6285 #endif
6286 VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6288 #if defined(NVALGRIND)
6289 (void)format;
6290 return 0;
6291 #else /* NVALGRIND */
6292 #if defined(_MSC_VER) || defined(__MINGW64__)
6293 uintptr_t _qzz_res;
6294 #else
6295 unsigned long _qzz_res;
6296 #endif
6297 va_list vargs;
6298 va_start(vargs, format);
6299 #if defined(_MSC_VER) || defined(__MINGW64__)
6300 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6301 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6302 (uintptr_t)format,
6303 (uintptr_t)&vargs,
6304 0, 0, 0);
6305 #else
6306 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6307 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6308 (unsigned long)format,
6309 (unsigned long)&vargs,
6310 0, 0, 0);
6311 #endif
6312 va_end(vargs);
6313 return (int)_qzz_res;
6314 #endif /* NVALGRIND */
6318 /* These requests allow control to move from the simulated CPU to the
6319 real CPU, calling an arbitrary function.
6321 Note that the current ThreadId is inserted as the first argument.
6322 So this call:
6324 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
6326 requires f to have this signature:
6328 Word f(Word tid, Word arg1, Word arg2)
6330 where "Word" is a word-sized type.
6332 Note that these client requests are not entirely reliable. For example,
6333 if you call a function with them that subsequently calls printf(),
6334 there's a high chance Valgrind will crash. Generally, your prospects of
6335 these working are made higher if the called function does not refer to
6336 any global variables, and does not refer to any libc or other functions
6337 (printf et al). Any kind of entanglement with libc or dynamic linking is
6338 likely to have a bad outcome, for tricky reasons which we've grappled
6339 with a lot in the past.
6341 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
6342 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6343 VG_USERREQ__CLIENT_CALL0, \
6344 _qyy_fn, \
6345 0, 0, 0, 0)
6347 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
6348 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6349 VG_USERREQ__CLIENT_CALL1, \
6350 _qyy_fn, \
6351 _qyy_arg1, 0, 0, 0)
6353 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
6354 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6355 VG_USERREQ__CLIENT_CALL2, \
6356 _qyy_fn, \
6357 _qyy_arg1, _qyy_arg2, 0, 0)
6359 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
6360 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6361 VG_USERREQ__CLIENT_CALL3, \
6362 _qyy_fn, \
6363 _qyy_arg1, _qyy_arg2, \
6364 _qyy_arg3, 0)
6367 /* Counts the number of errors that have been recorded by a tool. Nb:
6368 the tool must record the errors with VG_(maybe_record_error)() or
6369 VG_(unique_error)() for them to be counted. */
6370 #define VALGRIND_COUNT_ERRORS \
6371 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
6372 0 /* default return */, \
6373 VG_USERREQ__COUNT_ERRORS, \
6374 0, 0, 0, 0, 0)
6376 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
6377 when heap blocks are allocated in order to give accurate results. This
6378 happens automatically for the standard allocator functions such as
6379 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
6380 delete[], etc.
6382 But if your program uses a custom allocator, this doesn't automatically
6383 happen, and Valgrind will not do as well. For example, if you allocate
6384 superblocks with mmap() and then allocates chunks of the superblocks, all
6385 Valgrind's observations will be at the mmap() level and it won't know that
6386 the chunks should be considered separate entities. In Memcheck's case,
6387 that means you probably won't get heap block overrun detection (because
6388 there won't be redzones marked as unaddressable) and you definitely won't
6389 get any leak detection.
6391 The following client requests allow a custom allocator to be annotated so
6392 that it can be handled accurately by Valgrind.
6394 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
6395 by a malloc()-like function. For Memcheck (an illustrative case), this
6396 does two things:
6398 - It records that the block has been allocated. This means any addresses
6399 within the block mentioned in error messages will be
6400 identified as belonging to the block. It also means that if the block
6401 isn't freed it will be detected by the leak checker.
6403 - It marks the block as being addressable and undefined (if 'is_zeroed' is
6404 not set), or addressable and defined (if 'is_zeroed' is set). This
6405 controls how accesses to the block by the program are handled.
6407 'addr' is the start of the usable block (ie. after any
6408 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
6409 can apply redzones -- these are blocks of padding at the start and end of
6410 each block. Adding redzones is recommended as it makes it much more likely
6411 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
6412 zeroed (or filled with another predictable value), as is the case for
6413 calloc().
6415 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
6416 heap block -- that will be used by the client program -- is allocated.
6417 It's best to put it at the outermost level of the allocator if possible;
6418 for example, if you have a function my_alloc() which calls
6419 internal_alloc(), and the client request is put inside internal_alloc(),
6420 stack traces relating to the heap block will contain entries for both
6421 my_alloc() and internal_alloc(), which is probably not what you want.
6423 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
6424 custom blocks from within a heap block, B, that has been allocated with
6425 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
6426 -- the custom blocks will take precedence.
6428 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
6429 Memcheck, it does two things:
6431 - It records that the block has been deallocated. This assumes that the
6432 block was annotated as having been allocated via
6433 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
6435 - It marks the block as being unaddressable.
6437 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
6438 heap block is deallocated.
6440 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
6441 Memcheck, it does four things:
6443 - It records that the size of a block has been changed. This assumes that
6444 the block was annotated as having been allocated via
6445 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
6447 - If the block shrunk, it marks the freed memory as being unaddressable.
6449 - If the block grew, it marks the new area as undefined and defines a red
6450 zone past the end of the new block.
6452 - The V-bits of the overlap between the old and the new block are preserved.
6454 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
6455 and before deallocation of the old block.
6457 In many cases, these three client requests will not be enough to get your
6458 allocator working well with Memcheck. More specifically, if your allocator
6459 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
6460 will be necessary to mark the memory as addressable just before the zeroing
6461 occurs, otherwise you'll get a lot of invalid write errors. For example,
6462 you'll need to do this if your allocator recycles freed blocks, but it
6463 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
6464 Alternatively, if your allocator reuses freed blocks for allocator-internal
6465 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
6467 Really, what's happening is a blurring of the lines between the client
6468 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
6469 memory should be considered unaddressable to the client program, but the
6470 allocator knows more than the rest of the client program and so may be able
6471 to safely access it. Extra client requests are necessary for Valgrind to
6472 understand the distinction between the allocator and the rest of the
6473 program.
6475 Ignored if addr == 0.
6477 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
6478 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
6479 addr, sizeB, rzB, is_zeroed, 0)
6481 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6482 Ignored if addr == 0.
6484 #define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
6485 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
6486 addr, oldSizeB, newSizeB, rzB, 0)
6488 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6489 Ignored if addr == 0.
6491 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
6492 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
6493 addr, rzB, 0, 0, 0)
6495 /* Create a memory pool. */
6496 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
6497 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
6498 pool, rzB, is_zeroed, 0, 0)
6500 /* Create a memory pool with some flags specifying extended behaviour.
6501 When flags is zero, the behaviour is identical to VALGRIND_CREATE_MEMPOOL.
6503 The flag VALGRIND_MEMPOOL_METAPOOL specifies that the pieces of memory
6504 associated with the pool using VALGRIND_MEMPOOL_ALLOC will be used
6505 by the application as superblocks to dole out MALLOC_LIKE blocks using
6506 VALGRIND_MALLOCLIKE_BLOCK. In other words, a meta pool is a "2 levels"
6507 pool : first level is the blocks described by VALGRIND_MEMPOOL_ALLOC.
6508 The second level blocks are described using VALGRIND_MALLOCLIKE_BLOCK.
6509 Note that the association between the pool and the second level blocks
6510 is implicit : second level blocks will be located inside first level
6511 blocks. It is necessary to use the VALGRIND_MEMPOOL_METAPOOL flag
6512 for such 2 levels pools, as otherwise valgrind will detect overlapping
6513 memory blocks, and will abort execution (e.g. during leak search).
6515 Such a meta pool can also be marked as an 'auto free' pool using the flag
6516 VALGRIND_MEMPOOL_AUTO_FREE, which must be OR-ed together with the
6517 VALGRIND_MEMPOOL_METAPOOL. For an 'auto free' pool, VALGRIND_MEMPOOL_FREE
6518 will automatically free the second level blocks that are contained
6519 inside the first level block freed with VALGRIND_MEMPOOL_FREE.
6520 In other words, calling VALGRIND_MEMPOOL_FREE will cause implicit calls
6521 to VALGRIND_FREELIKE_BLOCK for all the second level blocks included
6522 in the first level block.
6523 Note: it is an error to use the VALGRIND_MEMPOOL_AUTO_FREE flag
6524 without the VALGRIND_MEMPOOL_METAPOOL flag.
6526 #define VALGRIND_MEMPOOL_AUTO_FREE 1
6527 #define VALGRIND_MEMPOOL_METAPOOL 2
6528 #define VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags) \
6529 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
6530 pool, rzB, is_zeroed, flags, 0)
6532 /* Destroy a memory pool. */
6533 #define VALGRIND_DESTROY_MEMPOOL(pool) \
6534 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
6535 pool, 0, 0, 0, 0)
6537 /* Associate a piece of memory with a memory pool. */
6538 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
6539 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
6540 pool, addr, size, 0, 0)
6542 /* Disassociate a piece of memory from a memory pool. */
6543 #define VALGRIND_MEMPOOL_FREE(pool, addr) \
6544 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
6545 pool, addr, 0, 0, 0)
6547 /* Disassociate any pieces outside a particular range. */
6548 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
6549 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
6550 pool, addr, size, 0, 0)
6552 /* Resize and/or move a piece associated with a memory pool. */
6553 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
6554 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
6555 poolA, poolB, 0, 0, 0)
6557 /* Resize and/or move a piece associated with a memory pool. */
6558 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
6559 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
6560 pool, addrA, addrB, size, 0)
6562 /* Return 1 if a mempool exists, else 0. */
6563 #define VALGRIND_MEMPOOL_EXISTS(pool) \
6564 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
6565 VG_USERREQ__MEMPOOL_EXISTS, \
6566 pool, 0, 0, 0, 0)
6568 /* Mark a piece of memory as being a stack. Returns a stack id.
6569 start is the lowest addressable stack byte, end is the highest
6570 addressable stack byte. */
6571 #define VALGRIND_STACK_REGISTER(start, end) \
6572 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
6573 VG_USERREQ__STACK_REGISTER, \
6574 start, end, 0, 0, 0)
6576 /* Unmark the piece of memory associated with a stack id as being a
6577 stack. */
6578 #define VALGRIND_STACK_DEREGISTER(id) \
6579 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
6580 id, 0, 0, 0, 0)
6582 /* Change the start and end address of the stack id.
6583 start is the new lowest addressable stack byte, end is the new highest
6584 addressable stack byte. */
6585 #define VALGRIND_STACK_CHANGE(id, start, end) \
6586 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
6587 id, start, end, 0, 0)
6589 /* Load PDB debug info for Wine PE image_map. */
6590 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
6591 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
6592 fd, ptr, total_size, delta, 0)
6594 /* Map a code address to a source file name and line number. buf64
6595 must point to a 64-byte buffer in the caller's address space. The
6596 result will be dumped in there and is guaranteed to be zero
6597 terminated. If no info is found, the first byte is set to zero. */
6598 #define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
6599 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
6600 VG_USERREQ__MAP_IP_TO_SRCLOC, \
6601 addr, buf64, 0, 0, 0)
6603 /* Disable error reporting for this thread. Behaves in a stack like
6604 way, so you can safely call this multiple times provided that
6605 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
6606 to re-enable reporting. The first call of this macro disables
6607 reporting. Subsequent calls have no effect except to increase the
6608 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
6609 reporting. Child threads do not inherit this setting from their
6610 parents -- they are always created with reporting enabled. */
6611 #define VALGRIND_DISABLE_ERROR_REPORTING \
6612 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6613 1, 0, 0, 0, 0)
6615 /* Re-enable error reporting, as per comments on
6616 VALGRIND_DISABLE_ERROR_REPORTING. */
6617 #define VALGRIND_ENABLE_ERROR_REPORTING \
6618 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6619 -1, 0, 0, 0, 0)
6621 /* Execute a monitor command from the client program.
6622 If a connection is opened with GDB, the output will be sent
6623 according to the output mode set for vgdb.
6624 If no connection is opened, output will go to the log output.
6625 Returns 1 if command not recognised, 0 otherwise. */
6626 #define VALGRIND_MONITOR_COMMAND(command) \
6627 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
6628 command, 0, 0, 0, 0)
6631 #undef PLAT_x86_darwin
6632 #undef PLAT_amd64_darwin
6633 #undef PLAT_x86_win32
6634 #undef PLAT_amd64_win64
6635 #undef PLAT_x86_linux
6636 #undef PLAT_amd64_linux
6637 #undef PLAT_ppc32_linux
6638 #undef PLAT_ppc64be_linux
6639 #undef PLAT_ppc64le_linux
6640 #undef PLAT_arm_linux
6641 #undef PLAT_s390x_linux
6642 #undef PLAT_mips32_linux
6643 #undef PLAT_mips64_linux
6644 #undef PLAT_x86_solaris
6645 #undef PLAT_amd64_solaris
6647 #endif /* __VALGRIND_H */