iPXE
valgrind.h
Go to the documentation of this file.
1/* -*- c -*-
2 ----------------------------------------------------------------
3
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.
9
10 ----------------------------------------------------------------
11
12 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
14
15 Copyright (C) 2000-2010 Julian Seward. All rights reserved.
16
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
20
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23
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.
28
29 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
31
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.
35
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.
47
48 ----------------------------------------------------------------
49
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.
54
55 ----------------------------------------------------------------
56*/
57
58
59/* This file is for inclusion into client (your!) code.
60
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
63
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. */
72
73#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
76FILE_LICENCE ( BSD3 );
77FILE_SECBOOT ( PERMITTED );
78
79
80/* ------------------------------------------------------------------ */
81/* VERSION NUMBER OF VALGRIND */
82/* ------------------------------------------------------------------ */
83
84/* Specify Valgrind's version number, so that user code can
85 conditionally compile based on our version number. Note that these
86 were introduced at version 3.6 and so do not exist in version 3.5
87 or earlier. The recommended way to use them to check for "version
88 X.Y or later" is (eg)
89
90#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
91 && (__VALGRIND_MAJOR__ > 3 \
92 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
93*/
94#define __VALGRIND_MAJOR__ 3
95#define __VALGRIND_MINOR__ 6
96
97
98#include <stdarg.h>
99
100/* Nb: this file might be included in a file compiled with -ansi. So
101 we can't use C++ style "//" comments nor the "asm" keyword (instead
102 use "__asm__"). */
103
104/* Derive some tags indicating what the target platform is. Note
105 that in this file we're using the compiler's CPP symbols for
106 identifying architectures, which are different to the ones we use
107 within the rest of Valgrind. Note, __powerpc__ is active for both
108 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
109 latter (on Linux, that is).
110
111 Misc note: how to find out what's predefined in gcc by default:
112 gcc -Wp,-dM somefile.c
113*/
114#undef PLAT_ppc64_aix5
115#undef PLAT_ppc32_aix5
116#undef PLAT_x86_darwin
117#undef PLAT_amd64_darwin
118#undef PLAT_x86_linux
119#undef PLAT_amd64_linux
120#undef PLAT_ppc32_linux
121#undef PLAT_ppc64_linux
122#undef PLAT_arm_linux
123
124#if defined(_AIX) && defined(__64BIT__)
125# define PLAT_ppc64_aix5 1
126#elif defined(_AIX) && !defined(__64BIT__)
127# define PLAT_ppc32_aix5 1
128#elif defined(__APPLE__) && defined(__i386__)
129# define PLAT_x86_darwin 1
130#elif defined(__APPLE__) && defined(__x86_64__)
131# define PLAT_amd64_darwin 1
132#elif defined(__linux__) && defined(__i386__)
133# define PLAT_x86_linux 1
134#elif defined(__linux__) && defined(__x86_64__)
135# define PLAT_amd64_linux 1
136#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
137# define PLAT_ppc32_linux 1
138#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
139# define PLAT_ppc64_linux 1
140#elif defined(__linux__) && defined(__arm__)
141# define PLAT_arm_linux 1
142#else
143/* If we're not compiling for our target platform, don't generate
144 any inline asms. */
145# if !defined(NVALGRIND)
146# define NVALGRIND 1
147# endif
148#endif
149
150
151/* ------------------------------------------------------------------ */
152/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
153/* in here of use to end-users -- skip to the next section. */
154/* ------------------------------------------------------------------ */
155
156#if defined(NVALGRIND)
157
158/* Define NVALGRIND to completely remove the Valgrind magic sequence
159 from the compiled code (analogous to NDEBUG's effects on
160 assert()) */
161#define VALGRIND_DO_CLIENT_REQUEST( \
162 _zzq_rlval, _zzq_default, _zzq_request, \
163 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
164 { \
165 (_zzq_rlval) = (_zzq_default); \
166 }
167
168#else /* ! NVALGRIND */
169
170/* The following defines the magic code sequences which the JITter
171 spots and handles magically. Don't look too closely at them as
172 they will rot your brain.
173
174 The assembly code sequences for all architectures is in this one
175 file. This is because this file must be stand-alone, and we don't
176 want to have multiple files.
177
178 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
179 value gets put in the return slot, so that everything works when
180 this is executed not under Valgrind. Args are passed in a memory
181 block, and so there's no intrinsic limit to the number that could
182 be passed, but it's currently five.
183
184 The macro args are:
185 _zzq_rlval result lvalue
186 _zzq_default default value (result returned when running on real CPU)
187 _zzq_request request code
188 _zzq_arg1..5 request params
189
190 The other two macros are used to support function wrapping, and are
191 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
192 guest's NRADDR pseudo-register and whatever other information is
193 needed to safely run the call original from the wrapper: on
194 ppc64-linux, the R2 value at the divert point is also needed. This
195 information is abstracted into a user-visible type, OrigFn.
196
197 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
198 guest, but guarantees that the branch instruction will not be
199 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
200 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
201 complete inline asm, since it needs to be combined with more magic
202 inline asm stuff to be useful.
203*/
204
205/* ------------------------- x86-{linux,darwin} ---------------- */
206
207#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
208
209typedef
210 struct {
211 unsigned int nraddr; /* where's the code? */
212 }
213 OrigFn;
214
215#define __SPECIAL_INSTRUCTION_PREAMBLE \
216 "roll $3, %%edi ; roll $13, %%edi\n\t" \
217 "roll $29, %%edi ; roll $19, %%edi\n\t"
218
219#define VALGRIND_DO_CLIENT_REQUEST( \
220 _zzq_rlval, _zzq_default, _zzq_request, \
221 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
222 { volatile unsigned int _zzq_args[6]; \
223 volatile unsigned int _zzq_result; \
224 _zzq_args[0] = (unsigned int)(_zzq_request); \
225 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
226 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
227 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
228 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
229 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
230 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
231 /* %EDX = client_request ( %EAX ) */ \
232 "xchgl %%ebx,%%ebx" \
233 : "=d" (_zzq_result) \
234 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
235 : "cc", "memory" \
236 ); \
237 _zzq_rlval = _zzq_result; \
238 }
239
240#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
241 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
242 volatile unsigned int __addr; \
243 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
244 /* %EAX = guest_NRADDR */ \
245 "xchgl %%ecx,%%ecx" \
246 : "=a" (__addr) \
247 : \
248 : "cc", "memory" \
249 ); \
250 _zzq_orig->nraddr = __addr; \
251 }
252
253#define VALGRIND_CALL_NOREDIR_EAX \
254 __SPECIAL_INSTRUCTION_PREAMBLE \
255 /* call-noredir *%EAX */ \
256 "xchgl %%edx,%%edx\n\t"
257#endif /* PLAT_x86_linux || PLAT_x86_darwin */
258
259/* ------------------------ amd64-{linux,darwin} --------------- */
260
261#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
262
263typedef
264 struct {
265 unsigned long long int nraddr; /* where's the code? */
266 }
267 OrigFn;
268
269#define __SPECIAL_INSTRUCTION_PREAMBLE \
270 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
271 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
272
273#define VALGRIND_DO_CLIENT_REQUEST( \
274 _zzq_rlval, _zzq_default, _zzq_request, \
275 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
276 { volatile unsigned long long int _zzq_args[6]; \
277 volatile unsigned long long int _zzq_result; \
278 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
279 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
280 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
281 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
282 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
283 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
284 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
285 /* %RDX = client_request ( %RAX ) */ \
286 "xchgq %%rbx,%%rbx" \
287 : "=d" (_zzq_result) \
288 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
289 : "cc", "memory" \
290 ); \
291 _zzq_rlval = _zzq_result; \
292 }
293
294#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
295 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
296 volatile unsigned long long int __addr; \
297 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
298 /* %RAX = guest_NRADDR */ \
299 "xchgq %%rcx,%%rcx" \
300 : "=a" (__addr) \
301 : \
302 : "cc", "memory" \
303 ); \
304 _zzq_orig->nraddr = __addr; \
305 }
306
307#define VALGRIND_CALL_NOREDIR_RAX \
308 __SPECIAL_INSTRUCTION_PREAMBLE \
309 /* call-noredir *%RAX */ \
310 "xchgq %%rdx,%%rdx\n\t"
311#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
312
313/* ------------------------ ppc32-linux ------------------------ */
314
315#if defined(PLAT_ppc32_linux)
316
317typedef
318 struct {
319 unsigned int nraddr; /* where's the code? */
320 }
321 OrigFn;
322
323#define __SPECIAL_INSTRUCTION_PREAMBLE \
324 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
325 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
326
327#define VALGRIND_DO_CLIENT_REQUEST( \
328 _zzq_rlval, _zzq_default, _zzq_request, \
329 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
330 \
331 { unsigned int _zzq_args[6]; \
332 unsigned int _zzq_result; \
333 unsigned int* _zzq_ptr; \
334 _zzq_args[0] = (unsigned int)(_zzq_request); \
335 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
336 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
337 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
338 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
339 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
340 _zzq_ptr = _zzq_args; \
341 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
342 "mr 4,%2\n\t" /*ptr*/ \
343 __SPECIAL_INSTRUCTION_PREAMBLE \
344 /* %R3 = client_request ( %R4 ) */ \
345 "or 1,1,1\n\t" \
346 "mr %0,3" /*result*/ \
347 : "=b" (_zzq_result) \
348 : "b" (_zzq_default), "b" (_zzq_ptr) \
349 : "cc", "memory", "r3", "r4"); \
350 _zzq_rlval = _zzq_result; \
351 }
352
353#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
354 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
355 unsigned int __addr; \
356 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
357 /* %R3 = guest_NRADDR */ \
358 "or 2,2,2\n\t" \
359 "mr %0,3" \
360 : "=b" (__addr) \
361 : \
362 : "cc", "memory", "r3" \
363 ); \
364 _zzq_orig->nraddr = __addr; \
365 }
366
367#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
368 __SPECIAL_INSTRUCTION_PREAMBLE \
369 /* branch-and-link-to-noredir *%R11 */ \
370 "or 3,3,3\n\t"
371#endif /* PLAT_ppc32_linux */
372
373/* ------------------------ ppc64-linux ------------------------ */
374
375#if defined(PLAT_ppc64_linux)
376
377typedef
378 struct {
379 unsigned long long int nraddr; /* where's the code? */
380 unsigned long long int r2; /* what tocptr do we need? */
381 }
382 OrigFn;
383
384#define __SPECIAL_INSTRUCTION_PREAMBLE \
385 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
386 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
387
388#define VALGRIND_DO_CLIENT_REQUEST( \
389 _zzq_rlval, _zzq_default, _zzq_request, \
390 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
391 \
392 { unsigned long long int _zzq_args[6]; \
393 register unsigned long long int _zzq_result __asm__("r3"); \
394 register unsigned long long int* _zzq_ptr __asm__("r4"); \
395 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
396 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
397 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
398 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
399 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
400 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
401 _zzq_ptr = _zzq_args; \
402 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
403 /* %R3 = client_request ( %R4 ) */ \
404 "or 1,1,1" \
405 : "=r" (_zzq_result) \
406 : "0" (_zzq_default), "r" (_zzq_ptr) \
407 : "cc", "memory"); \
408 _zzq_rlval = _zzq_result; \
409 }
410
411#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
412 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
413 register unsigned long long int __addr __asm__("r3"); \
414 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
415 /* %R3 = guest_NRADDR */ \
416 "or 2,2,2" \
417 : "=r" (__addr) \
418 : \
419 : "cc", "memory" \
420 ); \
421 _zzq_orig->nraddr = __addr; \
422 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
423 /* %R3 = guest_NRADDR_GPR2 */ \
424 "or 4,4,4" \
425 : "=r" (__addr) \
426 : \
427 : "cc", "memory" \
428 ); \
429 _zzq_orig->r2 = __addr; \
430 }
431
432#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
433 __SPECIAL_INSTRUCTION_PREAMBLE \
434 /* branch-and-link-to-noredir *%R11 */ \
435 "or 3,3,3\n\t"
436
437#endif /* PLAT_ppc64_linux */
438
439/* ------------------------- arm-linux ------------------------- */
440
441#if defined(PLAT_arm_linux)
442
443typedef
444 struct {
445 unsigned int nraddr; /* where's the code? */
446 }
447 OrigFn;
448
449#define __SPECIAL_INSTRUCTION_PREAMBLE \
450 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
451 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
452
453#define VALGRIND_DO_CLIENT_REQUEST( \
454 _zzq_rlval, _zzq_default, _zzq_request, \
455 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
456 \
457 { volatile unsigned int _zzq_args[6]; \
458 volatile unsigned int _zzq_result; \
459 _zzq_args[0] = (unsigned int)(_zzq_request); \
460 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
461 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
462 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
463 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
464 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
465 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
466 "mov r4, %2\n\t" /*ptr*/ \
467 __SPECIAL_INSTRUCTION_PREAMBLE \
468 /* R3 = client_request ( R4 ) */ \
469 "orr r10, r10, r10\n\t" \
470 "mov %0, r3" /*result*/ \
471 : "=r" (_zzq_result) \
472 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
473 : "cc","memory", "r3", "r4"); \
474 _zzq_rlval = _zzq_result; \
475 }
476
477#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
478 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
479 unsigned int __addr; \
480 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
481 /* R3 = guest_NRADDR */ \
482 "orr r11, r11, r11\n\t" \
483 "mov %0, r3" \
484 : "=r" (__addr) \
485 : \
486 : "cc", "memory", "r3" \
487 ); \
488 _zzq_orig->nraddr = __addr; \
489 }
490
491#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
492 __SPECIAL_INSTRUCTION_PREAMBLE \
493 /* branch-and-link-to-noredir *%R4 */ \
494 "orr r12, r12, r12\n\t"
495
496#endif /* PLAT_arm_linux */
497
498/* ------------------------ ppc32-aix5 ------------------------- */
499
500#if defined(PLAT_ppc32_aix5)
501
502typedef
503 struct {
504 unsigned int nraddr; /* where's the code? */
505 unsigned int r2; /* what tocptr do we need? */
506 }
507 OrigFn;
508
509#define __SPECIAL_INSTRUCTION_PREAMBLE \
510 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
511 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
512
513#define VALGRIND_DO_CLIENT_REQUEST( \
514 _zzq_rlval, _zzq_default, _zzq_request, \
515 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
516 \
517 { unsigned int _zzq_args[7]; \
518 register unsigned int _zzq_result; \
519 register unsigned int* _zzq_ptr; \
520 _zzq_args[0] = (unsigned int)(_zzq_request); \
521 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
522 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
523 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
524 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
525 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
526 _zzq_args[6] = (unsigned int)(_zzq_default); \
527 _zzq_ptr = _zzq_args; \
528 __asm__ volatile("mr 4,%1\n\t" \
529 "lwz 3, 24(4)\n\t" \
530 __SPECIAL_INSTRUCTION_PREAMBLE \
531 /* %R3 = client_request ( %R4 ) */ \
532 "or 1,1,1\n\t" \
533 "mr %0,3" \
534 : "=b" (_zzq_result) \
535 : "b" (_zzq_ptr) \
536 : "r3", "r4", "cc", "memory"); \
537 _zzq_rlval = _zzq_result; \
538 }
539
540#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
541 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
542 register unsigned int __addr; \
543 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
544 /* %R3 = guest_NRADDR */ \
545 "or 2,2,2\n\t" \
546 "mr %0,3" \
547 : "=b" (__addr) \
548 : \
549 : "r3", "cc", "memory" \
550 ); \
551 _zzq_orig->nraddr = __addr; \
552 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
553 /* %R3 = guest_NRADDR_GPR2 */ \
554 "or 4,4,4\n\t" \
555 "mr %0,3" \
556 : "=b" (__addr) \
557 : \
558 : "r3", "cc", "memory" \
559 ); \
560 _zzq_orig->r2 = __addr; \
561 }
562
563#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
564 __SPECIAL_INSTRUCTION_PREAMBLE \
565 /* branch-and-link-to-noredir *%R11 */ \
566 "or 3,3,3\n\t"
567
568#endif /* PLAT_ppc32_aix5 */
569
570/* ------------------------ ppc64-aix5 ------------------------- */
571
572#if defined(PLAT_ppc64_aix5)
573
574typedef
575 struct {
576 unsigned long long int nraddr; /* where's the code? */
577 unsigned long long int r2; /* what tocptr do we need? */
578 }
579 OrigFn;
580
581#define __SPECIAL_INSTRUCTION_PREAMBLE \
582 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
583 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
584
585#define VALGRIND_DO_CLIENT_REQUEST( \
586 _zzq_rlval, _zzq_default, _zzq_request, \
587 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
588 \
589 { unsigned long long int _zzq_args[7]; \
590 register unsigned long long int _zzq_result; \
591 register unsigned long long int* _zzq_ptr; \
592 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
593 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
594 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
595 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
596 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
597 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
598 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
599 _zzq_ptr = _zzq_args; \
600 __asm__ volatile("mr 4,%1\n\t" \
601 "ld 3, 48(4)\n\t" \
602 __SPECIAL_INSTRUCTION_PREAMBLE \
603 /* %R3 = client_request ( %R4 ) */ \
604 "or 1,1,1\n\t" \
605 "mr %0,3" \
606 : "=b" (_zzq_result) \
607 : "b" (_zzq_ptr) \
608 : "r3", "r4", "cc", "memory"); \
609 _zzq_rlval = _zzq_result; \
610 }
611
612#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
613 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
614 register unsigned long long int __addr; \
615 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
616 /* %R3 = guest_NRADDR */ \
617 "or 2,2,2\n\t" \
618 "mr %0,3" \
619 : "=b" (__addr) \
620 : \
621 : "r3", "cc", "memory" \
622 ); \
623 _zzq_orig->nraddr = __addr; \
624 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
625 /* %R3 = guest_NRADDR_GPR2 */ \
626 "or 4,4,4\n\t" \
627 "mr %0,3" \
628 : "=b" (__addr) \
629 : \
630 : "r3", "cc", "memory" \
631 ); \
632 _zzq_orig->r2 = __addr; \
633 }
634
635#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
636 __SPECIAL_INSTRUCTION_PREAMBLE \
637 /* branch-and-link-to-noredir *%R11 */ \
638 "or 3,3,3\n\t"
639
640#endif /* PLAT_ppc64_aix5 */
641
642/* Insert assembly code for other platforms here... */
643
644#endif /* NVALGRIND */
645
646
647/* ------------------------------------------------------------------ */
648/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
649/* ugly. It's the least-worst tradeoff I can think of. */
650/* ------------------------------------------------------------------ */
651
652/* This section defines magic (a.k.a appalling-hack) macros for doing
653 guaranteed-no-redirection macros, so as to get from function
654 wrappers to the functions they are wrapping. The whole point is to
655 construct standard call sequences, but to do the call itself with a
656 special no-redirect call pseudo-instruction that the JIT
657 understands and handles specially. This section is long and
658 repetitious, and I can't see a way to make it shorter.
659
660 The naming scheme is as follows:
661
662 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
663
664 'W' stands for "word" and 'v' for "void". Hence there are
665 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
666 and for each, the possibility of returning a word-typed result, or
667 no result.
668*/
669
670/* Use these to write the name of your wrapper. NOTE: duplicates
671 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
672
673/* Use an extra level of macroisation so as to ensure the soname/fnname
674 args are fully macro-expanded before pasting them together. */
675#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
676
677#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
678 VG_CONCAT4(_vgwZU_,soname,_,fnname)
679
680#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
681 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
682
683/* Use this macro from within a wrapper function to collect the
684 context (address and possibly other info) of the original function.
685 Once you have that you can then use it in one of the CALL_FN_
686 macros. The type of the argument _lval is OrigFn. */
687#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
688
689/* Derivatives of the main macros below, for calling functions
690 returning void. */
691
692#define CALL_FN_v_v(fnptr) \
693 do { volatile unsigned long _junk; \
694 CALL_FN_W_v(_junk,fnptr); } while (0)
695
696#define CALL_FN_v_W(fnptr, arg1) \
697 do { volatile unsigned long _junk; \
698 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
699
700#define CALL_FN_v_WW(fnptr, arg1,arg2) \
701 do { volatile unsigned long _junk; \
702 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
703
704#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
705 do { volatile unsigned long _junk; \
706 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
707
708#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
709 do { volatile unsigned long _junk; \
710 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
711
712#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
713 do { volatile unsigned long _junk; \
714 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
715
716#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
717 do { volatile unsigned long _junk; \
718 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
719
720#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
721 do { volatile unsigned long _junk; \
722 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
723
724/* ------------------------- x86-{linux,darwin} ---------------- */
725
726#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
727
728/* These regs are trashed by the hidden call. No need to mention eax
729 as gcc can already see that, plus causes gcc to bomb. */
730#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
731
732/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
733 long) == 4. */
734
735#define CALL_FN_W_v(lval, orig) \
736 do { \
737 volatile OrigFn _orig = (orig); \
738 volatile unsigned long _argvec[1]; \
739 volatile unsigned long _res; \
740 _argvec[0] = (unsigned long)_orig.nraddr; \
741 __asm__ volatile( \
742 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
743 VALGRIND_CALL_NOREDIR_EAX \
744 : /*out*/ "=a" (_res) \
745 : /*in*/ "a" (&_argvec[0]) \
746 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
747 ); \
748 lval = (__typeof__(lval)) _res; \
749 } while (0)
750
751#define CALL_FN_W_W(lval, orig, arg1) \
752 do { \
753 volatile OrigFn _orig = (orig); \
754 volatile unsigned long _argvec[2]; \
755 volatile unsigned long _res; \
756 _argvec[0] = (unsigned long)_orig.nraddr; \
757 _argvec[1] = (unsigned long)(arg1); \
758 __asm__ volatile( \
759 "pushl 4(%%eax)\n\t" \
760 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
761 VALGRIND_CALL_NOREDIR_EAX \
762 "addl $4, %%esp\n" \
763 : /*out*/ "=a" (_res) \
764 : /*in*/ "a" (&_argvec[0]) \
765 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
766 ); \
767 lval = (__typeof__(lval)) _res; \
768 } while (0)
769
770#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
771 do { \
772 volatile OrigFn _orig = (orig); \
773 volatile unsigned long _argvec[3]; \
774 volatile unsigned long _res; \
775 _argvec[0] = (unsigned long)_orig.nraddr; \
776 _argvec[1] = (unsigned long)(arg1); \
777 _argvec[2] = (unsigned long)(arg2); \
778 __asm__ volatile( \
779 "pushl 8(%%eax)\n\t" \
780 "pushl 4(%%eax)\n\t" \
781 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
782 VALGRIND_CALL_NOREDIR_EAX \
783 "addl $8, %%esp\n" \
784 : /*out*/ "=a" (_res) \
785 : /*in*/ "a" (&_argvec[0]) \
786 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
787 ); \
788 lval = (__typeof__(lval)) _res; \
789 } while (0)
790
791#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
792 do { \
793 volatile OrigFn _orig = (orig); \
794 volatile unsigned long _argvec[4]; \
795 volatile unsigned long _res; \
796 _argvec[0] = (unsigned long)_orig.nraddr; \
797 _argvec[1] = (unsigned long)(arg1); \
798 _argvec[2] = (unsigned long)(arg2); \
799 _argvec[3] = (unsigned long)(arg3); \
800 __asm__ volatile( \
801 "pushl 12(%%eax)\n\t" \
802 "pushl 8(%%eax)\n\t" \
803 "pushl 4(%%eax)\n\t" \
804 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
805 VALGRIND_CALL_NOREDIR_EAX \
806 "addl $12, %%esp\n" \
807 : /*out*/ "=a" (_res) \
808 : /*in*/ "a" (&_argvec[0]) \
809 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
810 ); \
811 lval = (__typeof__(lval)) _res; \
812 } while (0)
813
814#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
815 do { \
816 volatile OrigFn _orig = (orig); \
817 volatile unsigned long _argvec[5]; \
818 volatile unsigned long _res; \
819 _argvec[0] = (unsigned long)_orig.nraddr; \
820 _argvec[1] = (unsigned long)(arg1); \
821 _argvec[2] = (unsigned long)(arg2); \
822 _argvec[3] = (unsigned long)(arg3); \
823 _argvec[4] = (unsigned long)(arg4); \
824 __asm__ volatile( \
825 "pushl 16(%%eax)\n\t" \
826 "pushl 12(%%eax)\n\t" \
827 "pushl 8(%%eax)\n\t" \
828 "pushl 4(%%eax)\n\t" \
829 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
830 VALGRIND_CALL_NOREDIR_EAX \
831 "addl $16, %%esp\n" \
832 : /*out*/ "=a" (_res) \
833 : /*in*/ "a" (&_argvec[0]) \
834 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
835 ); \
836 lval = (__typeof__(lval)) _res; \
837 } while (0)
838
839#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
840 do { \
841 volatile OrigFn _orig = (orig); \
842 volatile unsigned long _argvec[6]; \
843 volatile unsigned long _res; \
844 _argvec[0] = (unsigned long)_orig.nraddr; \
845 _argvec[1] = (unsigned long)(arg1); \
846 _argvec[2] = (unsigned long)(arg2); \
847 _argvec[3] = (unsigned long)(arg3); \
848 _argvec[4] = (unsigned long)(arg4); \
849 _argvec[5] = (unsigned long)(arg5); \
850 __asm__ volatile( \
851 "pushl 20(%%eax)\n\t" \
852 "pushl 16(%%eax)\n\t" \
853 "pushl 12(%%eax)\n\t" \
854 "pushl 8(%%eax)\n\t" \
855 "pushl 4(%%eax)\n\t" \
856 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
857 VALGRIND_CALL_NOREDIR_EAX \
858 "addl $20, %%esp\n" \
859 : /*out*/ "=a" (_res) \
860 : /*in*/ "a" (&_argvec[0]) \
861 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
862 ); \
863 lval = (__typeof__(lval)) _res; \
864 } while (0)
865
866#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
867 do { \
868 volatile OrigFn _orig = (orig); \
869 volatile unsigned long _argvec[7]; \
870 volatile unsigned long _res; \
871 _argvec[0] = (unsigned long)_orig.nraddr; \
872 _argvec[1] = (unsigned long)(arg1); \
873 _argvec[2] = (unsigned long)(arg2); \
874 _argvec[3] = (unsigned long)(arg3); \
875 _argvec[4] = (unsigned long)(arg4); \
876 _argvec[5] = (unsigned long)(arg5); \
877 _argvec[6] = (unsigned long)(arg6); \
878 __asm__ volatile( \
879 "pushl 24(%%eax)\n\t" \
880 "pushl 20(%%eax)\n\t" \
881 "pushl 16(%%eax)\n\t" \
882 "pushl 12(%%eax)\n\t" \
883 "pushl 8(%%eax)\n\t" \
884 "pushl 4(%%eax)\n\t" \
885 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
886 VALGRIND_CALL_NOREDIR_EAX \
887 "addl $24, %%esp\n" \
888 : /*out*/ "=a" (_res) \
889 : /*in*/ "a" (&_argvec[0]) \
890 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
891 ); \
892 lval = (__typeof__(lval)) _res; \
893 } while (0)
894
895#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
896 arg7) \
897 do { \
898 volatile OrigFn _orig = (orig); \
899 volatile unsigned long _argvec[8]; \
900 volatile unsigned long _res; \
901 _argvec[0] = (unsigned long)_orig.nraddr; \
902 _argvec[1] = (unsigned long)(arg1); \
903 _argvec[2] = (unsigned long)(arg2); \
904 _argvec[3] = (unsigned long)(arg3); \
905 _argvec[4] = (unsigned long)(arg4); \
906 _argvec[5] = (unsigned long)(arg5); \
907 _argvec[6] = (unsigned long)(arg6); \
908 _argvec[7] = (unsigned long)(arg7); \
909 __asm__ volatile( \
910 "pushl 28(%%eax)\n\t" \
911 "pushl 24(%%eax)\n\t" \
912 "pushl 20(%%eax)\n\t" \
913 "pushl 16(%%eax)\n\t" \
914 "pushl 12(%%eax)\n\t" \
915 "pushl 8(%%eax)\n\t" \
916 "pushl 4(%%eax)\n\t" \
917 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
918 VALGRIND_CALL_NOREDIR_EAX \
919 "addl $28, %%esp\n" \
920 : /*out*/ "=a" (_res) \
921 : /*in*/ "a" (&_argvec[0]) \
922 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
923 ); \
924 lval = (__typeof__(lval)) _res; \
925 } while (0)
926
927#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
928 arg7,arg8) \
929 do { \
930 volatile OrigFn _orig = (orig); \
931 volatile unsigned long _argvec[9]; \
932 volatile unsigned long _res; \
933 _argvec[0] = (unsigned long)_orig.nraddr; \
934 _argvec[1] = (unsigned long)(arg1); \
935 _argvec[2] = (unsigned long)(arg2); \
936 _argvec[3] = (unsigned long)(arg3); \
937 _argvec[4] = (unsigned long)(arg4); \
938 _argvec[5] = (unsigned long)(arg5); \
939 _argvec[6] = (unsigned long)(arg6); \
940 _argvec[7] = (unsigned long)(arg7); \
941 _argvec[8] = (unsigned long)(arg8); \
942 __asm__ volatile( \
943 "pushl 32(%%eax)\n\t" \
944 "pushl 28(%%eax)\n\t" \
945 "pushl 24(%%eax)\n\t" \
946 "pushl 20(%%eax)\n\t" \
947 "pushl 16(%%eax)\n\t" \
948 "pushl 12(%%eax)\n\t" \
949 "pushl 8(%%eax)\n\t" \
950 "pushl 4(%%eax)\n\t" \
951 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
952 VALGRIND_CALL_NOREDIR_EAX \
953 "addl $32, %%esp\n" \
954 : /*out*/ "=a" (_res) \
955 : /*in*/ "a" (&_argvec[0]) \
956 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
957 ); \
958 lval = (__typeof__(lval)) _res; \
959 } while (0)
960
961#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
962 arg7,arg8,arg9) \
963 do { \
964 volatile OrigFn _orig = (orig); \
965 volatile unsigned long _argvec[10]; \
966 volatile unsigned long _res; \
967 _argvec[0] = (unsigned long)_orig.nraddr; \
968 _argvec[1] = (unsigned long)(arg1); \
969 _argvec[2] = (unsigned long)(arg2); \
970 _argvec[3] = (unsigned long)(arg3); \
971 _argvec[4] = (unsigned long)(arg4); \
972 _argvec[5] = (unsigned long)(arg5); \
973 _argvec[6] = (unsigned long)(arg6); \
974 _argvec[7] = (unsigned long)(arg7); \
975 _argvec[8] = (unsigned long)(arg8); \
976 _argvec[9] = (unsigned long)(arg9); \
977 __asm__ volatile( \
978 "pushl 36(%%eax)\n\t" \
979 "pushl 32(%%eax)\n\t" \
980 "pushl 28(%%eax)\n\t" \
981 "pushl 24(%%eax)\n\t" \
982 "pushl 20(%%eax)\n\t" \
983 "pushl 16(%%eax)\n\t" \
984 "pushl 12(%%eax)\n\t" \
985 "pushl 8(%%eax)\n\t" \
986 "pushl 4(%%eax)\n\t" \
987 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
988 VALGRIND_CALL_NOREDIR_EAX \
989 "addl $36, %%esp\n" \
990 : /*out*/ "=a" (_res) \
991 : /*in*/ "a" (&_argvec[0]) \
992 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
993 ); \
994 lval = (__typeof__(lval)) _res; \
995 } while (0)
996
997#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
998 arg7,arg8,arg9,arg10) \
999 do { \
1000 volatile OrigFn _orig = (orig); \
1001 volatile unsigned long _argvec[11]; \
1002 volatile unsigned long _res; \
1003 _argvec[0] = (unsigned long)_orig.nraddr; \
1004 _argvec[1] = (unsigned long)(arg1); \
1005 _argvec[2] = (unsigned long)(arg2); \
1006 _argvec[3] = (unsigned long)(arg3); \
1007 _argvec[4] = (unsigned long)(arg4); \
1008 _argvec[5] = (unsigned long)(arg5); \
1009 _argvec[6] = (unsigned long)(arg6); \
1010 _argvec[7] = (unsigned long)(arg7); \
1011 _argvec[8] = (unsigned long)(arg8); \
1012 _argvec[9] = (unsigned long)(arg9); \
1013 _argvec[10] = (unsigned long)(arg10); \
1014 __asm__ volatile( \
1015 "pushl 40(%%eax)\n\t" \
1016 "pushl 36(%%eax)\n\t" \
1017 "pushl 32(%%eax)\n\t" \
1018 "pushl 28(%%eax)\n\t" \
1019 "pushl 24(%%eax)\n\t" \
1020 "pushl 20(%%eax)\n\t" \
1021 "pushl 16(%%eax)\n\t" \
1022 "pushl 12(%%eax)\n\t" \
1023 "pushl 8(%%eax)\n\t" \
1024 "pushl 4(%%eax)\n\t" \
1025 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1026 VALGRIND_CALL_NOREDIR_EAX \
1027 "addl $40, %%esp\n" \
1028 : /*out*/ "=a" (_res) \
1029 : /*in*/ "a" (&_argvec[0]) \
1030 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1031 ); \
1032 lval = (__typeof__(lval)) _res; \
1033 } while (0)
1034
1035#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1036 arg6,arg7,arg8,arg9,arg10, \
1037 arg11) \
1038 do { \
1039 volatile OrigFn _orig = (orig); \
1040 volatile unsigned long _argvec[12]; \
1041 volatile unsigned long _res; \
1042 _argvec[0] = (unsigned long)_orig.nraddr; \
1043 _argvec[1] = (unsigned long)(arg1); \
1044 _argvec[2] = (unsigned long)(arg2); \
1045 _argvec[3] = (unsigned long)(arg3); \
1046 _argvec[4] = (unsigned long)(arg4); \
1047 _argvec[5] = (unsigned long)(arg5); \
1048 _argvec[6] = (unsigned long)(arg6); \
1049 _argvec[7] = (unsigned long)(arg7); \
1050 _argvec[8] = (unsigned long)(arg8); \
1051 _argvec[9] = (unsigned long)(arg9); \
1052 _argvec[10] = (unsigned long)(arg10); \
1053 _argvec[11] = (unsigned long)(arg11); \
1054 __asm__ volatile( \
1055 "pushl 44(%%eax)\n\t" \
1056 "pushl 40(%%eax)\n\t" \
1057 "pushl 36(%%eax)\n\t" \
1058 "pushl 32(%%eax)\n\t" \
1059 "pushl 28(%%eax)\n\t" \
1060 "pushl 24(%%eax)\n\t" \
1061 "pushl 20(%%eax)\n\t" \
1062 "pushl 16(%%eax)\n\t" \
1063 "pushl 12(%%eax)\n\t" \
1064 "pushl 8(%%eax)\n\t" \
1065 "pushl 4(%%eax)\n\t" \
1066 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1067 VALGRIND_CALL_NOREDIR_EAX \
1068 "addl $44, %%esp\n" \
1069 : /*out*/ "=a" (_res) \
1070 : /*in*/ "a" (&_argvec[0]) \
1071 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1072 ); \
1073 lval = (__typeof__(lval)) _res; \
1074 } while (0)
1075
1076#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1077 arg6,arg7,arg8,arg9,arg10, \
1078 arg11,arg12) \
1079 do { \
1080 volatile OrigFn _orig = (orig); \
1081 volatile unsigned long _argvec[13]; \
1082 volatile unsigned long _res; \
1083 _argvec[0] = (unsigned long)_orig.nraddr; \
1084 _argvec[1] = (unsigned long)(arg1); \
1085 _argvec[2] = (unsigned long)(arg2); \
1086 _argvec[3] = (unsigned long)(arg3); \
1087 _argvec[4] = (unsigned long)(arg4); \
1088 _argvec[5] = (unsigned long)(arg5); \
1089 _argvec[6] = (unsigned long)(arg6); \
1090 _argvec[7] = (unsigned long)(arg7); \
1091 _argvec[8] = (unsigned long)(arg8); \
1092 _argvec[9] = (unsigned long)(arg9); \
1093 _argvec[10] = (unsigned long)(arg10); \
1094 _argvec[11] = (unsigned long)(arg11); \
1095 _argvec[12] = (unsigned long)(arg12); \
1096 __asm__ volatile( \
1097 "pushl 48(%%eax)\n\t" \
1098 "pushl 44(%%eax)\n\t" \
1099 "pushl 40(%%eax)\n\t" \
1100 "pushl 36(%%eax)\n\t" \
1101 "pushl 32(%%eax)\n\t" \
1102 "pushl 28(%%eax)\n\t" \
1103 "pushl 24(%%eax)\n\t" \
1104 "pushl 20(%%eax)\n\t" \
1105 "pushl 16(%%eax)\n\t" \
1106 "pushl 12(%%eax)\n\t" \
1107 "pushl 8(%%eax)\n\t" \
1108 "pushl 4(%%eax)\n\t" \
1109 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1110 VALGRIND_CALL_NOREDIR_EAX \
1111 "addl $48, %%esp\n" \
1112 : /*out*/ "=a" (_res) \
1113 : /*in*/ "a" (&_argvec[0]) \
1114 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1115 ); \
1116 lval = (__typeof__(lval)) _res; \
1117 } while (0)
1118
1119#endif /* PLAT_x86_linux || PLAT_x86_darwin */
1120
1121/* ------------------------ amd64-{linux,darwin} --------------- */
1122
1123#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
1124
1125/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1126
1127/* These regs are trashed by the hidden call. */
1128#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1129 "rdi", "r8", "r9", "r10", "r11"
1130
1131/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1132 long) == 8. */
1133
1134/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1135 macros. In order not to trash the stack redzone, we need to drop
1136 %rsp by 128 before the hidden call, and restore afterwards. The
1137 nastyness is that it is only by luck that the stack still appears
1138 to be unwindable during the hidden call - since then the behaviour
1139 of any routine using this macro does not match what the CFI data
1140 says. Sigh.
1141
1142 Why is this important? Imagine that a wrapper has a stack
1143 allocated local, and passes to the hidden call, a pointer to it.
1144 Because gcc does not know about the hidden call, it may allocate
1145 that local in the redzone. Unfortunately the hidden call may then
1146 trash it before it comes to use it. So we must step clear of the
1147 redzone, for the duration of the hidden call, to make it safe.
1148
1149 Probably the same problem afflicts the other redzone-style ABIs too
1150 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1151 self describing (none of this CFI nonsense) so at least messing
1152 with the stack pointer doesn't give a danger of non-unwindable
1153 stack. */
1154
1155#define CALL_FN_W_v(lval, orig) \
1156 do { \
1157 volatile OrigFn _orig = (orig); \
1158 volatile unsigned long _argvec[1]; \
1159 volatile unsigned long _res; \
1160 _argvec[0] = (unsigned long)_orig.nraddr; \
1161 __asm__ volatile( \
1162 "subq $128,%%rsp\n\t" \
1163 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1164 VALGRIND_CALL_NOREDIR_RAX \
1165 "addq $128,%%rsp\n\t" \
1166 : /*out*/ "=a" (_res) \
1167 : /*in*/ "a" (&_argvec[0]) \
1168 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1169 ); \
1170 lval = (__typeof__(lval)) _res; \
1171 } while (0)
1172
1173#define CALL_FN_W_W(lval, orig, arg1) \
1174 do { \
1175 volatile OrigFn _orig = (orig); \
1176 volatile unsigned long _argvec[2]; \
1177 volatile unsigned long _res; \
1178 _argvec[0] = (unsigned long)_orig.nraddr; \
1179 _argvec[1] = (unsigned long)(arg1); \
1180 __asm__ volatile( \
1181 "subq $128,%%rsp\n\t" \
1182 "movq 8(%%rax), %%rdi\n\t" \
1183 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1184 VALGRIND_CALL_NOREDIR_RAX \
1185 "addq $128,%%rsp\n\t" \
1186 : /*out*/ "=a" (_res) \
1187 : /*in*/ "a" (&_argvec[0]) \
1188 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1189 ); \
1190 lval = (__typeof__(lval)) _res; \
1191 } while (0)
1192
1193#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1194 do { \
1195 volatile OrigFn _orig = (orig); \
1196 volatile unsigned long _argvec[3]; \
1197 volatile unsigned long _res; \
1198 _argvec[0] = (unsigned long)_orig.nraddr; \
1199 _argvec[1] = (unsigned long)(arg1); \
1200 _argvec[2] = (unsigned long)(arg2); \
1201 __asm__ volatile( \
1202 "subq $128,%%rsp\n\t" \
1203 "movq 16(%%rax), %%rsi\n\t" \
1204 "movq 8(%%rax), %%rdi\n\t" \
1205 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1206 VALGRIND_CALL_NOREDIR_RAX \
1207 "addq $128,%%rsp\n\t" \
1208 : /*out*/ "=a" (_res) \
1209 : /*in*/ "a" (&_argvec[0]) \
1210 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1211 ); \
1212 lval = (__typeof__(lval)) _res; \
1213 } while (0)
1214
1215#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1216 do { \
1217 volatile OrigFn _orig = (orig); \
1218 volatile unsigned long _argvec[4]; \
1219 volatile unsigned long _res; \
1220 _argvec[0] = (unsigned long)_orig.nraddr; \
1221 _argvec[1] = (unsigned long)(arg1); \
1222 _argvec[2] = (unsigned long)(arg2); \
1223 _argvec[3] = (unsigned long)(arg3); \
1224 __asm__ volatile( \
1225 "subq $128,%%rsp\n\t" \
1226 "movq 24(%%rax), %%rdx\n\t" \
1227 "movq 16(%%rax), %%rsi\n\t" \
1228 "movq 8(%%rax), %%rdi\n\t" \
1229 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1230 VALGRIND_CALL_NOREDIR_RAX \
1231 "addq $128,%%rsp\n\t" \
1232 : /*out*/ "=a" (_res) \
1233 : /*in*/ "a" (&_argvec[0]) \
1234 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1235 ); \
1236 lval = (__typeof__(lval)) _res; \
1237 } while (0)
1238
1239#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1240 do { \
1241 volatile OrigFn _orig = (orig); \
1242 volatile unsigned long _argvec[5]; \
1243 volatile unsigned long _res; \
1244 _argvec[0] = (unsigned long)_orig.nraddr; \
1245 _argvec[1] = (unsigned long)(arg1); \
1246 _argvec[2] = (unsigned long)(arg2); \
1247 _argvec[3] = (unsigned long)(arg3); \
1248 _argvec[4] = (unsigned long)(arg4); \
1249 __asm__ volatile( \
1250 "subq $128,%%rsp\n\t" \
1251 "movq 32(%%rax), %%rcx\n\t" \
1252 "movq 24(%%rax), %%rdx\n\t" \
1253 "movq 16(%%rax), %%rsi\n\t" \
1254 "movq 8(%%rax), %%rdi\n\t" \
1255 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1256 VALGRIND_CALL_NOREDIR_RAX \
1257 "addq $128,%%rsp\n\t" \
1258 : /*out*/ "=a" (_res) \
1259 : /*in*/ "a" (&_argvec[0]) \
1260 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1261 ); \
1262 lval = (__typeof__(lval)) _res; \
1263 } while (0)
1264
1265#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1266 do { \
1267 volatile OrigFn _orig = (orig); \
1268 volatile unsigned long _argvec[6]; \
1269 volatile unsigned long _res; \
1270 _argvec[0] = (unsigned long)_orig.nraddr; \
1271 _argvec[1] = (unsigned long)(arg1); \
1272 _argvec[2] = (unsigned long)(arg2); \
1273 _argvec[3] = (unsigned long)(arg3); \
1274 _argvec[4] = (unsigned long)(arg4); \
1275 _argvec[5] = (unsigned long)(arg5); \
1276 __asm__ volatile( \
1277 "subq $128,%%rsp\n\t" \
1278 "movq 40(%%rax), %%r8\n\t" \
1279 "movq 32(%%rax), %%rcx\n\t" \
1280 "movq 24(%%rax), %%rdx\n\t" \
1281 "movq 16(%%rax), %%rsi\n\t" \
1282 "movq 8(%%rax), %%rdi\n\t" \
1283 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1284 VALGRIND_CALL_NOREDIR_RAX \
1285 "addq $128,%%rsp\n\t" \
1286 : /*out*/ "=a" (_res) \
1287 : /*in*/ "a" (&_argvec[0]) \
1288 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1289 ); \
1290 lval = (__typeof__(lval)) _res; \
1291 } while (0)
1292
1293#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1294 do { \
1295 volatile OrigFn _orig = (orig); \
1296 volatile unsigned long _argvec[7]; \
1297 volatile unsigned long _res; \
1298 _argvec[0] = (unsigned long)_orig.nraddr; \
1299 _argvec[1] = (unsigned long)(arg1); \
1300 _argvec[2] = (unsigned long)(arg2); \
1301 _argvec[3] = (unsigned long)(arg3); \
1302 _argvec[4] = (unsigned long)(arg4); \
1303 _argvec[5] = (unsigned long)(arg5); \
1304 _argvec[6] = (unsigned long)(arg6); \
1305 __asm__ volatile( \
1306 "subq $128,%%rsp\n\t" \
1307 "movq 48(%%rax), %%r9\n\t" \
1308 "movq 40(%%rax), %%r8\n\t" \
1309 "movq 32(%%rax), %%rcx\n\t" \
1310 "movq 24(%%rax), %%rdx\n\t" \
1311 "movq 16(%%rax), %%rsi\n\t" \
1312 "movq 8(%%rax), %%rdi\n\t" \
1313 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1314 "addq $128,%%rsp\n\t" \
1315 VALGRIND_CALL_NOREDIR_RAX \
1316 : /*out*/ "=a" (_res) \
1317 : /*in*/ "a" (&_argvec[0]) \
1318 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1319 ); \
1320 lval = (__typeof__(lval)) _res; \
1321 } while (0)
1322
1323#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1324 arg7) \
1325 do { \
1326 volatile OrigFn _orig = (orig); \
1327 volatile unsigned long _argvec[8]; \
1328 volatile unsigned long _res; \
1329 _argvec[0] = (unsigned long)_orig.nraddr; \
1330 _argvec[1] = (unsigned long)(arg1); \
1331 _argvec[2] = (unsigned long)(arg2); \
1332 _argvec[3] = (unsigned long)(arg3); \
1333 _argvec[4] = (unsigned long)(arg4); \
1334 _argvec[5] = (unsigned long)(arg5); \
1335 _argvec[6] = (unsigned long)(arg6); \
1336 _argvec[7] = (unsigned long)(arg7); \
1337 __asm__ volatile( \
1338 "subq $128,%%rsp\n\t" \
1339 "pushq 56(%%rax)\n\t" \
1340 "movq 48(%%rax), %%r9\n\t" \
1341 "movq 40(%%rax), %%r8\n\t" \
1342 "movq 32(%%rax), %%rcx\n\t" \
1343 "movq 24(%%rax), %%rdx\n\t" \
1344 "movq 16(%%rax), %%rsi\n\t" \
1345 "movq 8(%%rax), %%rdi\n\t" \
1346 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1347 VALGRIND_CALL_NOREDIR_RAX \
1348 "addq $8, %%rsp\n" \
1349 "addq $128,%%rsp\n\t" \
1350 : /*out*/ "=a" (_res) \
1351 : /*in*/ "a" (&_argvec[0]) \
1352 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1353 ); \
1354 lval = (__typeof__(lval)) _res; \
1355 } while (0)
1356
1357#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1358 arg7,arg8) \
1359 do { \
1360 volatile OrigFn _orig = (orig); \
1361 volatile unsigned long _argvec[9]; \
1362 volatile unsigned long _res; \
1363 _argvec[0] = (unsigned long)_orig.nraddr; \
1364 _argvec[1] = (unsigned long)(arg1); \
1365 _argvec[2] = (unsigned long)(arg2); \
1366 _argvec[3] = (unsigned long)(arg3); \
1367 _argvec[4] = (unsigned long)(arg4); \
1368 _argvec[5] = (unsigned long)(arg5); \
1369 _argvec[6] = (unsigned long)(arg6); \
1370 _argvec[7] = (unsigned long)(arg7); \
1371 _argvec[8] = (unsigned long)(arg8); \
1372 __asm__ volatile( \
1373 "subq $128,%%rsp\n\t" \
1374 "pushq 64(%%rax)\n\t" \
1375 "pushq 56(%%rax)\n\t" \
1376 "movq 48(%%rax), %%r9\n\t" \
1377 "movq 40(%%rax), %%r8\n\t" \
1378 "movq 32(%%rax), %%rcx\n\t" \
1379 "movq 24(%%rax), %%rdx\n\t" \
1380 "movq 16(%%rax), %%rsi\n\t" \
1381 "movq 8(%%rax), %%rdi\n\t" \
1382 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1383 VALGRIND_CALL_NOREDIR_RAX \
1384 "addq $16, %%rsp\n" \
1385 "addq $128,%%rsp\n\t" \
1386 : /*out*/ "=a" (_res) \
1387 : /*in*/ "a" (&_argvec[0]) \
1388 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1389 ); \
1390 lval = (__typeof__(lval)) _res; \
1391 } while (0)
1392
1393#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1394 arg7,arg8,arg9) \
1395 do { \
1396 volatile OrigFn _orig = (orig); \
1397 volatile unsigned long _argvec[10]; \
1398 volatile unsigned long _res; \
1399 _argvec[0] = (unsigned long)_orig.nraddr; \
1400 _argvec[1] = (unsigned long)(arg1); \
1401 _argvec[2] = (unsigned long)(arg2); \
1402 _argvec[3] = (unsigned long)(arg3); \
1403 _argvec[4] = (unsigned long)(arg4); \
1404 _argvec[5] = (unsigned long)(arg5); \
1405 _argvec[6] = (unsigned long)(arg6); \
1406 _argvec[7] = (unsigned long)(arg7); \
1407 _argvec[8] = (unsigned long)(arg8); \
1408 _argvec[9] = (unsigned long)(arg9); \
1409 __asm__ volatile( \
1410 "subq $128,%%rsp\n\t" \
1411 "pushq 72(%%rax)\n\t" \
1412 "pushq 64(%%rax)\n\t" \
1413 "pushq 56(%%rax)\n\t" \
1414 "movq 48(%%rax), %%r9\n\t" \
1415 "movq 40(%%rax), %%r8\n\t" \
1416 "movq 32(%%rax), %%rcx\n\t" \
1417 "movq 24(%%rax), %%rdx\n\t" \
1418 "movq 16(%%rax), %%rsi\n\t" \
1419 "movq 8(%%rax), %%rdi\n\t" \
1420 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1421 VALGRIND_CALL_NOREDIR_RAX \
1422 "addq $24, %%rsp\n" \
1423 "addq $128,%%rsp\n\t" \
1424 : /*out*/ "=a" (_res) \
1425 : /*in*/ "a" (&_argvec[0]) \
1426 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1427 ); \
1428 lval = (__typeof__(lval)) _res; \
1429 } while (0)
1430
1431#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1432 arg7,arg8,arg9,arg10) \
1433 do { \
1434 volatile OrigFn _orig = (orig); \
1435 volatile unsigned long _argvec[11]; \
1436 volatile unsigned long _res; \
1437 _argvec[0] = (unsigned long)_orig.nraddr; \
1438 _argvec[1] = (unsigned long)(arg1); \
1439 _argvec[2] = (unsigned long)(arg2); \
1440 _argvec[3] = (unsigned long)(arg3); \
1441 _argvec[4] = (unsigned long)(arg4); \
1442 _argvec[5] = (unsigned long)(arg5); \
1443 _argvec[6] = (unsigned long)(arg6); \
1444 _argvec[7] = (unsigned long)(arg7); \
1445 _argvec[8] = (unsigned long)(arg8); \
1446 _argvec[9] = (unsigned long)(arg9); \
1447 _argvec[10] = (unsigned long)(arg10); \
1448 __asm__ volatile( \
1449 "subq $128,%%rsp\n\t" \
1450 "pushq 80(%%rax)\n\t" \
1451 "pushq 72(%%rax)\n\t" \
1452 "pushq 64(%%rax)\n\t" \
1453 "pushq 56(%%rax)\n\t" \
1454 "movq 48(%%rax), %%r9\n\t" \
1455 "movq 40(%%rax), %%r8\n\t" \
1456 "movq 32(%%rax), %%rcx\n\t" \
1457 "movq 24(%%rax), %%rdx\n\t" \
1458 "movq 16(%%rax), %%rsi\n\t" \
1459 "movq 8(%%rax), %%rdi\n\t" \
1460 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1461 VALGRIND_CALL_NOREDIR_RAX \
1462 "addq $32, %%rsp\n" \
1463 "addq $128,%%rsp\n\t" \
1464 : /*out*/ "=a" (_res) \
1465 : /*in*/ "a" (&_argvec[0]) \
1466 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1467 ); \
1468 lval = (__typeof__(lval)) _res; \
1469 } while (0)
1470
1471#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1472 arg7,arg8,arg9,arg10,arg11) \
1473 do { \
1474 volatile OrigFn _orig = (orig); \
1475 volatile unsigned long _argvec[12]; \
1476 volatile unsigned long _res; \
1477 _argvec[0] = (unsigned long)_orig.nraddr; \
1478 _argvec[1] = (unsigned long)(arg1); \
1479 _argvec[2] = (unsigned long)(arg2); \
1480 _argvec[3] = (unsigned long)(arg3); \
1481 _argvec[4] = (unsigned long)(arg4); \
1482 _argvec[5] = (unsigned long)(arg5); \
1483 _argvec[6] = (unsigned long)(arg6); \
1484 _argvec[7] = (unsigned long)(arg7); \
1485 _argvec[8] = (unsigned long)(arg8); \
1486 _argvec[9] = (unsigned long)(arg9); \
1487 _argvec[10] = (unsigned long)(arg10); \
1488 _argvec[11] = (unsigned long)(arg11); \
1489 __asm__ volatile( \
1490 "subq $128,%%rsp\n\t" \
1491 "pushq 88(%%rax)\n\t" \
1492 "pushq 80(%%rax)\n\t" \
1493 "pushq 72(%%rax)\n\t" \
1494 "pushq 64(%%rax)\n\t" \
1495 "pushq 56(%%rax)\n\t" \
1496 "movq 48(%%rax), %%r9\n\t" \
1497 "movq 40(%%rax), %%r8\n\t" \
1498 "movq 32(%%rax), %%rcx\n\t" \
1499 "movq 24(%%rax), %%rdx\n\t" \
1500 "movq 16(%%rax), %%rsi\n\t" \
1501 "movq 8(%%rax), %%rdi\n\t" \
1502 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1503 VALGRIND_CALL_NOREDIR_RAX \
1504 "addq $40, %%rsp\n" \
1505 "addq $128,%%rsp\n\t" \
1506 : /*out*/ "=a" (_res) \
1507 : /*in*/ "a" (&_argvec[0]) \
1508 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1509 ); \
1510 lval = (__typeof__(lval)) _res; \
1511 } while (0)
1512
1513#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1514 arg7,arg8,arg9,arg10,arg11,arg12) \
1515 do { \
1516 volatile OrigFn _orig = (orig); \
1517 volatile unsigned long _argvec[13]; \
1518 volatile unsigned long _res; \
1519 _argvec[0] = (unsigned long)_orig.nraddr; \
1520 _argvec[1] = (unsigned long)(arg1); \
1521 _argvec[2] = (unsigned long)(arg2); \
1522 _argvec[3] = (unsigned long)(arg3); \
1523 _argvec[4] = (unsigned long)(arg4); \
1524 _argvec[5] = (unsigned long)(arg5); \
1525 _argvec[6] = (unsigned long)(arg6); \
1526 _argvec[7] = (unsigned long)(arg7); \
1527 _argvec[8] = (unsigned long)(arg8); \
1528 _argvec[9] = (unsigned long)(arg9); \
1529 _argvec[10] = (unsigned long)(arg10); \
1530 _argvec[11] = (unsigned long)(arg11); \
1531 _argvec[12] = (unsigned long)(arg12); \
1532 __asm__ volatile( \
1533 "subq $128,%%rsp\n\t" \
1534 "pushq 96(%%rax)\n\t" \
1535 "pushq 88(%%rax)\n\t" \
1536 "pushq 80(%%rax)\n\t" \
1537 "pushq 72(%%rax)\n\t" \
1538 "pushq 64(%%rax)\n\t" \
1539 "pushq 56(%%rax)\n\t" \
1540 "movq 48(%%rax), %%r9\n\t" \
1541 "movq 40(%%rax), %%r8\n\t" \
1542 "movq 32(%%rax), %%rcx\n\t" \
1543 "movq 24(%%rax), %%rdx\n\t" \
1544 "movq 16(%%rax), %%rsi\n\t" \
1545 "movq 8(%%rax), %%rdi\n\t" \
1546 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1547 VALGRIND_CALL_NOREDIR_RAX \
1548 "addq $48, %%rsp\n" \
1549 "addq $128,%%rsp\n\t" \
1550 : /*out*/ "=a" (_res) \
1551 : /*in*/ "a" (&_argvec[0]) \
1552 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1553 ); \
1554 lval = (__typeof__(lval)) _res; \
1555 } while (0)
1556
1557#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
1558
1559/* ------------------------ ppc32-linux ------------------------ */
1560
1561#if defined(PLAT_ppc32_linux)
1562
1563/* This is useful for finding out about the on-stack stuff:
1564
1565 extern int f9 ( int,int,int,int,int,int,int,int,int );
1566 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1567 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1568 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1569
1570 int g9 ( void ) {
1571 return f9(11,22,33,44,55,66,77,88,99);
1572 }
1573 int g10 ( void ) {
1574 return f10(11,22,33,44,55,66,77,88,99,110);
1575 }
1576 int g11 ( void ) {
1577 return f11(11,22,33,44,55,66,77,88,99,110,121);
1578 }
1579 int g12 ( void ) {
1580 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1581 }
1582*/
1583
1584/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1585
1586/* These regs are trashed by the hidden call. */
1587#define __CALLER_SAVED_REGS \
1588 "lr", "ctr", "xer", \
1589 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1590 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1591 "r11", "r12", "r13"
1592
1593/* These CALL_FN_ macros assume that on ppc32-linux,
1594 sizeof(unsigned long) == 4. */
1595
1596#define CALL_FN_W_v(lval, orig) \
1597 do { \
1598 volatile OrigFn _orig = (orig); \
1599 volatile unsigned long _argvec[1]; \
1600 volatile unsigned long _res; \
1601 _argvec[0] = (unsigned long)_orig.nraddr; \
1602 __asm__ volatile( \
1603 "mr 11,%1\n\t" \
1604 "lwz 11,0(11)\n\t" /* target->r11 */ \
1605 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1606 "mr %0,3" \
1607 : /*out*/ "=r" (_res) \
1608 : /*in*/ "r" (&_argvec[0]) \
1609 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1610 ); \
1611 lval = (__typeof__(lval)) _res; \
1612 } while (0)
1613
1614#define CALL_FN_W_W(lval, orig, arg1) \
1615 do { \
1616 volatile OrigFn _orig = (orig); \
1617 volatile unsigned long _argvec[2]; \
1618 volatile unsigned long _res; \
1619 _argvec[0] = (unsigned long)_orig.nraddr; \
1620 _argvec[1] = (unsigned long)arg1; \
1621 __asm__ volatile( \
1622 "mr 11,%1\n\t" \
1623 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1624 "lwz 11,0(11)\n\t" /* target->r11 */ \
1625 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1626 "mr %0,3" \
1627 : /*out*/ "=r" (_res) \
1628 : /*in*/ "r" (&_argvec[0]) \
1629 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1630 ); \
1631 lval = (__typeof__(lval)) _res; \
1632 } while (0)
1633
1634#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1635 do { \
1636 volatile OrigFn _orig = (orig); \
1637 volatile unsigned long _argvec[3]; \
1638 volatile unsigned long _res; \
1639 _argvec[0] = (unsigned long)_orig.nraddr; \
1640 _argvec[1] = (unsigned long)arg1; \
1641 _argvec[2] = (unsigned long)arg2; \
1642 __asm__ volatile( \
1643 "mr 11,%1\n\t" \
1644 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1645 "lwz 4,8(11)\n\t" \
1646 "lwz 11,0(11)\n\t" /* target->r11 */ \
1647 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1648 "mr %0,3" \
1649 : /*out*/ "=r" (_res) \
1650 : /*in*/ "r" (&_argvec[0]) \
1651 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1652 ); \
1653 lval = (__typeof__(lval)) _res; \
1654 } while (0)
1655
1656#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1657 do { \
1658 volatile OrigFn _orig = (orig); \
1659 volatile unsigned long _argvec[4]; \
1660 volatile unsigned long _res; \
1661 _argvec[0] = (unsigned long)_orig.nraddr; \
1662 _argvec[1] = (unsigned long)arg1; \
1663 _argvec[2] = (unsigned long)arg2; \
1664 _argvec[3] = (unsigned long)arg3; \
1665 __asm__ volatile( \
1666 "mr 11,%1\n\t" \
1667 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1668 "lwz 4,8(11)\n\t" \
1669 "lwz 5,12(11)\n\t" \
1670 "lwz 11,0(11)\n\t" /* target->r11 */ \
1671 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1672 "mr %0,3" \
1673 : /*out*/ "=r" (_res) \
1674 : /*in*/ "r" (&_argvec[0]) \
1675 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1676 ); \
1677 lval = (__typeof__(lval)) _res; \
1678 } while (0)
1679
1680#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1681 do { \
1682 volatile OrigFn _orig = (orig); \
1683 volatile unsigned long _argvec[5]; \
1684 volatile unsigned long _res; \
1685 _argvec[0] = (unsigned long)_orig.nraddr; \
1686 _argvec[1] = (unsigned long)arg1; \
1687 _argvec[2] = (unsigned long)arg2; \
1688 _argvec[3] = (unsigned long)arg3; \
1689 _argvec[4] = (unsigned long)arg4; \
1690 __asm__ volatile( \
1691 "mr 11,%1\n\t" \
1692 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1693 "lwz 4,8(11)\n\t" \
1694 "lwz 5,12(11)\n\t" \
1695 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1696 "lwz 11,0(11)\n\t" /* target->r11 */ \
1697 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1698 "mr %0,3" \
1699 : /*out*/ "=r" (_res) \
1700 : /*in*/ "r" (&_argvec[0]) \
1701 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1702 ); \
1703 lval = (__typeof__(lval)) _res; \
1704 } while (0)
1705
1706#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1707 do { \
1708 volatile OrigFn _orig = (orig); \
1709 volatile unsigned long _argvec[6]; \
1710 volatile unsigned long _res; \
1711 _argvec[0] = (unsigned long)_orig.nraddr; \
1712 _argvec[1] = (unsigned long)arg1; \
1713 _argvec[2] = (unsigned long)arg2; \
1714 _argvec[3] = (unsigned long)arg3; \
1715 _argvec[4] = (unsigned long)arg4; \
1716 _argvec[5] = (unsigned long)arg5; \
1717 __asm__ volatile( \
1718 "mr 11,%1\n\t" \
1719 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1720 "lwz 4,8(11)\n\t" \
1721 "lwz 5,12(11)\n\t" \
1722 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1723 "lwz 7,20(11)\n\t" \
1724 "lwz 11,0(11)\n\t" /* target->r11 */ \
1725 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1726 "mr %0,3" \
1727 : /*out*/ "=r" (_res) \
1728 : /*in*/ "r" (&_argvec[0]) \
1729 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1730 ); \
1731 lval = (__typeof__(lval)) _res; \
1732 } while (0)
1733
1734#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1735 do { \
1736 volatile OrigFn _orig = (orig); \
1737 volatile unsigned long _argvec[7]; \
1738 volatile unsigned long _res; \
1739 _argvec[0] = (unsigned long)_orig.nraddr; \
1740 _argvec[1] = (unsigned long)arg1; \
1741 _argvec[2] = (unsigned long)arg2; \
1742 _argvec[3] = (unsigned long)arg3; \
1743 _argvec[4] = (unsigned long)arg4; \
1744 _argvec[5] = (unsigned long)arg5; \
1745 _argvec[6] = (unsigned long)arg6; \
1746 __asm__ volatile( \
1747 "mr 11,%1\n\t" \
1748 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1749 "lwz 4,8(11)\n\t" \
1750 "lwz 5,12(11)\n\t" \
1751 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1752 "lwz 7,20(11)\n\t" \
1753 "lwz 8,24(11)\n\t" \
1754 "lwz 11,0(11)\n\t" /* target->r11 */ \
1755 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1756 "mr %0,3" \
1757 : /*out*/ "=r" (_res) \
1758 : /*in*/ "r" (&_argvec[0]) \
1759 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1760 ); \
1761 lval = (__typeof__(lval)) _res; \
1762 } while (0)
1763
1764#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1765 arg7) \
1766 do { \
1767 volatile OrigFn _orig = (orig); \
1768 volatile unsigned long _argvec[8]; \
1769 volatile unsigned long _res; \
1770 _argvec[0] = (unsigned long)_orig.nraddr; \
1771 _argvec[1] = (unsigned long)arg1; \
1772 _argvec[2] = (unsigned long)arg2; \
1773 _argvec[3] = (unsigned long)arg3; \
1774 _argvec[4] = (unsigned long)arg4; \
1775 _argvec[5] = (unsigned long)arg5; \
1776 _argvec[6] = (unsigned long)arg6; \
1777 _argvec[7] = (unsigned long)arg7; \
1778 __asm__ volatile( \
1779 "mr 11,%1\n\t" \
1780 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1781 "lwz 4,8(11)\n\t" \
1782 "lwz 5,12(11)\n\t" \
1783 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1784 "lwz 7,20(11)\n\t" \
1785 "lwz 8,24(11)\n\t" \
1786 "lwz 9,28(11)\n\t" \
1787 "lwz 11,0(11)\n\t" /* target->r11 */ \
1788 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1789 "mr %0,3" \
1790 : /*out*/ "=r" (_res) \
1791 : /*in*/ "r" (&_argvec[0]) \
1792 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1793 ); \
1794 lval = (__typeof__(lval)) _res; \
1795 } while (0)
1796
1797#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1798 arg7,arg8) \
1799 do { \
1800 volatile OrigFn _orig = (orig); \
1801 volatile unsigned long _argvec[9]; \
1802 volatile unsigned long _res; \
1803 _argvec[0] = (unsigned long)_orig.nraddr; \
1804 _argvec[1] = (unsigned long)arg1; \
1805 _argvec[2] = (unsigned long)arg2; \
1806 _argvec[3] = (unsigned long)arg3; \
1807 _argvec[4] = (unsigned long)arg4; \
1808 _argvec[5] = (unsigned long)arg5; \
1809 _argvec[6] = (unsigned long)arg6; \
1810 _argvec[7] = (unsigned long)arg7; \
1811 _argvec[8] = (unsigned long)arg8; \
1812 __asm__ volatile( \
1813 "mr 11,%1\n\t" \
1814 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1815 "lwz 4,8(11)\n\t" \
1816 "lwz 5,12(11)\n\t" \
1817 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1818 "lwz 7,20(11)\n\t" \
1819 "lwz 8,24(11)\n\t" \
1820 "lwz 9,28(11)\n\t" \
1821 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1822 "lwz 11,0(11)\n\t" /* target->r11 */ \
1823 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1824 "mr %0,3" \
1825 : /*out*/ "=r" (_res) \
1826 : /*in*/ "r" (&_argvec[0]) \
1827 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1828 ); \
1829 lval = (__typeof__(lval)) _res; \
1830 } while (0)
1831
1832#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1833 arg7,arg8,arg9) \
1834 do { \
1835 volatile OrigFn _orig = (orig); \
1836 volatile unsigned long _argvec[10]; \
1837 volatile unsigned long _res; \
1838 _argvec[0] = (unsigned long)_orig.nraddr; \
1839 _argvec[1] = (unsigned long)arg1; \
1840 _argvec[2] = (unsigned long)arg2; \
1841 _argvec[3] = (unsigned long)arg3; \
1842 _argvec[4] = (unsigned long)arg4; \
1843 _argvec[5] = (unsigned long)arg5; \
1844 _argvec[6] = (unsigned long)arg6; \
1845 _argvec[7] = (unsigned long)arg7; \
1846 _argvec[8] = (unsigned long)arg8; \
1847 _argvec[9] = (unsigned long)arg9; \
1848 __asm__ volatile( \
1849 "mr 11,%1\n\t" \
1850 "addi 1,1,-16\n\t" \
1851 /* arg9 */ \
1852 "lwz 3,36(11)\n\t" \
1853 "stw 3,8(1)\n\t" \
1854 /* args1-8 */ \
1855 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1856 "lwz 4,8(11)\n\t" \
1857 "lwz 5,12(11)\n\t" \
1858 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1859 "lwz 7,20(11)\n\t" \
1860 "lwz 8,24(11)\n\t" \
1861 "lwz 9,28(11)\n\t" \
1862 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1863 "lwz 11,0(11)\n\t" /* target->r11 */ \
1864 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1865 "addi 1,1,16\n\t" \
1866 "mr %0,3" \
1867 : /*out*/ "=r" (_res) \
1868 : /*in*/ "r" (&_argvec[0]) \
1869 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1870 ); \
1871 lval = (__typeof__(lval)) _res; \
1872 } while (0)
1873
1874#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1875 arg7,arg8,arg9,arg10) \
1876 do { \
1877 volatile OrigFn _orig = (orig); \
1878 volatile unsigned long _argvec[11]; \
1879 volatile unsigned long _res; \
1880 _argvec[0] = (unsigned long)_orig.nraddr; \
1881 _argvec[1] = (unsigned long)arg1; \
1882 _argvec[2] = (unsigned long)arg2; \
1883 _argvec[3] = (unsigned long)arg3; \
1884 _argvec[4] = (unsigned long)arg4; \
1885 _argvec[5] = (unsigned long)arg5; \
1886 _argvec[6] = (unsigned long)arg6; \
1887 _argvec[7] = (unsigned long)arg7; \
1888 _argvec[8] = (unsigned long)arg8; \
1889 _argvec[9] = (unsigned long)arg9; \
1890 _argvec[10] = (unsigned long)arg10; \
1891 __asm__ volatile( \
1892 "mr 11,%1\n\t" \
1893 "addi 1,1,-16\n\t" \
1894 /* arg10 */ \
1895 "lwz 3,40(11)\n\t" \
1896 "stw 3,12(1)\n\t" \
1897 /* arg9 */ \
1898 "lwz 3,36(11)\n\t" \
1899 "stw 3,8(1)\n\t" \
1900 /* args1-8 */ \
1901 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1902 "lwz 4,8(11)\n\t" \
1903 "lwz 5,12(11)\n\t" \
1904 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1905 "lwz 7,20(11)\n\t" \
1906 "lwz 8,24(11)\n\t" \
1907 "lwz 9,28(11)\n\t" \
1908 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1909 "lwz 11,0(11)\n\t" /* target->r11 */ \
1910 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1911 "addi 1,1,16\n\t" \
1912 "mr %0,3" \
1913 : /*out*/ "=r" (_res) \
1914 : /*in*/ "r" (&_argvec[0]) \
1915 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1916 ); \
1917 lval = (__typeof__(lval)) _res; \
1918 } while (0)
1919
1920#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1921 arg7,arg8,arg9,arg10,arg11) \
1922 do { \
1923 volatile OrigFn _orig = (orig); \
1924 volatile unsigned long _argvec[12]; \
1925 volatile unsigned long _res; \
1926 _argvec[0] = (unsigned long)_orig.nraddr; \
1927 _argvec[1] = (unsigned long)arg1; \
1928 _argvec[2] = (unsigned long)arg2; \
1929 _argvec[3] = (unsigned long)arg3; \
1930 _argvec[4] = (unsigned long)arg4; \
1931 _argvec[5] = (unsigned long)arg5; \
1932 _argvec[6] = (unsigned long)arg6; \
1933 _argvec[7] = (unsigned long)arg7; \
1934 _argvec[8] = (unsigned long)arg8; \
1935 _argvec[9] = (unsigned long)arg9; \
1936 _argvec[10] = (unsigned long)arg10; \
1937 _argvec[11] = (unsigned long)arg11; \
1938 __asm__ volatile( \
1939 "mr 11,%1\n\t" \
1940 "addi 1,1,-32\n\t" \
1941 /* arg11 */ \
1942 "lwz 3,44(11)\n\t" \
1943 "stw 3,16(1)\n\t" \
1944 /* arg10 */ \
1945 "lwz 3,40(11)\n\t" \
1946 "stw 3,12(1)\n\t" \
1947 /* arg9 */ \
1948 "lwz 3,36(11)\n\t" \
1949 "stw 3,8(1)\n\t" \
1950 /* args1-8 */ \
1951 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1952 "lwz 4,8(11)\n\t" \
1953 "lwz 5,12(11)\n\t" \
1954 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1955 "lwz 7,20(11)\n\t" \
1956 "lwz 8,24(11)\n\t" \
1957 "lwz 9,28(11)\n\t" \
1958 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1959 "lwz 11,0(11)\n\t" /* target->r11 */ \
1960 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1961 "addi 1,1,32\n\t" \
1962 "mr %0,3" \
1963 : /*out*/ "=r" (_res) \
1964 : /*in*/ "r" (&_argvec[0]) \
1965 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1966 ); \
1967 lval = (__typeof__(lval)) _res; \
1968 } while (0)
1969
1970#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1971 arg7,arg8,arg9,arg10,arg11,arg12) \
1972 do { \
1973 volatile OrigFn _orig = (orig); \
1974 volatile unsigned long _argvec[13]; \
1975 volatile unsigned long _res; \
1976 _argvec[0] = (unsigned long)_orig.nraddr; \
1977 _argvec[1] = (unsigned long)arg1; \
1978 _argvec[2] = (unsigned long)arg2; \
1979 _argvec[3] = (unsigned long)arg3; \
1980 _argvec[4] = (unsigned long)arg4; \
1981 _argvec[5] = (unsigned long)arg5; \
1982 _argvec[6] = (unsigned long)arg6; \
1983 _argvec[7] = (unsigned long)arg7; \
1984 _argvec[8] = (unsigned long)arg8; \
1985 _argvec[9] = (unsigned long)arg9; \
1986 _argvec[10] = (unsigned long)arg10; \
1987 _argvec[11] = (unsigned long)arg11; \
1988 _argvec[12] = (unsigned long)arg12; \
1989 __asm__ volatile( \
1990 "mr 11,%1\n\t" \
1991 "addi 1,1,-32\n\t" \
1992 /* arg12 */ \
1993 "lwz 3,48(11)\n\t" \
1994 "stw 3,20(1)\n\t" \
1995 /* arg11 */ \
1996 "lwz 3,44(11)\n\t" \
1997 "stw 3,16(1)\n\t" \
1998 /* arg10 */ \
1999 "lwz 3,40(11)\n\t" \
2000 "stw 3,12(1)\n\t" \
2001 /* arg9 */ \
2002 "lwz 3,36(11)\n\t" \
2003 "stw 3,8(1)\n\t" \
2004 /* args1-8 */ \
2005 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2006 "lwz 4,8(11)\n\t" \
2007 "lwz 5,12(11)\n\t" \
2008 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2009 "lwz 7,20(11)\n\t" \
2010 "lwz 8,24(11)\n\t" \
2011 "lwz 9,28(11)\n\t" \
2012 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2013 "lwz 11,0(11)\n\t" /* target->r11 */ \
2014 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2015 "addi 1,1,32\n\t" \
2016 "mr %0,3" \
2017 : /*out*/ "=r" (_res) \
2018 : /*in*/ "r" (&_argvec[0]) \
2019 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2020 ); \
2021 lval = (__typeof__(lval)) _res; \
2022 } while (0)
2023
2024#endif /* PLAT_ppc32_linux */
2025
2026/* ------------------------ ppc64-linux ------------------------ */
2027
2028#if defined(PLAT_ppc64_linux)
2029
2030/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2031
2032/* These regs are trashed by the hidden call. */
2033#define __CALLER_SAVED_REGS \
2034 "lr", "ctr", "xer", \
2035 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2036 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2037 "r11", "r12", "r13"
2038
2039/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2040 long) == 8. */
2041
2042#define CALL_FN_W_v(lval, orig) \
2043 do { \
2044 volatile OrigFn _orig = (orig); \
2045 volatile unsigned long _argvec[3+0]; \
2046 volatile unsigned long _res; \
2047 /* _argvec[0] holds current r2 across the call */ \
2048 _argvec[1] = (unsigned long)_orig.r2; \
2049 _argvec[2] = (unsigned long)_orig.nraddr; \
2050 __asm__ volatile( \
2051 "mr 11,%1\n\t" \
2052 "std 2,-16(11)\n\t" /* save tocptr */ \
2053 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2054 "ld 11, 0(11)\n\t" /* target->r11 */ \
2055 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2056 "mr 11,%1\n\t" \
2057 "mr %0,3\n\t" \
2058 "ld 2,-16(11)" /* restore tocptr */ \
2059 : /*out*/ "=r" (_res) \
2060 : /*in*/ "r" (&_argvec[2]) \
2061 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2062 ); \
2063 lval = (__typeof__(lval)) _res; \
2064 } while (0)
2065
2066#define CALL_FN_W_W(lval, orig, arg1) \
2067 do { \
2068 volatile OrigFn _orig = (orig); \
2069 volatile unsigned long _argvec[3+1]; \
2070 volatile unsigned long _res; \
2071 /* _argvec[0] holds current r2 across the call */ \
2072 _argvec[1] = (unsigned long)_orig.r2; \
2073 _argvec[2] = (unsigned long)_orig.nraddr; \
2074 _argvec[2+1] = (unsigned long)arg1; \
2075 __asm__ volatile( \
2076 "mr 11,%1\n\t" \
2077 "std 2,-16(11)\n\t" /* save tocptr */ \
2078 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2079 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2080 "ld 11, 0(11)\n\t" /* target->r11 */ \
2081 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2082 "mr 11,%1\n\t" \
2083 "mr %0,3\n\t" \
2084 "ld 2,-16(11)" /* restore tocptr */ \
2085 : /*out*/ "=r" (_res) \
2086 : /*in*/ "r" (&_argvec[2]) \
2087 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2088 ); \
2089 lval = (__typeof__(lval)) _res; \
2090 } while (0)
2091
2092#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2093 do { \
2094 volatile OrigFn _orig = (orig); \
2095 volatile unsigned long _argvec[3+2]; \
2096 volatile unsigned long _res; \
2097 /* _argvec[0] holds current r2 across the call */ \
2098 _argvec[1] = (unsigned long)_orig.r2; \
2099 _argvec[2] = (unsigned long)_orig.nraddr; \
2100 _argvec[2+1] = (unsigned long)arg1; \
2101 _argvec[2+2] = (unsigned long)arg2; \
2102 __asm__ volatile( \
2103 "mr 11,%1\n\t" \
2104 "std 2,-16(11)\n\t" /* save tocptr */ \
2105 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2106 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2107 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2108 "ld 11, 0(11)\n\t" /* target->r11 */ \
2109 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2110 "mr 11,%1\n\t" \
2111 "mr %0,3\n\t" \
2112 "ld 2,-16(11)" /* restore tocptr */ \
2113 : /*out*/ "=r" (_res) \
2114 : /*in*/ "r" (&_argvec[2]) \
2115 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2116 ); \
2117 lval = (__typeof__(lval)) _res; \
2118 } while (0)
2119
2120#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2121 do { \
2122 volatile OrigFn _orig = (orig); \
2123 volatile unsigned long _argvec[3+3]; \
2124 volatile unsigned long _res; \
2125 /* _argvec[0] holds current r2 across the call */ \
2126 _argvec[1] = (unsigned long)_orig.r2; \
2127 _argvec[2] = (unsigned long)_orig.nraddr; \
2128 _argvec[2+1] = (unsigned long)arg1; \
2129 _argvec[2+2] = (unsigned long)arg2; \
2130 _argvec[2+3] = (unsigned long)arg3; \
2131 __asm__ volatile( \
2132 "mr 11,%1\n\t" \
2133 "std 2,-16(11)\n\t" /* save tocptr */ \
2134 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2135 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2136 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2137 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2138 "ld 11, 0(11)\n\t" /* target->r11 */ \
2139 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2140 "mr 11,%1\n\t" \
2141 "mr %0,3\n\t" \
2142 "ld 2,-16(11)" /* restore tocptr */ \
2143 : /*out*/ "=r" (_res) \
2144 : /*in*/ "r" (&_argvec[2]) \
2145 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2146 ); \
2147 lval = (__typeof__(lval)) _res; \
2148 } while (0)
2149
2150#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2151 do { \
2152 volatile OrigFn _orig = (orig); \
2153 volatile unsigned long _argvec[3+4]; \
2154 volatile unsigned long _res; \
2155 /* _argvec[0] holds current r2 across the call */ \
2156 _argvec[1] = (unsigned long)_orig.r2; \
2157 _argvec[2] = (unsigned long)_orig.nraddr; \
2158 _argvec[2+1] = (unsigned long)arg1; \
2159 _argvec[2+2] = (unsigned long)arg2; \
2160 _argvec[2+3] = (unsigned long)arg3; \
2161 _argvec[2+4] = (unsigned long)arg4; \
2162 __asm__ volatile( \
2163 "mr 11,%1\n\t" \
2164 "std 2,-16(11)\n\t" /* save tocptr */ \
2165 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2166 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2167 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2168 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2169 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2170 "ld 11, 0(11)\n\t" /* target->r11 */ \
2171 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2172 "mr 11,%1\n\t" \
2173 "mr %0,3\n\t" \
2174 "ld 2,-16(11)" /* restore tocptr */ \
2175 : /*out*/ "=r" (_res) \
2176 : /*in*/ "r" (&_argvec[2]) \
2177 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2178 ); \
2179 lval = (__typeof__(lval)) _res; \
2180 } while (0)
2181
2182#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2183 do { \
2184 volatile OrigFn _orig = (orig); \
2185 volatile unsigned long _argvec[3+5]; \
2186 volatile unsigned long _res; \
2187 /* _argvec[0] holds current r2 across the call */ \
2188 _argvec[1] = (unsigned long)_orig.r2; \
2189 _argvec[2] = (unsigned long)_orig.nraddr; \
2190 _argvec[2+1] = (unsigned long)arg1; \
2191 _argvec[2+2] = (unsigned long)arg2; \
2192 _argvec[2+3] = (unsigned long)arg3; \
2193 _argvec[2+4] = (unsigned long)arg4; \
2194 _argvec[2+5] = (unsigned long)arg5; \
2195 __asm__ volatile( \
2196 "mr 11,%1\n\t" \
2197 "std 2,-16(11)\n\t" /* save tocptr */ \
2198 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2199 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2200 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2201 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2202 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2203 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2204 "ld 11, 0(11)\n\t" /* target->r11 */ \
2205 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2206 "mr 11,%1\n\t" \
2207 "mr %0,3\n\t" \
2208 "ld 2,-16(11)" /* restore tocptr */ \
2209 : /*out*/ "=r" (_res) \
2210 : /*in*/ "r" (&_argvec[2]) \
2211 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2212 ); \
2213 lval = (__typeof__(lval)) _res; \
2214 } while (0)
2215
2216#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2217 do { \
2218 volatile OrigFn _orig = (orig); \
2219 volatile unsigned long _argvec[3+6]; \
2220 volatile unsigned long _res; \
2221 /* _argvec[0] holds current r2 across the call */ \
2222 _argvec[1] = (unsigned long)_orig.r2; \
2223 _argvec[2] = (unsigned long)_orig.nraddr; \
2224 _argvec[2+1] = (unsigned long)arg1; \
2225 _argvec[2+2] = (unsigned long)arg2; \
2226 _argvec[2+3] = (unsigned long)arg3; \
2227 _argvec[2+4] = (unsigned long)arg4; \
2228 _argvec[2+5] = (unsigned long)arg5; \
2229 _argvec[2+6] = (unsigned long)arg6; \
2230 __asm__ volatile( \
2231 "mr 11,%1\n\t" \
2232 "std 2,-16(11)\n\t" /* save tocptr */ \
2233 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2234 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2235 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2236 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2237 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2238 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2239 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2240 "ld 11, 0(11)\n\t" /* target->r11 */ \
2241 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2242 "mr 11,%1\n\t" \
2243 "mr %0,3\n\t" \
2244 "ld 2,-16(11)" /* restore tocptr */ \
2245 : /*out*/ "=r" (_res) \
2246 : /*in*/ "r" (&_argvec[2]) \
2247 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2248 ); \
2249 lval = (__typeof__(lval)) _res; \
2250 } while (0)
2251
2252#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2253 arg7) \
2254 do { \
2255 volatile OrigFn _orig = (orig); \
2256 volatile unsigned long _argvec[3+7]; \
2257 volatile unsigned long _res; \
2258 /* _argvec[0] holds current r2 across the call */ \
2259 _argvec[1] = (unsigned long)_orig.r2; \
2260 _argvec[2] = (unsigned long)_orig.nraddr; \
2261 _argvec[2+1] = (unsigned long)arg1; \
2262 _argvec[2+2] = (unsigned long)arg2; \
2263 _argvec[2+3] = (unsigned long)arg3; \
2264 _argvec[2+4] = (unsigned long)arg4; \
2265 _argvec[2+5] = (unsigned long)arg5; \
2266 _argvec[2+6] = (unsigned long)arg6; \
2267 _argvec[2+7] = (unsigned long)arg7; \
2268 __asm__ volatile( \
2269 "mr 11,%1\n\t" \
2270 "std 2,-16(11)\n\t" /* save tocptr */ \
2271 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2272 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2273 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2274 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2275 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2276 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2277 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2278 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2279 "ld 11, 0(11)\n\t" /* target->r11 */ \
2280 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2281 "mr 11,%1\n\t" \
2282 "mr %0,3\n\t" \
2283 "ld 2,-16(11)" /* restore tocptr */ \
2284 : /*out*/ "=r" (_res) \
2285 : /*in*/ "r" (&_argvec[2]) \
2286 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2287 ); \
2288 lval = (__typeof__(lval)) _res; \
2289 } while (0)
2290
2291#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2292 arg7,arg8) \
2293 do { \
2294 volatile OrigFn _orig = (orig); \
2295 volatile unsigned long _argvec[3+8]; \
2296 volatile unsigned long _res; \
2297 /* _argvec[0] holds current r2 across the call */ \
2298 _argvec[1] = (unsigned long)_orig.r2; \
2299 _argvec[2] = (unsigned long)_orig.nraddr; \
2300 _argvec[2+1] = (unsigned long)arg1; \
2301 _argvec[2+2] = (unsigned long)arg2; \
2302 _argvec[2+3] = (unsigned long)arg3; \
2303 _argvec[2+4] = (unsigned long)arg4; \
2304 _argvec[2+5] = (unsigned long)arg5; \
2305 _argvec[2+6] = (unsigned long)arg6; \
2306 _argvec[2+7] = (unsigned long)arg7; \
2307 _argvec[2+8] = (unsigned long)arg8; \
2308 __asm__ volatile( \
2309 "mr 11,%1\n\t" \
2310 "std 2,-16(11)\n\t" /* save tocptr */ \
2311 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2312 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2313 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2314 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2315 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2316 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2317 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2318 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2319 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2320 "ld 11, 0(11)\n\t" /* target->r11 */ \
2321 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2322 "mr 11,%1\n\t" \
2323 "mr %0,3\n\t" \
2324 "ld 2,-16(11)" /* restore tocptr */ \
2325 : /*out*/ "=r" (_res) \
2326 : /*in*/ "r" (&_argvec[2]) \
2327 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2328 ); \
2329 lval = (__typeof__(lval)) _res; \
2330 } while (0)
2331
2332#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2333 arg7,arg8,arg9) \
2334 do { \
2335 volatile OrigFn _orig = (orig); \
2336 volatile unsigned long _argvec[3+9]; \
2337 volatile unsigned long _res; \
2338 /* _argvec[0] holds current r2 across the call */ \
2339 _argvec[1] = (unsigned long)_orig.r2; \
2340 _argvec[2] = (unsigned long)_orig.nraddr; \
2341 _argvec[2+1] = (unsigned long)arg1; \
2342 _argvec[2+2] = (unsigned long)arg2; \
2343 _argvec[2+3] = (unsigned long)arg3; \
2344 _argvec[2+4] = (unsigned long)arg4; \
2345 _argvec[2+5] = (unsigned long)arg5; \
2346 _argvec[2+6] = (unsigned long)arg6; \
2347 _argvec[2+7] = (unsigned long)arg7; \
2348 _argvec[2+8] = (unsigned long)arg8; \
2349 _argvec[2+9] = (unsigned long)arg9; \
2350 __asm__ volatile( \
2351 "mr 11,%1\n\t" \
2352 "std 2,-16(11)\n\t" /* save tocptr */ \
2353 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2354 "addi 1,1,-128\n\t" /* expand stack frame */ \
2355 /* arg9 */ \
2356 "ld 3,72(11)\n\t" \
2357 "std 3,112(1)\n\t" \
2358 /* args1-8 */ \
2359 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2360 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2361 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2362 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2363 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2364 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2365 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2366 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2367 "ld 11, 0(11)\n\t" /* target->r11 */ \
2368 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2369 "mr 11,%1\n\t" \
2370 "mr %0,3\n\t" \
2371 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2372 "addi 1,1,128" /* restore frame */ \
2373 : /*out*/ "=r" (_res) \
2374 : /*in*/ "r" (&_argvec[2]) \
2375 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2376 ); \
2377 lval = (__typeof__(lval)) _res; \
2378 } while (0)
2379
2380#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2381 arg7,arg8,arg9,arg10) \
2382 do { \
2383 volatile OrigFn _orig = (orig); \
2384 volatile unsigned long _argvec[3+10]; \
2385 volatile unsigned long _res; \
2386 /* _argvec[0] holds current r2 across the call */ \
2387 _argvec[1] = (unsigned long)_orig.r2; \
2388 _argvec[2] = (unsigned long)_orig.nraddr; \
2389 _argvec[2+1] = (unsigned long)arg1; \
2390 _argvec[2+2] = (unsigned long)arg2; \
2391 _argvec[2+3] = (unsigned long)arg3; \
2392 _argvec[2+4] = (unsigned long)arg4; \
2393 _argvec[2+5] = (unsigned long)arg5; \
2394 _argvec[2+6] = (unsigned long)arg6; \
2395 _argvec[2+7] = (unsigned long)arg7; \
2396 _argvec[2+8] = (unsigned long)arg8; \
2397 _argvec[2+9] = (unsigned long)arg9; \
2398 _argvec[2+10] = (unsigned long)arg10; \
2399 __asm__ volatile( \
2400 "mr 11,%1\n\t" \
2401 "std 2,-16(11)\n\t" /* save tocptr */ \
2402 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2403 "addi 1,1,-128\n\t" /* expand stack frame */ \
2404 /* arg10 */ \
2405 "ld 3,80(11)\n\t" \
2406 "std 3,120(1)\n\t" \
2407 /* arg9 */ \
2408 "ld 3,72(11)\n\t" \
2409 "std 3,112(1)\n\t" \
2410 /* args1-8 */ \
2411 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2412 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2413 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2414 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2415 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2416 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2417 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2418 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2419 "ld 11, 0(11)\n\t" /* target->r11 */ \
2420 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2421 "mr 11,%1\n\t" \
2422 "mr %0,3\n\t" \
2423 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2424 "addi 1,1,128" /* restore frame */ \
2425 : /*out*/ "=r" (_res) \
2426 : /*in*/ "r" (&_argvec[2]) \
2427 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2428 ); \
2429 lval = (__typeof__(lval)) _res; \
2430 } while (0)
2431
2432#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2433 arg7,arg8,arg9,arg10,arg11) \
2434 do { \
2435 volatile OrigFn _orig = (orig); \
2436 volatile unsigned long _argvec[3+11]; \
2437 volatile unsigned long _res; \
2438 /* _argvec[0] holds current r2 across the call */ \
2439 _argvec[1] = (unsigned long)_orig.r2; \
2440 _argvec[2] = (unsigned long)_orig.nraddr; \
2441 _argvec[2+1] = (unsigned long)arg1; \
2442 _argvec[2+2] = (unsigned long)arg2; \
2443 _argvec[2+3] = (unsigned long)arg3; \
2444 _argvec[2+4] = (unsigned long)arg4; \
2445 _argvec[2+5] = (unsigned long)arg5; \
2446 _argvec[2+6] = (unsigned long)arg6; \
2447 _argvec[2+7] = (unsigned long)arg7; \
2448 _argvec[2+8] = (unsigned long)arg8; \
2449 _argvec[2+9] = (unsigned long)arg9; \
2450 _argvec[2+10] = (unsigned long)arg10; \
2451 _argvec[2+11] = (unsigned long)arg11; \
2452 __asm__ volatile( \
2453 "mr 11,%1\n\t" \
2454 "std 2,-16(11)\n\t" /* save tocptr */ \
2455 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2456 "addi 1,1,-144\n\t" /* expand stack frame */ \
2457 /* arg11 */ \
2458 "ld 3,88(11)\n\t" \
2459 "std 3,128(1)\n\t" \
2460 /* arg10 */ \
2461 "ld 3,80(11)\n\t" \
2462 "std 3,120(1)\n\t" \
2463 /* arg9 */ \
2464 "ld 3,72(11)\n\t" \
2465 "std 3,112(1)\n\t" \
2466 /* args1-8 */ \
2467 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2468 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2469 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2470 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2471 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2472 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2473 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2474 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2475 "ld 11, 0(11)\n\t" /* target->r11 */ \
2476 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2477 "mr 11,%1\n\t" \
2478 "mr %0,3\n\t" \
2479 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2480 "addi 1,1,144" /* restore frame */ \
2481 : /*out*/ "=r" (_res) \
2482 : /*in*/ "r" (&_argvec[2]) \
2483 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2484 ); \
2485 lval = (__typeof__(lval)) _res; \
2486 } while (0)
2487
2488#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2489 arg7,arg8,arg9,arg10,arg11,arg12) \
2490 do { \
2491 volatile OrigFn _orig = (orig); \
2492 volatile unsigned long _argvec[3+12]; \
2493 volatile unsigned long _res; \
2494 /* _argvec[0] holds current r2 across the call */ \
2495 _argvec[1] = (unsigned long)_orig.r2; \
2496 _argvec[2] = (unsigned long)_orig.nraddr; \
2497 _argvec[2+1] = (unsigned long)arg1; \
2498 _argvec[2+2] = (unsigned long)arg2; \
2499 _argvec[2+3] = (unsigned long)arg3; \
2500 _argvec[2+4] = (unsigned long)arg4; \
2501 _argvec[2+5] = (unsigned long)arg5; \
2502 _argvec[2+6] = (unsigned long)arg6; \
2503 _argvec[2+7] = (unsigned long)arg7; \
2504 _argvec[2+8] = (unsigned long)arg8; \
2505 _argvec[2+9] = (unsigned long)arg9; \
2506 _argvec[2+10] = (unsigned long)arg10; \
2507 _argvec[2+11] = (unsigned long)arg11; \
2508 _argvec[2+12] = (unsigned long)arg12; \
2509 __asm__ volatile( \
2510 "mr 11,%1\n\t" \
2511 "std 2,-16(11)\n\t" /* save tocptr */ \
2512 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2513 "addi 1,1,-144\n\t" /* expand stack frame */ \
2514 /* arg12 */ \
2515 "ld 3,96(11)\n\t" \
2516 "std 3,136(1)\n\t" \
2517 /* arg11 */ \
2518 "ld 3,88(11)\n\t" \
2519 "std 3,128(1)\n\t" \
2520 /* arg10 */ \
2521 "ld 3,80(11)\n\t" \
2522 "std 3,120(1)\n\t" \
2523 /* arg9 */ \
2524 "ld 3,72(11)\n\t" \
2525 "std 3,112(1)\n\t" \
2526 /* args1-8 */ \
2527 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2528 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2529 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2530 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2531 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2532 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2533 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2534 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2535 "ld 11, 0(11)\n\t" /* target->r11 */ \
2536 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2537 "mr 11,%1\n\t" \
2538 "mr %0,3\n\t" \
2539 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2540 "addi 1,1,144" /* restore frame */ \
2541 : /*out*/ "=r" (_res) \
2542 : /*in*/ "r" (&_argvec[2]) \
2543 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2544 ); \
2545 lval = (__typeof__(lval)) _res; \
2546 } while (0)
2547
2548#endif /* PLAT_ppc64_linux */
2549
2550/* ------------------------- arm-linux ------------------------- */
2551
2552#if defined(PLAT_arm_linux)
2553
2554/* These regs are trashed by the hidden call. */
2555#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2556
2557/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2558 long) == 4. */
2559
2560#define CALL_FN_W_v(lval, orig) \
2561 do { \
2562 volatile OrigFn _orig = (orig); \
2563 volatile unsigned long _argvec[1]; \
2564 volatile unsigned long _res; \
2565 _argvec[0] = (unsigned long)_orig.nraddr; \
2566 __asm__ volatile( \
2567 "ldr r4, [%1] \n\t" /* target->r4 */ \
2568 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2569 "mov %0, r0\n" \
2570 : /*out*/ "=r" (_res) \
2571 : /*in*/ "0" (&_argvec[0]) \
2572 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2573 ); \
2574 lval = (__typeof__(lval)) _res; \
2575 } while (0)
2576
2577#define CALL_FN_W_W(lval, orig, arg1) \
2578 do { \
2579 volatile OrigFn _orig = (orig); \
2580 volatile unsigned long _argvec[2]; \
2581 volatile unsigned long _res; \
2582 _argvec[0] = (unsigned long)_orig.nraddr; \
2583 _argvec[1] = (unsigned long)(arg1); \
2584 __asm__ volatile( \
2585 "ldr r0, [%1, #4] \n\t" \
2586 "ldr r4, [%1] \n\t" /* target->r4 */ \
2587 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2588 "mov %0, r0\n" \
2589 : /*out*/ "=r" (_res) \
2590 : /*in*/ "0" (&_argvec[0]) \
2591 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2592 ); \
2593 lval = (__typeof__(lval)) _res; \
2594 } while (0)
2595
2596#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2597 do { \
2598 volatile OrigFn _orig = (orig); \
2599 volatile unsigned long _argvec[3]; \
2600 volatile unsigned long _res; \
2601 _argvec[0] = (unsigned long)_orig.nraddr; \
2602 _argvec[1] = (unsigned long)(arg1); \
2603 _argvec[2] = (unsigned long)(arg2); \
2604 __asm__ volatile( \
2605 "ldr r0, [%1, #4] \n\t" \
2606 "ldr r1, [%1, #8] \n\t" \
2607 "ldr r4, [%1] \n\t" /* target->r4 */ \
2608 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2609 "mov %0, r0\n" \
2610 : /*out*/ "=r" (_res) \
2611 : /*in*/ "0" (&_argvec[0]) \
2612 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2613 ); \
2614 lval = (__typeof__(lval)) _res; \
2615 } while (0)
2616
2617#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2618 do { \
2619 volatile OrigFn _orig = (orig); \
2620 volatile unsigned long _argvec[4]; \
2621 volatile unsigned long _res; \
2622 _argvec[0] = (unsigned long)_orig.nraddr; \
2623 _argvec[1] = (unsigned long)(arg1); \
2624 _argvec[2] = (unsigned long)(arg2); \
2625 _argvec[3] = (unsigned long)(arg3); \
2626 __asm__ volatile( \
2627 "ldr r0, [%1, #4] \n\t" \
2628 "ldr r1, [%1, #8] \n\t" \
2629 "ldr r2, [%1, #12] \n\t" \
2630 "ldr r4, [%1] \n\t" /* target->r4 */ \
2631 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2632 "mov %0, r0\n" \
2633 : /*out*/ "=r" (_res) \
2634 : /*in*/ "0" (&_argvec[0]) \
2635 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2636 ); \
2637 lval = (__typeof__(lval)) _res; \
2638 } while (0)
2639
2640#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2641 do { \
2642 volatile OrigFn _orig = (orig); \
2643 volatile unsigned long _argvec[5]; \
2644 volatile unsigned long _res; \
2645 _argvec[0] = (unsigned long)_orig.nraddr; \
2646 _argvec[1] = (unsigned long)(arg1); \
2647 _argvec[2] = (unsigned long)(arg2); \
2648 _argvec[3] = (unsigned long)(arg3); \
2649 _argvec[4] = (unsigned long)(arg4); \
2650 __asm__ volatile( \
2651 "ldr r0, [%1, #4] \n\t" \
2652 "ldr r1, [%1, #8] \n\t" \
2653 "ldr r2, [%1, #12] \n\t" \
2654 "ldr r3, [%1, #16] \n\t" \
2655 "ldr r4, [%1] \n\t" /* target->r4 */ \
2656 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2657 "mov %0, r0" \
2658 : /*out*/ "=r" (_res) \
2659 : /*in*/ "0" (&_argvec[0]) \
2660 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2661 ); \
2662 lval = (__typeof__(lval)) _res; \
2663 } while (0)
2664
2665#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2666 do { \
2667 volatile OrigFn _orig = (orig); \
2668 volatile unsigned long _argvec[6]; \
2669 volatile unsigned long _res; \
2670 _argvec[0] = (unsigned long)_orig.nraddr; \
2671 _argvec[1] = (unsigned long)(arg1); \
2672 _argvec[2] = (unsigned long)(arg2); \
2673 _argvec[3] = (unsigned long)(arg3); \
2674 _argvec[4] = (unsigned long)(arg4); \
2675 _argvec[5] = (unsigned long)(arg5); \
2676 __asm__ volatile( \
2677 "ldr r0, [%1, #20] \n\t" \
2678 "push {r0} \n\t" \
2679 "ldr r0, [%1, #4] \n\t" \
2680 "ldr r1, [%1, #8] \n\t" \
2681 "ldr r2, [%1, #12] \n\t" \
2682 "ldr r3, [%1, #16] \n\t" \
2683 "ldr r4, [%1] \n\t" /* target->r4 */ \
2684 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2685 "add sp, sp, #4 \n\t" \
2686 "mov %0, r0" \
2687 : /*out*/ "=r" (_res) \
2688 : /*in*/ "0" (&_argvec[0]) \
2689 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2690 ); \
2691 lval = (__typeof__(lval)) _res; \
2692 } while (0)
2693
2694#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2695 do { \
2696 volatile OrigFn _orig = (orig); \
2697 volatile unsigned long _argvec[7]; \
2698 volatile unsigned long _res; \
2699 _argvec[0] = (unsigned long)_orig.nraddr; \
2700 _argvec[1] = (unsigned long)(arg1); \
2701 _argvec[2] = (unsigned long)(arg2); \
2702 _argvec[3] = (unsigned long)(arg3); \
2703 _argvec[4] = (unsigned long)(arg4); \
2704 _argvec[5] = (unsigned long)(arg5); \
2705 _argvec[6] = (unsigned long)(arg6); \
2706 __asm__ volatile( \
2707 "ldr r0, [%1, #20] \n\t" \
2708 "ldr r1, [%1, #24] \n\t" \
2709 "push {r0, r1} \n\t" \
2710 "ldr r0, [%1, #4] \n\t" \
2711 "ldr r1, [%1, #8] \n\t" \
2712 "ldr r2, [%1, #12] \n\t" \
2713 "ldr r3, [%1, #16] \n\t" \
2714 "ldr r4, [%1] \n\t" /* target->r4 */ \
2715 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2716 "add sp, sp, #8 \n\t" \
2717 "mov %0, r0" \
2718 : /*out*/ "=r" (_res) \
2719 : /*in*/ "0" (&_argvec[0]) \
2720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2721 ); \
2722 lval = (__typeof__(lval)) _res; \
2723 } while (0)
2724
2725#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2726 arg7) \
2727 do { \
2728 volatile OrigFn _orig = (orig); \
2729 volatile unsigned long _argvec[8]; \
2730 volatile unsigned long _res; \
2731 _argvec[0] = (unsigned long)_orig.nraddr; \
2732 _argvec[1] = (unsigned long)(arg1); \
2733 _argvec[2] = (unsigned long)(arg2); \
2734 _argvec[3] = (unsigned long)(arg3); \
2735 _argvec[4] = (unsigned long)(arg4); \
2736 _argvec[5] = (unsigned long)(arg5); \
2737 _argvec[6] = (unsigned long)(arg6); \
2738 _argvec[7] = (unsigned long)(arg7); \
2739 __asm__ volatile( \
2740 "ldr r0, [%1, #20] \n\t" \
2741 "ldr r1, [%1, #24] \n\t" \
2742 "ldr r2, [%1, #28] \n\t" \
2743 "push {r0, r1, r2} \n\t" \
2744 "ldr r0, [%1, #4] \n\t" \
2745 "ldr r1, [%1, #8] \n\t" \
2746 "ldr r2, [%1, #12] \n\t" \
2747 "ldr r3, [%1, #16] \n\t" \
2748 "ldr r4, [%1] \n\t" /* target->r4 */ \
2749 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2750 "add sp, sp, #12 \n\t" \
2751 "mov %0, r0" \
2752 : /*out*/ "=r" (_res) \
2753 : /*in*/ "0" (&_argvec[0]) \
2754 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2755 ); \
2756 lval = (__typeof__(lval)) _res; \
2757 } while (0)
2758
2759#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2760 arg7,arg8) \
2761 do { \
2762 volatile OrigFn _orig = (orig); \
2763 volatile unsigned long _argvec[9]; \
2764 volatile unsigned long _res; \
2765 _argvec[0] = (unsigned long)_orig.nraddr; \
2766 _argvec[1] = (unsigned long)(arg1); \
2767 _argvec[2] = (unsigned long)(arg2); \
2768 _argvec[3] = (unsigned long)(arg3); \
2769 _argvec[4] = (unsigned long)(arg4); \
2770 _argvec[5] = (unsigned long)(arg5); \
2771 _argvec[6] = (unsigned long)(arg6); \
2772 _argvec[7] = (unsigned long)(arg7); \
2773 _argvec[8] = (unsigned long)(arg8); \
2774 __asm__ volatile( \
2775 "ldr r0, [%1, #20] \n\t" \
2776 "ldr r1, [%1, #24] \n\t" \
2777 "ldr r2, [%1, #28] \n\t" \
2778 "ldr r3, [%1, #32] \n\t" \
2779 "push {r0, r1, r2, r3} \n\t" \
2780 "ldr r0, [%1, #4] \n\t" \
2781 "ldr r1, [%1, #8] \n\t" \
2782 "ldr r2, [%1, #12] \n\t" \
2783 "ldr r3, [%1, #16] \n\t" \
2784 "ldr r4, [%1] \n\t" /* target->r4 */ \
2785 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2786 "add sp, sp, #16 \n\t" \
2787 "mov %0, r0" \
2788 : /*out*/ "=r" (_res) \
2789 : /*in*/ "0" (&_argvec[0]) \
2790 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2791 ); \
2792 lval = (__typeof__(lval)) _res; \
2793 } while (0)
2794
2795#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2796 arg7,arg8,arg9) \
2797 do { \
2798 volatile OrigFn _orig = (orig); \
2799 volatile unsigned long _argvec[10]; \
2800 volatile unsigned long _res; \
2801 _argvec[0] = (unsigned long)_orig.nraddr; \
2802 _argvec[1] = (unsigned long)(arg1); \
2803 _argvec[2] = (unsigned long)(arg2); \
2804 _argvec[3] = (unsigned long)(arg3); \
2805 _argvec[4] = (unsigned long)(arg4); \
2806 _argvec[5] = (unsigned long)(arg5); \
2807 _argvec[6] = (unsigned long)(arg6); \
2808 _argvec[7] = (unsigned long)(arg7); \
2809 _argvec[8] = (unsigned long)(arg8); \
2810 _argvec[9] = (unsigned long)(arg9); \
2811 __asm__ volatile( \
2812 "ldr r0, [%1, #20] \n\t" \
2813 "ldr r1, [%1, #24] \n\t" \
2814 "ldr r2, [%1, #28] \n\t" \
2815 "ldr r3, [%1, #32] \n\t" \
2816 "ldr r4, [%1, #36] \n\t" \
2817 "push {r0, r1, r2, r3, r4} \n\t" \
2818 "ldr r0, [%1, #4] \n\t" \
2819 "ldr r1, [%1, #8] \n\t" \
2820 "ldr r2, [%1, #12] \n\t" \
2821 "ldr r3, [%1, #16] \n\t" \
2822 "ldr r4, [%1] \n\t" /* target->r4 */ \
2823 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2824 "add sp, sp, #20 \n\t" \
2825 "mov %0, r0" \
2826 : /*out*/ "=r" (_res) \
2827 : /*in*/ "0" (&_argvec[0]) \
2828 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2829 ); \
2830 lval = (__typeof__(lval)) _res; \
2831 } while (0)
2832
2833#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2834 arg7,arg8,arg9,arg10) \
2835 do { \
2836 volatile OrigFn _orig = (orig); \
2837 volatile unsigned long _argvec[11]; \
2838 volatile unsigned long _res; \
2839 _argvec[0] = (unsigned long)_orig.nraddr; \
2840 _argvec[1] = (unsigned long)(arg1); \
2841 _argvec[2] = (unsigned long)(arg2); \
2842 _argvec[3] = (unsigned long)(arg3); \
2843 _argvec[4] = (unsigned long)(arg4); \
2844 _argvec[5] = (unsigned long)(arg5); \
2845 _argvec[6] = (unsigned long)(arg6); \
2846 _argvec[7] = (unsigned long)(arg7); \
2847 _argvec[8] = (unsigned long)(arg8); \
2848 _argvec[9] = (unsigned long)(arg9); \
2849 _argvec[10] = (unsigned long)(arg10); \
2850 __asm__ volatile( \
2851 "ldr r0, [%1, #40] \n\t" \
2852 "push {r0} \n\t" \
2853 "ldr r0, [%1, #20] \n\t" \
2854 "ldr r1, [%1, #24] \n\t" \
2855 "ldr r2, [%1, #28] \n\t" \
2856 "ldr r3, [%1, #32] \n\t" \
2857 "ldr r4, [%1, #36] \n\t" \
2858 "push {r0, r1, r2, r3, r4} \n\t" \
2859 "ldr r0, [%1, #4] \n\t" \
2860 "ldr r1, [%1, #8] \n\t" \
2861 "ldr r2, [%1, #12] \n\t" \
2862 "ldr r3, [%1, #16] \n\t" \
2863 "ldr r4, [%1] \n\t" /* target->r4 */ \
2864 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2865 "add sp, sp, #24 \n\t" \
2866 "mov %0, r0" \
2867 : /*out*/ "=r" (_res) \
2868 : /*in*/ "0" (&_argvec[0]) \
2869 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2870 ); \
2871 lval = (__typeof__(lval)) _res; \
2872 } while (0)
2873
2874#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2875 arg6,arg7,arg8,arg9,arg10, \
2876 arg11) \
2877 do { \
2878 volatile OrigFn _orig = (orig); \
2879 volatile unsigned long _argvec[12]; \
2880 volatile unsigned long _res; \
2881 _argvec[0] = (unsigned long)_orig.nraddr; \
2882 _argvec[1] = (unsigned long)(arg1); \
2883 _argvec[2] = (unsigned long)(arg2); \
2884 _argvec[3] = (unsigned long)(arg3); \
2885 _argvec[4] = (unsigned long)(arg4); \
2886 _argvec[5] = (unsigned long)(arg5); \
2887 _argvec[6] = (unsigned long)(arg6); \
2888 _argvec[7] = (unsigned long)(arg7); \
2889 _argvec[8] = (unsigned long)(arg8); \
2890 _argvec[9] = (unsigned long)(arg9); \
2891 _argvec[10] = (unsigned long)(arg10); \
2892 _argvec[11] = (unsigned long)(arg11); \
2893 __asm__ volatile( \
2894 "ldr r0, [%1, #40] \n\t" \
2895 "ldr r1, [%1, #44] \n\t" \
2896 "push {r0, r1} \n\t" \
2897 "ldr r0, [%1, #20] \n\t" \
2898 "ldr r1, [%1, #24] \n\t" \
2899 "ldr r2, [%1, #28] \n\t" \
2900 "ldr r3, [%1, #32] \n\t" \
2901 "ldr r4, [%1, #36] \n\t" \
2902 "push {r0, r1, r2, r3, r4} \n\t" \
2903 "ldr r0, [%1, #4] \n\t" \
2904 "ldr r1, [%1, #8] \n\t" \
2905 "ldr r2, [%1, #12] \n\t" \
2906 "ldr r3, [%1, #16] \n\t" \
2907 "ldr r4, [%1] \n\t" /* target->r4 */ \
2908 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2909 "add sp, sp, #28 \n\t" \
2910 "mov %0, r0" \
2911 : /*out*/ "=r" (_res) \
2912 : /*in*/ "0" (&_argvec[0]) \
2913 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
2914 ); \
2915 lval = (__typeof__(lval)) _res; \
2916 } while (0)
2917
2918#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2919 arg6,arg7,arg8,arg9,arg10, \
2920 arg11,arg12) \
2921 do { \
2922 volatile OrigFn _orig = (orig); \
2923 volatile unsigned long _argvec[13]; \
2924 volatile unsigned long _res; \
2925 _argvec[0] = (unsigned long)_orig.nraddr; \
2926 _argvec[1] = (unsigned long)(arg1); \
2927 _argvec[2] = (unsigned long)(arg2); \
2928 _argvec[3] = (unsigned long)(arg3); \
2929 _argvec[4] = (unsigned long)(arg4); \
2930 _argvec[5] = (unsigned long)(arg5); \
2931 _argvec[6] = (unsigned long)(arg6); \
2932 _argvec[7] = (unsigned long)(arg7); \
2933 _argvec[8] = (unsigned long)(arg8); \
2934 _argvec[9] = (unsigned long)(arg9); \
2935 _argvec[10] = (unsigned long)(arg10); \
2936 _argvec[11] = (unsigned long)(arg11); \
2937 _argvec[12] = (unsigned long)(arg12); \
2938 __asm__ volatile( \
2939 "ldr r0, [%1, #40] \n\t" \
2940 "ldr r1, [%1, #44] \n\t" \
2941 "ldr r2, [%1, #48] \n\t" \
2942 "push {r0, r1, r2} \n\t" \
2943 "ldr r0, [%1, #20] \n\t" \
2944 "ldr r1, [%1, #24] \n\t" \
2945 "ldr r2, [%1, #28] \n\t" \
2946 "ldr r3, [%1, #32] \n\t" \
2947 "ldr r4, [%1, #36] \n\t" \
2948 "push {r0, r1, r2, r3, r4} \n\t" \
2949 "ldr r0, [%1, #4] \n\t" \
2950 "ldr r1, [%1, #8] \n\t" \
2951 "ldr r2, [%1, #12] \n\t" \
2952 "ldr r3, [%1, #16] \n\t" \
2953 "ldr r4, [%1] \n\t" /* target->r4 */ \
2954 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2955 "add sp, sp, #32 \n\t" \
2956 "mov %0, r0" \
2957 : /*out*/ "=r" (_res) \
2958 : /*in*/ "0" (&_argvec[0]) \
2959 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2960 ); \
2961 lval = (__typeof__(lval)) _res; \
2962 } while (0)
2963
2964#endif /* PLAT_arm_linux */
2965
2966/* ------------------------ ppc32-aix5 ------------------------- */
2967
2968#if defined(PLAT_ppc32_aix5)
2969
2970/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2971
2972/* These regs are trashed by the hidden call. */
2973#define __CALLER_SAVED_REGS \
2974 "lr", "ctr", "xer", \
2975 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2976 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2977 "r11", "r12", "r13"
2978
2979/* Expand the stack frame, copying enough info that unwinding
2980 still works. Trashes r3. */
2981
2982#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2983 "addi 1,1,-" #_n_fr "\n\t" \
2984 "lwz 3," #_n_fr "(1)\n\t" \
2985 "stw 3,0(1)\n\t"
2986
2987#define VG_CONTRACT_FRAME_BY(_n_fr) \
2988 "addi 1,1," #_n_fr "\n\t"
2989
2990/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2991 long) == 4. */
2992
2993#define CALL_FN_W_v(lval, orig) \
2994 do { \
2995 volatile OrigFn _orig = (orig); \
2996 volatile unsigned long _argvec[3+0]; \
2997 volatile unsigned long _res; \
2998 /* _argvec[0] holds current r2 across the call */ \
2999 _argvec[1] = (unsigned long)_orig.r2; \
3000 _argvec[2] = (unsigned long)_orig.nraddr; \
3001 __asm__ volatile( \
3002 "mr 11,%1\n\t" \
3003 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3004 "stw 2,-8(11)\n\t" /* save tocptr */ \
3005 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3006 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3007 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3008 "mr 11,%1\n\t" \
3009 "mr %0,3\n\t" \
3010 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3011 VG_CONTRACT_FRAME_BY(512) \
3012 : /*out*/ "=r" (_res) \
3013 : /*in*/ "r" (&_argvec[2]) \
3014 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3015 ); \
3016 lval = (__typeof__(lval)) _res; \
3017 } while (0)
3018
3019#define CALL_FN_W_W(lval, orig, arg1) \
3020 do { \
3021 volatile OrigFn _orig = (orig); \
3022 volatile unsigned long _argvec[3+1]; \
3023 volatile unsigned long _res; \
3024 /* _argvec[0] holds current r2 across the call */ \
3025 _argvec[1] = (unsigned long)_orig.r2; \
3026 _argvec[2] = (unsigned long)_orig.nraddr; \
3027 _argvec[2+1] = (unsigned long)arg1; \
3028 __asm__ volatile( \
3029 "mr 11,%1\n\t" \
3030 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3031 "stw 2,-8(11)\n\t" /* save tocptr */ \
3032 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3033 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3034 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3035 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3036 "mr 11,%1\n\t" \
3037 "mr %0,3\n\t" \
3038 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3039 VG_CONTRACT_FRAME_BY(512) \
3040 : /*out*/ "=r" (_res) \
3041 : /*in*/ "r" (&_argvec[2]) \
3042 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3043 ); \
3044 lval = (__typeof__(lval)) _res; \
3045 } while (0)
3046
3047#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3048 do { \
3049 volatile OrigFn _orig = (orig); \
3050 volatile unsigned long _argvec[3+2]; \
3051 volatile unsigned long _res; \
3052 /* _argvec[0] holds current r2 across the call */ \
3053 _argvec[1] = (unsigned long)_orig.r2; \
3054 _argvec[2] = (unsigned long)_orig.nraddr; \
3055 _argvec[2+1] = (unsigned long)arg1; \
3056 _argvec[2+2] = (unsigned long)arg2; \
3057 __asm__ volatile( \
3058 "mr 11,%1\n\t" \
3059 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3060 "stw 2,-8(11)\n\t" /* save tocptr */ \
3061 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3062 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3063 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3064 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3065 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3066 "mr 11,%1\n\t" \
3067 "mr %0,3\n\t" \
3068 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3069 VG_CONTRACT_FRAME_BY(512) \
3070 : /*out*/ "=r" (_res) \
3071 : /*in*/ "r" (&_argvec[2]) \
3072 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3073 ); \
3074 lval = (__typeof__(lval)) _res; \
3075 } while (0)
3076
3077#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3078 do { \
3079 volatile OrigFn _orig = (orig); \
3080 volatile unsigned long _argvec[3+3]; \
3081 volatile unsigned long _res; \
3082 /* _argvec[0] holds current r2 across the call */ \
3083 _argvec[1] = (unsigned long)_orig.r2; \
3084 _argvec[2] = (unsigned long)_orig.nraddr; \
3085 _argvec[2+1] = (unsigned long)arg1; \
3086 _argvec[2+2] = (unsigned long)arg2; \
3087 _argvec[2+3] = (unsigned long)arg3; \
3088 __asm__ volatile( \
3089 "mr 11,%1\n\t" \
3090 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3091 "stw 2,-8(11)\n\t" /* save tocptr */ \
3092 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3093 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3094 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3095 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3096 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3097 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3098 "mr 11,%1\n\t" \
3099 "mr %0,3\n\t" \
3100 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3101 VG_CONTRACT_FRAME_BY(512) \
3102 : /*out*/ "=r" (_res) \
3103 : /*in*/ "r" (&_argvec[2]) \
3104 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3105 ); \
3106 lval = (__typeof__(lval)) _res; \
3107 } while (0)
3108
3109#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3110 do { \
3111 volatile OrigFn _orig = (orig); \
3112 volatile unsigned long _argvec[3+4]; \
3113 volatile unsigned long _res; \
3114 /* _argvec[0] holds current r2 across the call */ \
3115 _argvec[1] = (unsigned long)_orig.r2; \
3116 _argvec[2] = (unsigned long)_orig.nraddr; \
3117 _argvec[2+1] = (unsigned long)arg1; \
3118 _argvec[2+2] = (unsigned long)arg2; \
3119 _argvec[2+3] = (unsigned long)arg3; \
3120 _argvec[2+4] = (unsigned long)arg4; \
3121 __asm__ volatile( \
3122 "mr 11,%1\n\t" \
3123 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3124 "stw 2,-8(11)\n\t" /* save tocptr */ \
3125 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3126 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3127 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3128 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3129 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3130 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3131 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3132 "mr 11,%1\n\t" \
3133 "mr %0,3\n\t" \
3134 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3135 VG_CONTRACT_FRAME_BY(512) \
3136 : /*out*/ "=r" (_res) \
3137 : /*in*/ "r" (&_argvec[2]) \
3138 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3139 ); \
3140 lval = (__typeof__(lval)) _res; \
3141 } while (0)
3142
3143#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3144 do { \
3145 volatile OrigFn _orig = (orig); \
3146 volatile unsigned long _argvec[3+5]; \
3147 volatile unsigned long _res; \
3148 /* _argvec[0] holds current r2 across the call */ \
3149 _argvec[1] = (unsigned long)_orig.r2; \
3150 _argvec[2] = (unsigned long)_orig.nraddr; \
3151 _argvec[2+1] = (unsigned long)arg1; \
3152 _argvec[2+2] = (unsigned long)arg2; \
3153 _argvec[2+3] = (unsigned long)arg3; \
3154 _argvec[2+4] = (unsigned long)arg4; \
3155 _argvec[2+5] = (unsigned long)arg5; \
3156 __asm__ volatile( \
3157 "mr 11,%1\n\t" \
3158 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3159 "stw 2,-8(11)\n\t" /* save tocptr */ \
3160 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3161 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3162 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3163 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3164 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3165 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3166 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3167 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3168 "mr 11,%1\n\t" \
3169 "mr %0,3\n\t" \
3170 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3171 VG_CONTRACT_FRAME_BY(512) \
3172 : /*out*/ "=r" (_res) \
3173 : /*in*/ "r" (&_argvec[2]) \
3174 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3175 ); \
3176 lval = (__typeof__(lval)) _res; \
3177 } while (0)
3178
3179#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3180 do { \
3181 volatile OrigFn _orig = (orig); \
3182 volatile unsigned long _argvec[3+6]; \
3183 volatile unsigned long _res; \
3184 /* _argvec[0] holds current r2 across the call */ \
3185 _argvec[1] = (unsigned long)_orig.r2; \
3186 _argvec[2] = (unsigned long)_orig.nraddr; \
3187 _argvec[2+1] = (unsigned long)arg1; \
3188 _argvec[2+2] = (unsigned long)arg2; \
3189 _argvec[2+3] = (unsigned long)arg3; \
3190 _argvec[2+4] = (unsigned long)arg4; \
3191 _argvec[2+5] = (unsigned long)arg5; \
3192 _argvec[2+6] = (unsigned long)arg6; \
3193 __asm__ volatile( \
3194 "mr 11,%1\n\t" \
3195 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3196 "stw 2,-8(11)\n\t" /* save tocptr */ \
3197 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3198 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3199 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3200 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3201 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3202 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3203 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3204 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3205 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3206 "mr 11,%1\n\t" \
3207 "mr %0,3\n\t" \
3208 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3209 VG_CONTRACT_FRAME_BY(512) \
3210 : /*out*/ "=r" (_res) \
3211 : /*in*/ "r" (&_argvec[2]) \
3212 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3213 ); \
3214 lval = (__typeof__(lval)) _res; \
3215 } while (0)
3216
3217#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3218 arg7) \
3219 do { \
3220 volatile OrigFn _orig = (orig); \
3221 volatile unsigned long _argvec[3+7]; \
3222 volatile unsigned long _res; \
3223 /* _argvec[0] holds current r2 across the call */ \
3224 _argvec[1] = (unsigned long)_orig.r2; \
3225 _argvec[2] = (unsigned long)_orig.nraddr; \
3226 _argvec[2+1] = (unsigned long)arg1; \
3227 _argvec[2+2] = (unsigned long)arg2; \
3228 _argvec[2+3] = (unsigned long)arg3; \
3229 _argvec[2+4] = (unsigned long)arg4; \
3230 _argvec[2+5] = (unsigned long)arg5; \
3231 _argvec[2+6] = (unsigned long)arg6; \
3232 _argvec[2+7] = (unsigned long)arg7; \
3233 __asm__ volatile( \
3234 "mr 11,%1\n\t" \
3235 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3236 "stw 2,-8(11)\n\t" /* save tocptr */ \
3237 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3238 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3239 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3240 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3241 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3242 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3243 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3244 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3245 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3246 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3247 "mr 11,%1\n\t" \
3248 "mr %0,3\n\t" \
3249 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3250 VG_CONTRACT_FRAME_BY(512) \
3251 : /*out*/ "=r" (_res) \
3252 : /*in*/ "r" (&_argvec[2]) \
3253 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3254 ); \
3255 lval = (__typeof__(lval)) _res; \
3256 } while (0)
3257
3258#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3259 arg7,arg8) \
3260 do { \
3261 volatile OrigFn _orig = (orig); \
3262 volatile unsigned long _argvec[3+8]; \
3263 volatile unsigned long _res; \
3264 /* _argvec[0] holds current r2 across the call */ \
3265 _argvec[1] = (unsigned long)_orig.r2; \
3266 _argvec[2] = (unsigned long)_orig.nraddr; \
3267 _argvec[2+1] = (unsigned long)arg1; \
3268 _argvec[2+2] = (unsigned long)arg2; \
3269 _argvec[2+3] = (unsigned long)arg3; \
3270 _argvec[2+4] = (unsigned long)arg4; \
3271 _argvec[2+5] = (unsigned long)arg5; \
3272 _argvec[2+6] = (unsigned long)arg6; \
3273 _argvec[2+7] = (unsigned long)arg7; \
3274 _argvec[2+8] = (unsigned long)arg8; \
3275 __asm__ volatile( \
3276 "mr 11,%1\n\t" \
3277 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3278 "stw 2,-8(11)\n\t" /* save tocptr */ \
3279 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3280 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3281 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3282 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3283 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3284 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3285 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3286 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3287 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3288 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3289 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3290 "mr 11,%1\n\t" \
3291 "mr %0,3\n\t" \
3292 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3293 VG_CONTRACT_FRAME_BY(512) \
3294 : /*out*/ "=r" (_res) \
3295 : /*in*/ "r" (&_argvec[2]) \
3296 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3297 ); \
3298 lval = (__typeof__(lval)) _res; \
3299 } while (0)
3300
3301#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3302 arg7,arg8,arg9) \
3303 do { \
3304 volatile OrigFn _orig = (orig); \
3305 volatile unsigned long _argvec[3+9]; \
3306 volatile unsigned long _res; \
3307 /* _argvec[0] holds current r2 across the call */ \
3308 _argvec[1] = (unsigned long)_orig.r2; \
3309 _argvec[2] = (unsigned long)_orig.nraddr; \
3310 _argvec[2+1] = (unsigned long)arg1; \
3311 _argvec[2+2] = (unsigned long)arg2; \
3312 _argvec[2+3] = (unsigned long)arg3; \
3313 _argvec[2+4] = (unsigned long)arg4; \
3314 _argvec[2+5] = (unsigned long)arg5; \
3315 _argvec[2+6] = (unsigned long)arg6; \
3316 _argvec[2+7] = (unsigned long)arg7; \
3317 _argvec[2+8] = (unsigned long)arg8; \
3318 _argvec[2+9] = (unsigned long)arg9; \
3319 __asm__ volatile( \
3320 "mr 11,%1\n\t" \
3321 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3322 "stw 2,-8(11)\n\t" /* save tocptr */ \
3323 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3324 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3325 /* arg9 */ \
3326 "lwz 3,36(11)\n\t" \
3327 "stw 3,56(1)\n\t" \
3328 /* args1-8 */ \
3329 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3330 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3331 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3332 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3333 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3334 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3335 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3336 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3337 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3338 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3339 "mr 11,%1\n\t" \
3340 "mr %0,3\n\t" \
3341 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3342 VG_CONTRACT_FRAME_BY(64) \
3343 VG_CONTRACT_FRAME_BY(512) \
3344 : /*out*/ "=r" (_res) \
3345 : /*in*/ "r" (&_argvec[2]) \
3346 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3347 ); \
3348 lval = (__typeof__(lval)) _res; \
3349 } while (0)
3350
3351#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3352 arg7,arg8,arg9,arg10) \
3353 do { \
3354 volatile OrigFn _orig = (orig); \
3355 volatile unsigned long _argvec[3+10]; \
3356 volatile unsigned long _res; \
3357 /* _argvec[0] holds current r2 across the call */ \
3358 _argvec[1] = (unsigned long)_orig.r2; \
3359 _argvec[2] = (unsigned long)_orig.nraddr; \
3360 _argvec[2+1] = (unsigned long)arg1; \
3361 _argvec[2+2] = (unsigned long)arg2; \
3362 _argvec[2+3] = (unsigned long)arg3; \
3363 _argvec[2+4] = (unsigned long)arg4; \
3364 _argvec[2+5] = (unsigned long)arg5; \
3365 _argvec[2+6] = (unsigned long)arg6; \
3366 _argvec[2+7] = (unsigned long)arg7; \
3367 _argvec[2+8] = (unsigned long)arg8; \
3368 _argvec[2+9] = (unsigned long)arg9; \
3369 _argvec[2+10] = (unsigned long)arg10; \
3370 __asm__ volatile( \
3371 "mr 11,%1\n\t" \
3372 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3373 "stw 2,-8(11)\n\t" /* save tocptr */ \
3374 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3375 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3376 /* arg10 */ \
3377 "lwz 3,40(11)\n\t" \
3378 "stw 3,60(1)\n\t" \
3379 /* arg9 */ \
3380 "lwz 3,36(11)\n\t" \
3381 "stw 3,56(1)\n\t" \
3382 /* args1-8 */ \
3383 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3384 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3385 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3386 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3387 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3388 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3389 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3390 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3391 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3392 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3393 "mr 11,%1\n\t" \
3394 "mr %0,3\n\t" \
3395 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3396 VG_CONTRACT_FRAME_BY(64) \
3397 VG_CONTRACT_FRAME_BY(512) \
3398 : /*out*/ "=r" (_res) \
3399 : /*in*/ "r" (&_argvec[2]) \
3400 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3401 ); \
3402 lval = (__typeof__(lval)) _res; \
3403 } while (0)
3404
3405#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3406 arg7,arg8,arg9,arg10,arg11) \
3407 do { \
3408 volatile OrigFn _orig = (orig); \
3409 volatile unsigned long _argvec[3+11]; \
3410 volatile unsigned long _res; \
3411 /* _argvec[0] holds current r2 across the call */ \
3412 _argvec[1] = (unsigned long)_orig.r2; \
3413 _argvec[2] = (unsigned long)_orig.nraddr; \
3414 _argvec[2+1] = (unsigned long)arg1; \
3415 _argvec[2+2] = (unsigned long)arg2; \
3416 _argvec[2+3] = (unsigned long)arg3; \
3417 _argvec[2+4] = (unsigned long)arg4; \
3418 _argvec[2+5] = (unsigned long)arg5; \
3419 _argvec[2+6] = (unsigned long)arg6; \
3420 _argvec[2+7] = (unsigned long)arg7; \
3421 _argvec[2+8] = (unsigned long)arg8; \
3422 _argvec[2+9] = (unsigned long)arg9; \
3423 _argvec[2+10] = (unsigned long)arg10; \
3424 _argvec[2+11] = (unsigned long)arg11; \
3425 __asm__ volatile( \
3426 "mr 11,%1\n\t" \
3427 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3428 "stw 2,-8(11)\n\t" /* save tocptr */ \
3429 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3430 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3431 /* arg11 */ \
3432 "lwz 3,44(11)\n\t" \
3433 "stw 3,64(1)\n\t" \
3434 /* arg10 */ \
3435 "lwz 3,40(11)\n\t" \
3436 "stw 3,60(1)\n\t" \
3437 /* arg9 */ \
3438 "lwz 3,36(11)\n\t" \
3439 "stw 3,56(1)\n\t" \
3440 /* args1-8 */ \
3441 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3442 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3443 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3444 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3445 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3446 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3447 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3448 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3449 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3450 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3451 "mr 11,%1\n\t" \
3452 "mr %0,3\n\t" \
3453 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3454 VG_CONTRACT_FRAME_BY(72) \
3455 VG_CONTRACT_FRAME_BY(512) \
3456 : /*out*/ "=r" (_res) \
3457 : /*in*/ "r" (&_argvec[2]) \
3458 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3459 ); \
3460 lval = (__typeof__(lval)) _res; \
3461 } while (0)
3462
3463#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3464 arg7,arg8,arg9,arg10,arg11,arg12) \
3465 do { \
3466 volatile OrigFn _orig = (orig); \
3467 volatile unsigned long _argvec[3+12]; \
3468 volatile unsigned long _res; \
3469 /* _argvec[0] holds current r2 across the call */ \
3470 _argvec[1] = (unsigned long)_orig.r2; \
3471 _argvec[2] = (unsigned long)_orig.nraddr; \
3472 _argvec[2+1] = (unsigned long)arg1; \
3473 _argvec[2+2] = (unsigned long)arg2; \
3474 _argvec[2+3] = (unsigned long)arg3; \
3475 _argvec[2+4] = (unsigned long)arg4; \
3476 _argvec[2+5] = (unsigned long)arg5; \
3477 _argvec[2+6] = (unsigned long)arg6; \
3478 _argvec[2+7] = (unsigned long)arg7; \
3479 _argvec[2+8] = (unsigned long)arg8; \
3480 _argvec[2+9] = (unsigned long)arg9; \
3481 _argvec[2+10] = (unsigned long)arg10; \
3482 _argvec[2+11] = (unsigned long)arg11; \
3483 _argvec[2+12] = (unsigned long)arg12; \
3484 __asm__ volatile( \
3485 "mr 11,%1\n\t" \
3486 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3487 "stw 2,-8(11)\n\t" /* save tocptr */ \
3488 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3489 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3490 /* arg12 */ \
3491 "lwz 3,48(11)\n\t" \
3492 "stw 3,68(1)\n\t" \
3493 /* arg11 */ \
3494 "lwz 3,44(11)\n\t" \
3495 "stw 3,64(1)\n\t" \
3496 /* arg10 */ \
3497 "lwz 3,40(11)\n\t" \
3498 "stw 3,60(1)\n\t" \
3499 /* arg9 */ \
3500 "lwz 3,36(11)\n\t" \
3501 "stw 3,56(1)\n\t" \
3502 /* args1-8 */ \
3503 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3504 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3505 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3506 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3507 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3508 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3509 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3510 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3511 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3512 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3513 "mr 11,%1\n\t" \
3514 "mr %0,3\n\t" \
3515 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3516 VG_CONTRACT_FRAME_BY(72) \
3517 VG_CONTRACT_FRAME_BY(512) \
3518 : /*out*/ "=r" (_res) \
3519 : /*in*/ "r" (&_argvec[2]) \
3520 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3521 ); \
3522 lval = (__typeof__(lval)) _res; \
3523 } while (0)
3524
3525#endif /* PLAT_ppc32_aix5 */
3526
3527/* ------------------------ ppc64-aix5 ------------------------- */
3528
3529#if defined(PLAT_ppc64_aix5)
3530
3531/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3532
3533/* These regs are trashed by the hidden call. */
3534#define __CALLER_SAVED_REGS \
3535 "lr", "ctr", "xer", \
3536 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3537 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3538 "r11", "r12", "r13"
3539
3540/* Expand the stack frame, copying enough info that unwinding
3541 still works. Trashes r3. */
3542
3543#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3544 "addi 1,1,-" #_n_fr "\n\t" \
3545 "ld 3," #_n_fr "(1)\n\t" \
3546 "std 3,0(1)\n\t"
3547
3548#define VG_CONTRACT_FRAME_BY(_n_fr) \
3549 "addi 1,1," #_n_fr "\n\t"
3550
3551/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3552 long) == 8. */
3553
3554#define CALL_FN_W_v(lval, orig) \
3555 do { \
3556 volatile OrigFn _orig = (orig); \
3557 volatile unsigned long _argvec[3+0]; \
3558 volatile unsigned long _res; \
3559 /* _argvec[0] holds current r2 across the call */ \
3560 _argvec[1] = (unsigned long)_orig.r2; \
3561 _argvec[2] = (unsigned long)_orig.nraddr; \
3562 __asm__ volatile( \
3563 "mr 11,%1\n\t" \
3564 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3565 "std 2,-16(11)\n\t" /* save tocptr */ \
3566 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3567 "ld 11, 0(11)\n\t" /* target->r11 */ \
3568 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3569 "mr 11,%1\n\t" \
3570 "mr %0,3\n\t" \
3571 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3572 VG_CONTRACT_FRAME_BY(512) \
3573 : /*out*/ "=r" (_res) \
3574 : /*in*/ "r" (&_argvec[2]) \
3575 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3576 ); \
3577 lval = (__typeof__(lval)) _res; \
3578 } while (0)
3579
3580#define CALL_FN_W_W(lval, orig, arg1) \
3581 do { \
3582 volatile OrigFn _orig = (orig); \
3583 volatile unsigned long _argvec[3+1]; \
3584 volatile unsigned long _res; \
3585 /* _argvec[0] holds current r2 across the call */ \
3586 _argvec[1] = (unsigned long)_orig.r2; \
3587 _argvec[2] = (unsigned long)_orig.nraddr; \
3588 _argvec[2+1] = (unsigned long)arg1; \
3589 __asm__ volatile( \
3590 "mr 11,%1\n\t" \
3591 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3592 "std 2,-16(11)\n\t" /* save tocptr */ \
3593 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3594 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3595 "ld 11, 0(11)\n\t" /* target->r11 */ \
3596 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3597 "mr 11,%1\n\t" \
3598 "mr %0,3\n\t" \
3599 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3600 VG_CONTRACT_FRAME_BY(512) \
3601 : /*out*/ "=r" (_res) \
3602 : /*in*/ "r" (&_argvec[2]) \
3603 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3604 ); \
3605 lval = (__typeof__(lval)) _res; \
3606 } while (0)
3607
3608#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3609 do { \
3610 volatile OrigFn _orig = (orig); \
3611 volatile unsigned long _argvec[3+2]; \
3612 volatile unsigned long _res; \
3613 /* _argvec[0] holds current r2 across the call */ \
3614 _argvec[1] = (unsigned long)_orig.r2; \
3615 _argvec[2] = (unsigned long)_orig.nraddr; \
3616 _argvec[2+1] = (unsigned long)arg1; \
3617 _argvec[2+2] = (unsigned long)arg2; \
3618 __asm__ volatile( \
3619 "mr 11,%1\n\t" \
3620 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3621 "std 2,-16(11)\n\t" /* save tocptr */ \
3622 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3623 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3624 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3625 "ld 11, 0(11)\n\t" /* target->r11 */ \
3626 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3627 "mr 11,%1\n\t" \
3628 "mr %0,3\n\t" \
3629 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3630 VG_CONTRACT_FRAME_BY(512) \
3631 : /*out*/ "=r" (_res) \
3632 : /*in*/ "r" (&_argvec[2]) \
3633 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3634 ); \
3635 lval = (__typeof__(lval)) _res; \
3636 } while (0)
3637
3638#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3639 do { \
3640 volatile OrigFn _orig = (orig); \
3641 volatile unsigned long _argvec[3+3]; \
3642 volatile unsigned long _res; \
3643 /* _argvec[0] holds current r2 across the call */ \
3644 _argvec[1] = (unsigned long)_orig.r2; \
3645 _argvec[2] = (unsigned long)_orig.nraddr; \
3646 _argvec[2+1] = (unsigned long)arg1; \
3647 _argvec[2+2] = (unsigned long)arg2; \
3648 _argvec[2+3] = (unsigned long)arg3; \
3649 __asm__ volatile( \
3650 "mr 11,%1\n\t" \
3651 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3652 "std 2,-16(11)\n\t" /* save tocptr */ \
3653 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3654 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3655 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3656 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3657 "ld 11, 0(11)\n\t" /* target->r11 */ \
3658 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3659 "mr 11,%1\n\t" \
3660 "mr %0,3\n\t" \
3661 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3662 VG_CONTRACT_FRAME_BY(512) \
3663 : /*out*/ "=r" (_res) \
3664 : /*in*/ "r" (&_argvec[2]) \
3665 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3666 ); \
3667 lval = (__typeof__(lval)) _res; \
3668 } while (0)
3669
3670#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3671 do { \
3672 volatile OrigFn _orig = (orig); \
3673 volatile unsigned long _argvec[3+4]; \
3674 volatile unsigned long _res; \
3675 /* _argvec[0] holds current r2 across the call */ \
3676 _argvec[1] = (unsigned long)_orig.r2; \
3677 _argvec[2] = (unsigned long)_orig.nraddr; \
3678 _argvec[2+1] = (unsigned long)arg1; \
3679 _argvec[2+2] = (unsigned long)arg2; \
3680 _argvec[2+3] = (unsigned long)arg3; \
3681 _argvec[2+4] = (unsigned long)arg4; \
3682 __asm__ volatile( \
3683 "mr 11,%1\n\t" \
3684 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3685 "std 2,-16(11)\n\t" /* save tocptr */ \
3686 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3687 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3688 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3689 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3690 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3691 "ld 11, 0(11)\n\t" /* target->r11 */ \
3692 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3693 "mr 11,%1\n\t" \
3694 "mr %0,3\n\t" \
3695 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3696 VG_CONTRACT_FRAME_BY(512) \
3697 : /*out*/ "=r" (_res) \
3698 : /*in*/ "r" (&_argvec[2]) \
3699 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3700 ); \
3701 lval = (__typeof__(lval)) _res; \
3702 } while (0)
3703
3704#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3705 do { \
3706 volatile OrigFn _orig = (orig); \
3707 volatile unsigned long _argvec[3+5]; \
3708 volatile unsigned long _res; \
3709 /* _argvec[0] holds current r2 across the call */ \
3710 _argvec[1] = (unsigned long)_orig.r2; \
3711 _argvec[2] = (unsigned long)_orig.nraddr; \
3712 _argvec[2+1] = (unsigned long)arg1; \
3713 _argvec[2+2] = (unsigned long)arg2; \
3714 _argvec[2+3] = (unsigned long)arg3; \
3715 _argvec[2+4] = (unsigned long)arg4; \
3716 _argvec[2+5] = (unsigned long)arg5; \
3717 __asm__ volatile( \
3718 "mr 11,%1\n\t" \
3719 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3720 "std 2,-16(11)\n\t" /* save tocptr */ \
3721 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3722 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3723 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3724 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3725 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3726 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3727 "ld 11, 0(11)\n\t" /* target->r11 */ \
3728 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3729 "mr 11,%1\n\t" \
3730 "mr %0,3\n\t" \
3731 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3732 VG_CONTRACT_FRAME_BY(512) \
3733 : /*out*/ "=r" (_res) \
3734 : /*in*/ "r" (&_argvec[2]) \
3735 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3736 ); \
3737 lval = (__typeof__(lval)) _res; \
3738 } while (0)
3739
3740#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3741 do { \
3742 volatile OrigFn _orig = (orig); \
3743 volatile unsigned long _argvec[3+6]; \
3744 volatile unsigned long _res; \
3745 /* _argvec[0] holds current r2 across the call */ \
3746 _argvec[1] = (unsigned long)_orig.r2; \
3747 _argvec[2] = (unsigned long)_orig.nraddr; \
3748 _argvec[2+1] = (unsigned long)arg1; \
3749 _argvec[2+2] = (unsigned long)arg2; \
3750 _argvec[2+3] = (unsigned long)arg3; \
3751 _argvec[2+4] = (unsigned long)arg4; \
3752 _argvec[2+5] = (unsigned long)arg5; \
3753 _argvec[2+6] = (unsigned long)arg6; \
3754 __asm__ volatile( \
3755 "mr 11,%1\n\t" \
3756 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3757 "std 2,-16(11)\n\t" /* save tocptr */ \
3758 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3759 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3760 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3761 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3762 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3763 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3764 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3765 "ld 11, 0(11)\n\t" /* target->r11 */ \
3766 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3767 "mr 11,%1\n\t" \
3768 "mr %0,3\n\t" \
3769 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3770 VG_CONTRACT_FRAME_BY(512) \
3771 : /*out*/ "=r" (_res) \
3772 : /*in*/ "r" (&_argvec[2]) \
3773 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3774 ); \
3775 lval = (__typeof__(lval)) _res; \
3776 } while (0)
3777
3778#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3779 arg7) \
3780 do { \
3781 volatile OrigFn _orig = (orig); \
3782 volatile unsigned long _argvec[3+7]; \
3783 volatile unsigned long _res; \
3784 /* _argvec[0] holds current r2 across the call */ \
3785 _argvec[1] = (unsigned long)_orig.r2; \
3786 _argvec[2] = (unsigned long)_orig.nraddr; \
3787 _argvec[2+1] = (unsigned long)arg1; \
3788 _argvec[2+2] = (unsigned long)arg2; \
3789 _argvec[2+3] = (unsigned long)arg3; \
3790 _argvec[2+4] = (unsigned long)arg4; \
3791 _argvec[2+5] = (unsigned long)arg5; \
3792 _argvec[2+6] = (unsigned long)arg6; \
3793 _argvec[2+7] = (unsigned long)arg7; \
3794 __asm__ volatile( \
3795 "mr 11,%1\n\t" \
3796 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3797 "std 2,-16(11)\n\t" /* save tocptr */ \
3798 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3799 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3800 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3801 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3802 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3803 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3804 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3805 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3806 "ld 11, 0(11)\n\t" /* target->r11 */ \
3807 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3808 "mr 11,%1\n\t" \
3809 "mr %0,3\n\t" \
3810 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3811 VG_CONTRACT_FRAME_BY(512) \
3812 : /*out*/ "=r" (_res) \
3813 : /*in*/ "r" (&_argvec[2]) \
3814 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3815 ); \
3816 lval = (__typeof__(lval)) _res; \
3817 } while (0)
3818
3819#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3820 arg7,arg8) \
3821 do { \
3822 volatile OrigFn _orig = (orig); \
3823 volatile unsigned long _argvec[3+8]; \
3824 volatile unsigned long _res; \
3825 /* _argvec[0] holds current r2 across the call */ \
3826 _argvec[1] = (unsigned long)_orig.r2; \
3827 _argvec[2] = (unsigned long)_orig.nraddr; \
3828 _argvec[2+1] = (unsigned long)arg1; \
3829 _argvec[2+2] = (unsigned long)arg2; \
3830 _argvec[2+3] = (unsigned long)arg3; \
3831 _argvec[2+4] = (unsigned long)arg4; \
3832 _argvec[2+5] = (unsigned long)arg5; \
3833 _argvec[2+6] = (unsigned long)arg6; \
3834 _argvec[2+7] = (unsigned long)arg7; \
3835 _argvec[2+8] = (unsigned long)arg8; \
3836 __asm__ volatile( \
3837 "mr 11,%1\n\t" \
3838 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3839 "std 2,-16(11)\n\t" /* save tocptr */ \
3840 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3841 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3842 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3843 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3844 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3845 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3846 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3847 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3848 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3849 "ld 11, 0(11)\n\t" /* target->r11 */ \
3850 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3851 "mr 11,%1\n\t" \
3852 "mr %0,3\n\t" \
3853 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3854 VG_CONTRACT_FRAME_BY(512) \
3855 : /*out*/ "=r" (_res) \
3856 : /*in*/ "r" (&_argvec[2]) \
3857 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3858 ); \
3859 lval = (__typeof__(lval)) _res; \
3860 } while (0)
3861
3862#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3863 arg7,arg8,arg9) \
3864 do { \
3865 volatile OrigFn _orig = (orig); \
3866 volatile unsigned long _argvec[3+9]; \
3867 volatile unsigned long _res; \
3868 /* _argvec[0] holds current r2 across the call */ \
3869 _argvec[1] = (unsigned long)_orig.r2; \
3870 _argvec[2] = (unsigned long)_orig.nraddr; \
3871 _argvec[2+1] = (unsigned long)arg1; \
3872 _argvec[2+2] = (unsigned long)arg2; \
3873 _argvec[2+3] = (unsigned long)arg3; \
3874 _argvec[2+4] = (unsigned long)arg4; \
3875 _argvec[2+5] = (unsigned long)arg5; \
3876 _argvec[2+6] = (unsigned long)arg6; \
3877 _argvec[2+7] = (unsigned long)arg7; \
3878 _argvec[2+8] = (unsigned long)arg8; \
3879 _argvec[2+9] = (unsigned long)arg9; \
3880 __asm__ volatile( \
3881 "mr 11,%1\n\t" \
3882 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3883 "std 2,-16(11)\n\t" /* save tocptr */ \
3884 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3885 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3886 /* arg9 */ \
3887 "ld 3,72(11)\n\t" \
3888 "std 3,112(1)\n\t" \
3889 /* args1-8 */ \
3890 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3891 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3892 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3893 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3894 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3895 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3896 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3897 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3898 "ld 11, 0(11)\n\t" /* target->r11 */ \
3899 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3900 "mr 11,%1\n\t" \
3901 "mr %0,3\n\t" \
3902 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3903 VG_CONTRACT_FRAME_BY(128) \
3904 VG_CONTRACT_FRAME_BY(512) \
3905 : /*out*/ "=r" (_res) \
3906 : /*in*/ "r" (&_argvec[2]) \
3907 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3908 ); \
3909 lval = (__typeof__(lval)) _res; \
3910 } while (0)
3911
3912#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3913 arg7,arg8,arg9,arg10) \
3914 do { \
3915 volatile OrigFn _orig = (orig); \
3916 volatile unsigned long _argvec[3+10]; \
3917 volatile unsigned long _res; \
3918 /* _argvec[0] holds current r2 across the call */ \
3919 _argvec[1] = (unsigned long)_orig.r2; \
3920 _argvec[2] = (unsigned long)_orig.nraddr; \
3921 _argvec[2+1] = (unsigned long)arg1; \
3922 _argvec[2+2] = (unsigned long)arg2; \
3923 _argvec[2+3] = (unsigned long)arg3; \
3924 _argvec[2+4] = (unsigned long)arg4; \
3925 _argvec[2+5] = (unsigned long)arg5; \
3926 _argvec[2+6] = (unsigned long)arg6; \
3927 _argvec[2+7] = (unsigned long)arg7; \
3928 _argvec[2+8] = (unsigned long)arg8; \
3929 _argvec[2+9] = (unsigned long)arg9; \
3930 _argvec[2+10] = (unsigned long)arg10; \
3931 __asm__ volatile( \
3932 "mr 11,%1\n\t" \
3933 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3934 "std 2,-16(11)\n\t" /* save tocptr */ \
3935 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3936 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3937 /* arg10 */ \
3938 "ld 3,80(11)\n\t" \
3939 "std 3,120(1)\n\t" \
3940 /* arg9 */ \
3941 "ld 3,72(11)\n\t" \
3942 "std 3,112(1)\n\t" \
3943 /* args1-8 */ \
3944 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3945 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3946 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3947 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3948 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3949 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3950 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3951 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3952 "ld 11, 0(11)\n\t" /* target->r11 */ \
3953 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3954 "mr 11,%1\n\t" \
3955 "mr %0,3\n\t" \
3956 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3957 VG_CONTRACT_FRAME_BY(128) \
3958 VG_CONTRACT_FRAME_BY(512) \
3959 : /*out*/ "=r" (_res) \
3960 : /*in*/ "r" (&_argvec[2]) \
3961 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3962 ); \
3963 lval = (__typeof__(lval)) _res; \
3964 } while (0)
3965
3966#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3967 arg7,arg8,arg9,arg10,arg11) \
3968 do { \
3969 volatile OrigFn _orig = (orig); \
3970 volatile unsigned long _argvec[3+11]; \
3971 volatile unsigned long _res; \
3972 /* _argvec[0] holds current r2 across the call */ \
3973 _argvec[1] = (unsigned long)_orig.r2; \
3974 _argvec[2] = (unsigned long)_orig.nraddr; \
3975 _argvec[2+1] = (unsigned long)arg1; \
3976 _argvec[2+2] = (unsigned long)arg2; \
3977 _argvec[2+3] = (unsigned long)arg3; \
3978 _argvec[2+4] = (unsigned long)arg4; \
3979 _argvec[2+5] = (unsigned long)arg5; \
3980 _argvec[2+6] = (unsigned long)arg6; \
3981 _argvec[2+7] = (unsigned long)arg7; \
3982 _argvec[2+8] = (unsigned long)arg8; \
3983 _argvec[2+9] = (unsigned long)arg9; \
3984 _argvec[2+10] = (unsigned long)arg10; \
3985 _argvec[2+11] = (unsigned long)arg11; \
3986 __asm__ volatile( \
3987 "mr 11,%1\n\t" \
3988 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3989 "std 2,-16(11)\n\t" /* save tocptr */ \
3990 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3991 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3992 /* arg11 */ \
3993 "ld 3,88(11)\n\t" \
3994 "std 3,128(1)\n\t" \
3995 /* arg10 */ \
3996 "ld 3,80(11)\n\t" \
3997 "std 3,120(1)\n\t" \
3998 /* arg9 */ \
3999 "ld 3,72(11)\n\t" \
4000 "std 3,112(1)\n\t" \
4001 /* args1-8 */ \
4002 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4003 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4004 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4005 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4006 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4007 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4008 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4009 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4010 "ld 11, 0(11)\n\t" /* target->r11 */ \
4011 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4012 "mr 11,%1\n\t" \
4013 "mr %0,3\n\t" \
4014 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4015 VG_CONTRACT_FRAME_BY(144) \
4016 VG_CONTRACT_FRAME_BY(512) \
4017 : /*out*/ "=r" (_res) \
4018 : /*in*/ "r" (&_argvec[2]) \
4019 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4020 ); \
4021 lval = (__typeof__(lval)) _res; \
4022 } while (0)
4023
4024#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4025 arg7,arg8,arg9,arg10,arg11,arg12) \
4026 do { \
4027 volatile OrigFn _orig = (orig); \
4028 volatile unsigned long _argvec[3+12]; \
4029 volatile unsigned long _res; \
4030 /* _argvec[0] holds current r2 across the call */ \
4031 _argvec[1] = (unsigned long)_orig.r2; \
4032 _argvec[2] = (unsigned long)_orig.nraddr; \
4033 _argvec[2+1] = (unsigned long)arg1; \
4034 _argvec[2+2] = (unsigned long)arg2; \
4035 _argvec[2+3] = (unsigned long)arg3; \
4036 _argvec[2+4] = (unsigned long)arg4; \
4037 _argvec[2+5] = (unsigned long)arg5; \
4038 _argvec[2+6] = (unsigned long)arg6; \
4039 _argvec[2+7] = (unsigned long)arg7; \
4040 _argvec[2+8] = (unsigned long)arg8; \
4041 _argvec[2+9] = (unsigned long)arg9; \
4042 _argvec[2+10] = (unsigned long)arg10; \
4043 _argvec[2+11] = (unsigned long)arg11; \
4044 _argvec[2+12] = (unsigned long)arg12; \
4045 __asm__ volatile( \
4046 "mr 11,%1\n\t" \
4047 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4048 "std 2,-16(11)\n\t" /* save tocptr */ \
4049 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4050 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4051 /* arg12 */ \
4052 "ld 3,96(11)\n\t" \
4053 "std 3,136(1)\n\t" \
4054 /* arg11 */ \
4055 "ld 3,88(11)\n\t" \
4056 "std 3,128(1)\n\t" \
4057 /* arg10 */ \
4058 "ld 3,80(11)\n\t" \
4059 "std 3,120(1)\n\t" \
4060 /* arg9 */ \
4061 "ld 3,72(11)\n\t" \
4062 "std 3,112(1)\n\t" \
4063 /* args1-8 */ \
4064 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4065 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4066 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4067 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4068 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4069 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4070 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4071 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4072 "ld 11, 0(11)\n\t" /* target->r11 */ \
4073 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4074 "mr 11,%1\n\t" \
4075 "mr %0,3\n\t" \
4076 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4077 VG_CONTRACT_FRAME_BY(144) \
4078 VG_CONTRACT_FRAME_BY(512) \
4079 : /*out*/ "=r" (_res) \
4080 : /*in*/ "r" (&_argvec[2]) \
4081 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4082 ); \
4083 lval = (__typeof__(lval)) _res; \
4084 } while (0)
4085
4086#endif /* PLAT_ppc64_aix5 */
4087
4088
4089/* ------------------------------------------------------------------ */
4090/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4091/* */
4092/* ------------------------------------------------------------------ */
4093
4094/* Some request codes. There are many more of these, but most are not
4095 exposed to end-user view. These are the public ones, all of the
4096 form 0x1000 + small_number.
4097
4098 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4099 ones start at 0x2000.
4100*/
4101
4102/* These macros are used by tools -- they must be public, but don't
4103 embed them into other programs. */
4104#define VG_USERREQ_TOOL_BASE(a,b) \
4105 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
4106#define VG_IS_TOOL_USERREQ(a, b, v) \
4107 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
4108
4109/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4110 This enum comprises an ABI exported by Valgrind to programs
4111 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4112 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
4113typedef
4116
4117 /* These allow any function to be called from the simulated
4118 CPU but run on the real CPU. Nb: the first arg passed to
4119 the function is always the ThreadId of the running
4120 thread! So CLIENT_CALL0 actually requires a 1 arg
4121 function, etc. */
4126
4127 /* Can be useful in regression testing suites -- eg. can
4128 send Valgrind's output to /dev/null and still count
4129 errors. */
4131
4132 /* These are useful and can be interpreted by any tool that
4133 tracks malloc() et al, by using vg_replace_malloc.c. */
4136 /* Memory pool support. */
4145
4146 /* Allow printfs to valgrind log. */
4147 /* The first two pass the va_list argument by value, which
4148 assumes it is the same size as or smaller than a UWord,
4149 which generally isn't the case. Hence are deprecated.
4150 The second two pass the vargs by reference and so are
4151 immune to this problem. */
4152 /* both :: char* fmt, va_list vargs (DEPRECATED) */
4155 /* both :: char* fmt, va_list* vargs */
4158
4159 /* Stack support. */
4163
4164 /* Wine support */
4167
4168#if !defined(__GNUC__)
4169# define __extension__ /* */
4170#endif
4171
4172/* Returns the number of Valgrinds this code is running under. That
4173 is, 0 if running natively, 1 if running under Valgrind, 2 if
4174 running under Valgrind which is running under another Valgrind,
4175 etc. */
4176#define RUNNING_ON_VALGRIND __extension__ \
4177 ({unsigned int _qzz_res; \
4178 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
4179 VG_USERREQ__RUNNING_ON_VALGRIND, \
4180 0, 0, 0, 0, 0); \
4181 _qzz_res; \
4182 })
4183
4184
4185/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4186 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4187 since it provides a way to make sure valgrind will retranslate the
4188 invalidated area. Returns no value. */
4189#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4190 {unsigned int _qzz_res; \
4191 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4192 VG_USERREQ__DISCARD_TRANSLATIONS, \
4193 _qzz_addr, _qzz_len, 0, 0, 0); \
4194 }
4195
4196
4197/* These requests are for getting Valgrind itself to print something.
4198 Possibly with a backtrace. This is a really ugly hack. The return value
4199 is the number of characters printed, excluding the "**<pid>** " part at the
4200 start and the backtrace (if present). */
4201
4202#if defined(NVALGRIND)
4203
4204# define VALGRIND_PRINTF(...)
4205# define VALGRIND_PRINTF_BACKTRACE(...)
4206
4207#else /* NVALGRIND */
4208
4209/* Modern GCC will optimize the static routine out if unused,
4210 and unused attribute will shut down warnings about it. */
4211static int VALGRIND_PRINTF(const char *format, ...)
4212 __attribute__((format(__printf__, 1, 2), __unused__));
4213static int
4214VALGRIND_PRINTF(const char *format, ...)
4215{
4216 unsigned long _qzz_res;
4217 va_list vargs;
4218 va_start(vargs, format);
4219 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4221 (unsigned long)format,
4222 (unsigned long)&vargs,
4223 0, 0, 0);
4224 va_end(vargs);
4225 return (int)_qzz_res;
4226}
4227
4228static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4229 __attribute__((format(__printf__, 1, 2), __unused__));
4230static int
4231VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4232{
4233 unsigned long _qzz_res;
4234 va_list vargs;
4235 va_start(vargs, format);
4236 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4238 (unsigned long)format,
4239 (unsigned long)&vargs,
4240 0, 0, 0);
4241 va_end(vargs);
4242 return (int)_qzz_res;
4243}
4244
4245#endif /* NVALGRIND */
4246
4247
4248/* These requests allow control to move from the simulated CPU to the
4249 real CPU, calling an arbitary function.
4250
4251 Note that the current ThreadId is inserted as the first argument.
4252 So this call:
4253
4254 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4255
4256 requires f to have this signature:
4257
4258 Word f(Word tid, Word arg1, Word arg2)
4259
4260 where "Word" is a word-sized type.
4261
4262 Note that these client requests are not entirely reliable. For example,
4263 if you call a function with them that subsequently calls printf(),
4264 there's a high chance Valgrind will crash. Generally, your prospects of
4265 these working are made higher if the called function does not refer to
4266 any global variables, and does not refer to any libc or other functions
4267 (printf et al). Any kind of entanglement with libc or dynamic linking is
4268 likely to have a bad outcome, for tricky reasons which we've grappled
4269 with a lot in the past.
4270*/
4271#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
4272 __extension__ \
4273 ({unsigned long _qyy_res; \
4274 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4275 VG_USERREQ__CLIENT_CALL0, \
4276 _qyy_fn, \
4277 0, 0, 0, 0); \
4278 _qyy_res; \
4279 })
4280
4281#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
4282 __extension__ \
4283 ({unsigned long _qyy_res; \
4284 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4285 VG_USERREQ__CLIENT_CALL1, \
4286 _qyy_fn, \
4287 _qyy_arg1, 0, 0, 0); \
4288 _qyy_res; \
4289 })
4290
4291#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
4292 __extension__ \
4293 ({unsigned long _qyy_res; \
4294 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4295 VG_USERREQ__CLIENT_CALL2, \
4296 _qyy_fn, \
4297 _qyy_arg1, _qyy_arg2, 0, 0); \
4298 _qyy_res; \
4299 })
4300
4301#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
4302 __extension__ \
4303 ({unsigned long _qyy_res; \
4304 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4305 VG_USERREQ__CLIENT_CALL3, \
4306 _qyy_fn, \
4307 _qyy_arg1, _qyy_arg2, \
4308 _qyy_arg3, 0); \
4309 _qyy_res; \
4310 })
4311
4312
4313/* Counts the number of errors that have been recorded by a tool. Nb:
4314 the tool must record the errors with VG_(maybe_record_error)() or
4315 VG_(unique_error)() for them to be counted. */
4316#define VALGRIND_COUNT_ERRORS \
4317 __extension__ \
4318 ({unsigned int _qyy_res; \
4319 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4320 VG_USERREQ__COUNT_ERRORS, \
4321 0, 0, 0, 0, 0); \
4322 _qyy_res; \
4323 })
4324
4325/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4326 when heap blocks are allocated in order to give accurate results. This
4327 happens automatically for the standard allocator functions such as
4328 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4329 delete[], etc.
4330
4331 But if your program uses a custom allocator, this doesn't automatically
4332 happen, and Valgrind will not do as well. For example, if you allocate
4333 superblocks with mmap() and then allocates chunks of the superblocks, all
4334 Valgrind's observations will be at the mmap() level and it won't know that
4335 the chunks should be considered separate entities. In Memcheck's case,
4336 that means you probably won't get heap block overrun detection (because
4337 there won't be redzones marked as unaddressable) and you definitely won't
4338 get any leak detection.
4339
4340 The following client requests allow a custom allocator to be annotated so
4341 that it can be handled accurately by Valgrind.
4342
4343 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4344 by a malloc()-like function. For Memcheck (an illustrative case), this
4345 does two things:
4346
4347 - It records that the block has been allocated. This means any addresses
4348 within the block mentioned in error messages will be
4349 identified as belonging to the block. It also means that if the block
4350 isn't freed it will be detected by the leak checker.
4351
4352 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4353 not set), or addressable and defined (if 'is_zeroed' is set). This
4354 controls how accesses to the block by the program are handled.
4355
4356 'addr' is the start of the usable block (ie. after any
4357 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4358 can apply redzones -- these are blocks of padding at the start and end of
4359 each block. Adding redzones is recommended as it makes it much more likely
4360 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4361 zeroed (or filled with another predictable value), as is the case for
4362 calloc().
4363
4364 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4365 heap block -- that will be used by the client program -- is allocated.
4366 It's best to put it at the outermost level of the allocator if possible;
4367 for example, if you have a function my_alloc() which calls
4368 internal_alloc(), and the client request is put inside internal_alloc(),
4369 stack traces relating to the heap block will contain entries for both
4370 my_alloc() and internal_alloc(), which is probably not what you want.
4371
4372 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4373 custom blocks from within a heap block, B, that has been allocated with
4374 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4375 -- the custom blocks will take precedence.
4376
4377 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4378 Memcheck, it does two things:
4379
4380 - It records that the block has been deallocated. This assumes that the
4381 block was annotated as having been allocated via
4382 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4383
4384 - It marks the block as being unaddressable.
4385
4386 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4387 heap block is deallocated.
4388
4389 In many cases, these two client requests will not be enough to get your
4390 allocator working well with Memcheck. More specifically, if your allocator
4391 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4392 will be necessary to mark the memory as addressable just before the zeroing
4393 occurs, otherwise you'll get a lot of invalid write errors. For example,
4394 you'll need to do this if your allocator recycles freed blocks, but it
4395 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4396 Alternatively, if your allocator reuses freed blocks for allocator-internal
4397 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4398
4399 Really, what's happening is a blurring of the lines between the client
4400 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4401 memory should be considered unaddressable to the client program, but the
4402 allocator knows more than the rest of the client program and so may be able
4403 to safely access it. Extra client requests are necessary for Valgrind to
4404 understand the distinction between the allocator and the rest of the
4405 program.
4406
4407 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4408 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4409
4410 Ignored if addr == 0.
4411*/
4412#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4413 {unsigned int __unused _qzz_res; \
4414 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4415 VG_USERREQ__MALLOCLIKE_BLOCK, \
4416 addr, sizeB, rzB, is_zeroed, 0); \
4417 }
4418
4419/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4420 Ignored if addr == 0.
4421*/
4422#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4423 {unsigned int __unused _qzz_res; \
4424 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4425 VG_USERREQ__FREELIKE_BLOCK, \
4426 addr, rzB, 0, 0, 0); \
4427 }
4428
4429/* Create a memory pool. */
4430#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4431 {unsigned int _qzz_res; \
4432 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4433 VG_USERREQ__CREATE_MEMPOOL, \
4434 pool, rzB, is_zeroed, 0, 0); \
4435 }
4436
4437/* Destroy a memory pool. */
4438#define VALGRIND_DESTROY_MEMPOOL(pool) \
4439 {unsigned int _qzz_res; \
4440 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4441 VG_USERREQ__DESTROY_MEMPOOL, \
4442 pool, 0, 0, 0, 0); \
4443 }
4444
4445/* Associate a piece of memory with a memory pool. */
4446#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4447 {unsigned int _qzz_res; \
4448 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4449 VG_USERREQ__MEMPOOL_ALLOC, \
4450 pool, addr, size, 0, 0); \
4451 }
4452
4453/* Disassociate a piece of memory from a memory pool. */
4454#define VALGRIND_MEMPOOL_FREE(pool, addr) \
4455 {unsigned int _qzz_res; \
4456 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4457 VG_USERREQ__MEMPOOL_FREE, \
4458 pool, addr, 0, 0, 0); \
4459 }
4460
4461/* Disassociate any pieces outside a particular range. */
4462#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4463 {unsigned int _qzz_res; \
4464 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4465 VG_USERREQ__MEMPOOL_TRIM, \
4466 pool, addr, size, 0, 0); \
4467 }
4468
4469/* Resize and/or move a piece associated with a memory pool. */
4470#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4471 {unsigned int _qzz_res; \
4472 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4473 VG_USERREQ__MOVE_MEMPOOL, \
4474 poolA, poolB, 0, 0, 0); \
4475 }
4476
4477/* Resize and/or move a piece associated with a memory pool. */
4478#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4479 {unsigned int _qzz_res; \
4480 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4481 VG_USERREQ__MEMPOOL_CHANGE, \
4482 pool, addrA, addrB, size, 0); \
4483 }
4484
4485/* Return 1 if a mempool exists, else 0. */
4486#define VALGRIND_MEMPOOL_EXISTS(pool) \
4487 __extension__ \
4488 ({unsigned int _qzz_res; \
4489 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4490 VG_USERREQ__MEMPOOL_EXISTS, \
4491 pool, 0, 0, 0, 0); \
4492 _qzz_res; \
4493 })
4494
4495/* Mark a piece of memory as being a stack. Returns a stack id. */
4496#define VALGRIND_STACK_REGISTER(start, end) \
4497 __extension__ \
4498 ({unsigned int _qzz_res; \
4499 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4500 VG_USERREQ__STACK_REGISTER, \
4501 start, end, 0, 0, 0); \
4502 _qzz_res; \
4503 })
4504
4505/* Unmark the piece of memory associated with a stack id as being a
4506 stack. */
4507#define VALGRIND_STACK_DEREGISTER(id) \
4508 {unsigned int _qzz_res; \
4509 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4510 VG_USERREQ__STACK_DEREGISTER, \
4511 id, 0, 0, 0, 0); \
4512 }
4513
4514/* Change the start and end address of the stack id. */
4515#define VALGRIND_STACK_CHANGE(id, start, end) \
4516 {unsigned int _qzz_res; \
4517 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4518 VG_USERREQ__STACK_CHANGE, \
4519 id, start, end, 0, 0); \
4520 }
4521
4522/* Load PDB debug info for Wine PE image_map. */
4523#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4524 {unsigned int _qzz_res; \
4525 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4526 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4527 fd, ptr, total_size, delta, 0); \
4528 }
4529
4530
4531#undef PLAT_x86_linux
4532#undef PLAT_amd64_linux
4533#undef PLAT_ppc32_linux
4534#undef PLAT_ppc64_linux
4535#undef PLAT_arm_linux
4536#undef PLAT_ppc32_aix5
4537#undef PLAT_ppc64_aix5
4538
4539#endif /* __VALGRIND_H */
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define __attribute__(x)
Definition compiler.h:10
#define va_end(ap)
Definition stdarg.h:10
#define va_start(ap, last)
Definition stdarg.h:8
__builtin_va_list va_list
Definition stdarg.h:7
#define VALGRIND_PRINTF_BACKTRACE(...)
Definition valgrind.h:4205
#define VALGRIND_PRINTF(...)
Definition valgrind.h:4204
Vg_ClientRequest
Definition valgrind.h:4114
@ VG_USERREQ__DESTROY_MEMPOOL
Definition valgrind.h:4138
@ VG_USERREQ__LOAD_PDB_DEBUGINFO
Definition valgrind.h:4165
@ VG_USERREQ__PRINTF_BACKTRACE
Definition valgrind.h:4154
@ VG_USERREQ__MEMPOOL_ALLOC
Definition valgrind.h:4139
@ VG_USERREQ__MALLOCLIKE_BLOCK
Definition valgrind.h:4134
@ VG_USERREQ__COUNT_ERRORS
Definition valgrind.h:4130
@ VG_USERREQ__STACK_REGISTER
Definition valgrind.h:4160
@ VG_USERREQ__MEMPOOL_CHANGE
Definition valgrind.h:4143
@ VG_USERREQ__PRINTF_VALIST_BY_REF
Definition valgrind.h:4156
@ VG_USERREQ__RUNNING_ON_VALGRIND
Definition valgrind.h:4114
@ VG_USERREQ__CLIENT_CALL0
Definition valgrind.h:4122
@ VG_USERREQ__DISCARD_TRANSLATIONS
Definition valgrind.h:4115
@ VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF
Definition valgrind.h:4157
@ VG_USERREQ__FREELIKE_BLOCK
Definition valgrind.h:4135
@ VG_USERREQ__CREATE_MEMPOOL
Definition valgrind.h:4137
@ VG_USERREQ__MOVE_MEMPOOL
Definition valgrind.h:4142
@ VG_USERREQ__CLIENT_CALL3
Definition valgrind.h:4125
@ VG_USERREQ__MEMPOOL_TRIM
Definition valgrind.h:4141
@ VG_USERREQ__CLIENT_CALL2
Definition valgrind.h:4124
@ VG_USERREQ__PRINTF
Definition valgrind.h:4153
@ VG_USERREQ__STACK_CHANGE
Definition valgrind.h:4162
@ VG_USERREQ__STACK_DEREGISTER
Definition valgrind.h:4161
@ VG_USERREQ__MEMPOOL_FREE
Definition valgrind.h:4140
@ VG_USERREQ__MEMPOOL_EXISTS
Definition valgrind.h:4144
@ VG_USERREQ__CLIENT_CALL1
Definition valgrind.h:4123
#define VALGRIND_DO_CLIENT_REQUEST( _zzq_rlval, _zzq_default, _zzq_request, _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)
Definition valgrind.h:161
int const char * format
Definition xfer.h:105