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