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