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