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