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