Add Valgrind hooks for memory pools
[exim.git] / src / src / valgrind.h
1 /* -*- c -*-
2 ----------------------------------------------------------------
3
4 Notice that the following BSD-style license applies to this one
5 file (valgrind.h) only. The rest of Valgrind is licensed under the
6 terms of the GNU General Public License, version 2, unless
7 otherwise indicated. See the COPYING file in the source
8 distribution for details.
9
10 ----------------------------------------------------------------
11
12 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
14
15 Copyright (C) 2000-2009 Julian Seward. All rights reserved.
16
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
20
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23
24 2. The origin of this software must not be misrepresented; you must
25 not claim that you wrote the original software. If you use this
26 software in a product, an acknowledgment in the product
27 documentation would be appreciated but is not required.
28
29 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
31
32 4. The name of the author may not be used to endorse or promote
33 products derived from this software without specific prior written
34 permission.
35
36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48 ----------------------------------------------------------------
49
50 Notice that the above BSD-style license applies to this one file
51 (valgrind.h) only. The entire rest of Valgrind is licensed under
52 the terms of the GNU General Public License, version 2. See the
53 COPYING file in the source distribution for details.
54
55 ----------------------------------------------------------------
56 */
57
58
59 /* This file is for inclusion into client (your!) code.
60
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
63
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
67 consumes very few (eg. 7) instructions, so the resulting performance
68 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
72
73 #ifndef __VALGRIND_H
74 #define __VALGRIND_H
75
76 #include <stdarg.h>
77
78 /* Nb: this file might be included in a file compiled with -ansi. So
79 we can't use C++ style "//" comments nor the "asm" keyword (instead
80 use "__asm__"). */
81
82 /* Derive some tags indicating what the target platform is. Note
83 that in this file we're using the compiler's CPP symbols for
84 identifying architectures, which are different to the ones we use
85 within the rest of Valgrind. Note, __powerpc__ is active for both
86 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
87 latter (on Linux, that is). */
88 #undef PLAT_x86_linux
89 #undef PLAT_amd64_linux
90 #undef PLAT_ppc32_linux
91 #undef PLAT_ppc64_linux
92 #undef PLAT_ppc32_aix5
93 #undef PLAT_ppc64_aix5
94
95
96 #if defined(_AIX) && defined(__64BIT__)
97 # define PLAT_ppc64_aix5 1
98 #elif defined(_AIX) && !defined(__64BIT__)
99 # define PLAT_ppc32_aix5 1
100 #elif defined(__APPLE__) && defined(__i386__)
101 # define PLAT_x86_darwin 1
102 #elif defined(__APPLE__) && defined(__x86_64__)
103 # define PLAT_amd64_darwin 1
104 #elif defined(__i386__)
105 # define PLAT_x86_linux 1
106 #elif defined(__x86_64__)
107 # define PLAT_amd64_linux 1
108 #elif defined(__powerpc__) && !defined(__powerpc64__)
109 # define PLAT_ppc32_linux 1
110 #elif defined(__powerpc__) && defined(__powerpc64__)
111 # define PLAT_ppc64_linux 1
112 #else
113 /* If we're not compiling for our target platform, don't generate
114 any inline asms. */
115 # if !defined(NVALGRIND)
116 # define NVALGRIND 1
117 # endif
118 #endif
119
120
121 /* ------------------------------------------------------------------ */
122 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
123 /* in here of use to end-users -- skip to the next section. */
124 /* ------------------------------------------------------------------ */
125
126 #if defined(NVALGRIND)
127
128 /* Define NVALGRIND to completely remove the Valgrind magic sequence
129 from the compiled code (analogous to NDEBUG's effects on
130 assert()) */
131 #define VALGRIND_DO_CLIENT_REQUEST( \
132 _zzq_rlval, _zzq_default, _zzq_request, \
133 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
134 { \
135 (_zzq_rlval) = (_zzq_default); \
136 }
137
138 #else /* ! NVALGRIND */
139
140 /* The following defines the magic code sequences which the JITter
141 spots and handles magically. Don't look too closely at them as
142 they will rot your brain.
143
144 The assembly code sequences for all architectures is in this one
145 file. This is because this file must be stand-alone, and we don't
146 want to have multiple files.
147
148 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
149 value gets put in the return slot, so that everything works when
150 this is executed not under Valgrind. Args are passed in a memory
151 block, and so there's no intrinsic limit to the number that could
152 be passed, but it's currently five.
153
154 The macro args are:
155 _zzq_rlval result lvalue
156 _zzq_default default value (result returned when running on real CPU)
157 _zzq_request request code
158 _zzq_arg1..5 request params
159
160 The other two macros are used to support function wrapping, and are
161 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
162 guest's NRADDR pseudo-register and whatever other information is
163 needed to safely run the call original from the wrapper: on
164 ppc64-linux, the R2 value at the divert point is also needed. This
165 information is abstracted into a user-visible type, OrigFn.
166
167 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
168 guest, but guarantees that the branch instruction will not be
169 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
170 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
171 complete inline asm, since it needs to be combined with more magic
172 inline asm stuff to be useful.
173 */
174
175 /* ------------------------- x86-{linux,darwin} ---------------- */
176
177 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
178
179 typedef
180 struct {
181 unsigned int nraddr; /* where's the code? */
182 }
183 OrigFn;
184
185 #define __SPECIAL_INSTRUCTION_PREAMBLE \
186 "roll $3, %%edi ; roll $13, %%edi\n\t" \
187 "roll $29, %%edi ; roll $19, %%edi\n\t"
188
189 #define VALGRIND_DO_CLIENT_REQUEST( \
190 _zzq_rlval, _zzq_default, _zzq_request, \
191 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
192 { volatile unsigned int _zzq_args[6]; \
193 volatile unsigned int _zzq_result; \
194 _zzq_args[0] = (unsigned int)(_zzq_request); \
195 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
196 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
197 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
198 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
199 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
200 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
201 /* %EDX = client_request ( %EAX ) */ \
202 "xchgl %%ebx,%%ebx" \
203 : "=d" (_zzq_result) \
204 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
205 : "cc", "memory" \
206 ); \
207 _zzq_rlval = _zzq_result; \
208 }
209
210 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
211 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
212 volatile unsigned int __addr; \
213 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
214 /* %EAX = guest_NRADDR */ \
215 "xchgl %%ecx,%%ecx" \
216 : "=a" (__addr) \
217 : \
218 : "cc", "memory" \
219 ); \
220 _zzq_orig->nraddr = __addr; \
221 }
222
223 #define VALGRIND_CALL_NOREDIR_EAX \
224 __SPECIAL_INSTRUCTION_PREAMBLE \
225 /* call-noredir *%EAX */ \
226 "xchgl %%edx,%%edx\n\t"
227 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
228
229 /* ------------------------ amd64-{linux,darwin} --------------- */
230
231 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
232
233 typedef
234 struct {
235 unsigned long long int nraddr; /* where's the code? */
236 }
237 OrigFn;
238
239 #define __SPECIAL_INSTRUCTION_PREAMBLE \
240 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
241 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
242
243 #define VALGRIND_DO_CLIENT_REQUEST( \
244 _zzq_rlval, _zzq_default, _zzq_request, \
245 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
246 { volatile unsigned long long int _zzq_args[6]; \
247 volatile unsigned long long int _zzq_result; \
248 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
249 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
250 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
251 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
252 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
253 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
254 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
255 /* %RDX = client_request ( %RAX ) */ \
256 "xchgq %%rbx,%%rbx" \
257 : "=d" (_zzq_result) \
258 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
259 : "cc", "memory" \
260 ); \
261 _zzq_rlval = _zzq_result; \
262 }
263
264 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
265 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
266 volatile unsigned long long int __addr; \
267 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
268 /* %RAX = guest_NRADDR */ \
269 "xchgq %%rcx,%%rcx" \
270 : "=a" (__addr) \
271 : \
272 : "cc", "memory" \
273 ); \
274 _zzq_orig->nraddr = __addr; \
275 }
276
277 #define VALGRIND_CALL_NOREDIR_RAX \
278 __SPECIAL_INSTRUCTION_PREAMBLE \
279 /* call-noredir *%RAX */ \
280 "xchgq %%rdx,%%rdx\n\t"
281 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
282
283 /* ------------------------ ppc32-linux ------------------------ */
284
285 #if defined(PLAT_ppc32_linux)
286
287 typedef
288 struct {
289 unsigned int nraddr; /* where's the code? */
290 }
291 OrigFn;
292
293 #define __SPECIAL_INSTRUCTION_PREAMBLE \
294 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
295 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
296
297 #define VALGRIND_DO_CLIENT_REQUEST( \
298 _zzq_rlval, _zzq_default, _zzq_request, \
299 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
300 \
301 { unsigned int _zzq_args[6]; \
302 unsigned int _zzq_result; \
303 unsigned int* _zzq_ptr; \
304 _zzq_args[0] = (unsigned int)(_zzq_request); \
305 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
306 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
307 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
308 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
309 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
310 _zzq_ptr = _zzq_args; \
311 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
312 "mr 4,%2\n\t" /*ptr*/ \
313 __SPECIAL_INSTRUCTION_PREAMBLE \
314 /* %R3 = client_request ( %R4 ) */ \
315 "or 1,1,1\n\t" \
316 "mr %0,3" /*result*/ \
317 : "=b" (_zzq_result) \
318 : "b" (_zzq_default), "b" (_zzq_ptr) \
319 : "cc", "memory", "r3", "r4"); \
320 _zzq_rlval = _zzq_result; \
321 }
322
323 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
324 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
325 unsigned int __addr; \
326 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
327 /* %R3 = guest_NRADDR */ \
328 "or 2,2,2\n\t" \
329 "mr %0,3" \
330 : "=b" (__addr) \
331 : \
332 : "cc", "memory", "r3" \
333 ); \
334 _zzq_orig->nraddr = __addr; \
335 }
336
337 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
338 __SPECIAL_INSTRUCTION_PREAMBLE \
339 /* branch-and-link-to-noredir *%R11 */ \
340 "or 3,3,3\n\t"
341 #endif /* PLAT_ppc32_linux */
342
343 /* ------------------------ ppc64-linux ------------------------ */
344
345 #if defined(PLAT_ppc64_linux)
346
347 typedef
348 struct {
349 unsigned long long int nraddr; /* where's the code? */
350 unsigned long long int r2; /* what tocptr do we need? */
351 }
352 OrigFn;
353
354 #define __SPECIAL_INSTRUCTION_PREAMBLE \
355 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
356 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
357
358 #define VALGRIND_DO_CLIENT_REQUEST( \
359 _zzq_rlval, _zzq_default, _zzq_request, \
360 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
361 \
362 { unsigned long long int _zzq_args[6]; \
363 register unsigned long long int _zzq_result __asm__("r3"); \
364 register unsigned long long int* _zzq_ptr __asm__("r4"); \
365 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
366 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
367 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
368 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
369 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
370 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
371 _zzq_ptr = _zzq_args; \
372 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
373 /* %R3 = client_request ( %R4 ) */ \
374 "or 1,1,1" \
375 : "=r" (_zzq_result) \
376 : "0" (_zzq_default), "r" (_zzq_ptr) \
377 : "cc", "memory"); \
378 _zzq_rlval = _zzq_result; \
379 }
380
381 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
382 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
383 register unsigned long long int __addr __asm__("r3"); \
384 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
385 /* %R3 = guest_NRADDR */ \
386 "or 2,2,2" \
387 : "=r" (__addr) \
388 : \
389 : "cc", "memory" \
390 ); \
391 _zzq_orig->nraddr = __addr; \
392 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
393 /* %R3 = guest_NRADDR_GPR2 */ \
394 "or 4,4,4" \
395 : "=r" (__addr) \
396 : \
397 : "cc", "memory" \
398 ); \
399 _zzq_orig->r2 = __addr; \
400 }
401
402 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
403 __SPECIAL_INSTRUCTION_PREAMBLE \
404 /* branch-and-link-to-noredir *%R11 */ \
405 "or 3,3,3\n\t"
406
407 #endif /* PLAT_ppc64_linux */
408
409 /* ------------------------ ppc32-aix5 ------------------------- */
410
411 #if defined(PLAT_ppc32_aix5)
412
413 typedef
414 struct {
415 unsigned int nraddr; /* where's the code? */
416 unsigned int r2; /* what tocptr do we need? */
417 }
418 OrigFn;
419
420 #define __SPECIAL_INSTRUCTION_PREAMBLE \
421 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
422 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
423
424 #define VALGRIND_DO_CLIENT_REQUEST( \
425 _zzq_rlval, _zzq_default, _zzq_request, \
426 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
427 \
428 { unsigned int _zzq_args[7]; \
429 register unsigned int _zzq_result; \
430 register unsigned int* _zzq_ptr; \
431 _zzq_args[0] = (unsigned int)(_zzq_request); \
432 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
433 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
434 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
435 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
436 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
437 _zzq_args[6] = (unsigned int)(_zzq_default); \
438 _zzq_ptr = _zzq_args; \
439 __asm__ volatile("mr 4,%1\n\t" \
440 "lwz 3, 24(4)\n\t" \
441 __SPECIAL_INSTRUCTION_PREAMBLE \
442 /* %R3 = client_request ( %R4 ) */ \
443 "or 1,1,1\n\t" \
444 "mr %0,3" \
445 : "=b" (_zzq_result) \
446 : "b" (_zzq_ptr) \
447 : "r3", "r4", "cc", "memory"); \
448 _zzq_rlval = _zzq_result; \
449 }
450
451 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
452 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
453 register unsigned int __addr; \
454 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
455 /* %R3 = guest_NRADDR */ \
456 "or 2,2,2\n\t" \
457 "mr %0,3" \
458 : "=b" (__addr) \
459 : \
460 : "r3", "cc", "memory" \
461 ); \
462 _zzq_orig->nraddr = __addr; \
463 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
464 /* %R3 = guest_NRADDR_GPR2 */ \
465 "or 4,4,4\n\t" \
466 "mr %0,3" \
467 : "=b" (__addr) \
468 : \
469 : "r3", "cc", "memory" \
470 ); \
471 _zzq_orig->r2 = __addr; \
472 }
473
474 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
475 __SPECIAL_INSTRUCTION_PREAMBLE \
476 /* branch-and-link-to-noredir *%R11 */ \
477 "or 3,3,3\n\t"
478
479 #endif /* PLAT_ppc32_aix5 */
480
481 /* ------------------------ ppc64-aix5 ------------------------- */
482
483 #if defined(PLAT_ppc64_aix5)
484
485 typedef
486 struct {
487 unsigned long long int nraddr; /* where's the code? */
488 unsigned long long int r2; /* what tocptr do we need? */
489 }
490 OrigFn;
491
492 #define __SPECIAL_INSTRUCTION_PREAMBLE \
493 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
494 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
495
496 #define VALGRIND_DO_CLIENT_REQUEST( \
497 _zzq_rlval, _zzq_default, _zzq_request, \
498 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
499 \
500 { unsigned long long int _zzq_args[7]; \
501 register unsigned long long int _zzq_result; \
502 register unsigned long long int* _zzq_ptr; \
503 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
504 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
505 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
506 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
507 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
508 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
509 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
510 _zzq_ptr = _zzq_args; \
511 __asm__ volatile("mr 4,%1\n\t" \
512 "ld 3, 48(4)\n\t" \
513 __SPECIAL_INSTRUCTION_PREAMBLE \
514 /* %R3 = client_request ( %R4 ) */ \
515 "or 1,1,1\n\t" \
516 "mr %0,3" \
517 : "=b" (_zzq_result) \
518 : "b" (_zzq_ptr) \
519 : "r3", "r4", "cc", "memory"); \
520 _zzq_rlval = _zzq_result; \
521 }
522
523 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
524 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
525 register unsigned long long int __addr; \
526 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
527 /* %R3 = guest_NRADDR */ \
528 "or 2,2,2\n\t" \
529 "mr %0,3" \
530 : "=b" (__addr) \
531 : \
532 : "r3", "cc", "memory" \
533 ); \
534 _zzq_orig->nraddr = __addr; \
535 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
536 /* %R3 = guest_NRADDR_GPR2 */ \
537 "or 4,4,4\n\t" \
538 "mr %0,3" \
539 : "=b" (__addr) \
540 : \
541 : "r3", "cc", "memory" \
542 ); \
543 _zzq_orig->r2 = __addr; \
544 }
545
546 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
547 __SPECIAL_INSTRUCTION_PREAMBLE \
548 /* branch-and-link-to-noredir *%R11 */ \
549 "or 3,3,3\n\t"
550
551 #endif /* PLAT_ppc64_aix5 */
552
553 /* Insert assembly code for other platforms here... */
554
555 #endif /* NVALGRIND */
556
557
558 /* ------------------------------------------------------------------ */
559 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
560 /* ugly. It's the least-worst tradeoff I can think of. */
561 /* ------------------------------------------------------------------ */
562
563 /* This section defines magic (a.k.a appalling-hack) macros for doing
564 guaranteed-no-redirection macros, so as to get from function
565 wrappers to the functions they are wrapping. The whole point is to
566 construct standard call sequences, but to do the call itself with a
567 special no-redirect call pseudo-instruction that the JIT
568 understands and handles specially. This section is long and
569 repetitious, and I can't see a way to make it shorter.
570
571 The naming scheme is as follows:
572
573 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
574
575 'W' stands for "word" and 'v' for "void". Hence there are
576 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
577 and for each, the possibility of returning a word-typed result, or
578 no result.
579 */
580
581 /* Use these to write the name of your wrapper. NOTE: duplicates
582 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
583
584 /* Use an extra level of macroisation so as to ensure the soname/fnname
585 args are fully macro-expanded before pasting them together. */
586 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
587
588 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
589 VG_CONCAT4(_vgwZU_,soname,_,fnname)
590
591 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
592 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
593
594 /* Use this macro from within a wrapper function to collect the
595 context (address and possibly other info) of the original function.
596 Once you have that you can then use it in one of the CALL_FN_
597 macros. The type of the argument _lval is OrigFn. */
598 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
599
600 /* Derivatives of the main macros below, for calling functions
601 returning void. */
602
603 #define CALL_FN_v_v(fnptr) \
604 do { volatile unsigned long _junk; \
605 CALL_FN_W_v(_junk,fnptr); } while (0)
606
607 #define CALL_FN_v_W(fnptr, arg1) \
608 do { volatile unsigned long _junk; \
609 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
610
611 #define CALL_FN_v_WW(fnptr, arg1,arg2) \
612 do { volatile unsigned long _junk; \
613 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
614
615 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
616 do { volatile unsigned long _junk; \
617 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
618
619 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
620 do { volatile unsigned long _junk; \
621 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
622
623 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
624 do { volatile unsigned long _junk; \
625 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
626
627 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
628 do { volatile unsigned long _junk; \
629 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
630
631 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
632 do { volatile unsigned long _junk; \
633 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
634
635 /* ------------------------- x86-{linux,darwin} ---------------- */
636
637 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
638
639 /* These regs are trashed by the hidden call. No need to mention eax
640 as gcc can already see that, plus causes gcc to bomb. */
641 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
642
643 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
644 long) == 4. */
645
646 #define CALL_FN_W_v(lval, orig) \
647 do { \
648 volatile OrigFn _orig = (orig); \
649 volatile unsigned long _argvec[1]; \
650 volatile unsigned long _res; \
651 _argvec[0] = (unsigned long)_orig.nraddr; \
652 __asm__ volatile( \
653 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
654 VALGRIND_CALL_NOREDIR_EAX \
655 : /*out*/ "=a" (_res) \
656 : /*in*/ "a" (&_argvec[0]) \
657 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
658 ); \
659 lval = (__typeof__(lval)) _res; \
660 } while (0)
661
662 #define CALL_FN_W_W(lval, orig, arg1) \
663 do { \
664 volatile OrigFn _orig = (orig); \
665 volatile unsigned long _argvec[2]; \
666 volatile unsigned long _res; \
667 _argvec[0] = (unsigned long)_orig.nraddr; \
668 _argvec[1] = (unsigned long)(arg1); \
669 __asm__ volatile( \
670 "pushl 4(%%eax)\n\t" \
671 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
672 VALGRIND_CALL_NOREDIR_EAX \
673 "addl $4, %%esp\n" \
674 : /*out*/ "=a" (_res) \
675 : /*in*/ "a" (&_argvec[0]) \
676 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
677 ); \
678 lval = (__typeof__(lval)) _res; \
679 } while (0)
680
681 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
682 do { \
683 volatile OrigFn _orig = (orig); \
684 volatile unsigned long _argvec[3]; \
685 volatile unsigned long _res; \
686 _argvec[0] = (unsigned long)_orig.nraddr; \
687 _argvec[1] = (unsigned long)(arg1); \
688 _argvec[2] = (unsigned long)(arg2); \
689 __asm__ volatile( \
690 "pushl 8(%%eax)\n\t" \
691 "pushl 4(%%eax)\n\t" \
692 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
693 VALGRIND_CALL_NOREDIR_EAX \
694 "addl $8, %%esp\n" \
695 : /*out*/ "=a" (_res) \
696 : /*in*/ "a" (&_argvec[0]) \
697 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
698 ); \
699 lval = (__typeof__(lval)) _res; \
700 } while (0)
701
702 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
703 do { \
704 volatile OrigFn _orig = (orig); \
705 volatile unsigned long _argvec[4]; \
706 volatile unsigned long _res; \
707 _argvec[0] = (unsigned long)_orig.nraddr; \
708 _argvec[1] = (unsigned long)(arg1); \
709 _argvec[2] = (unsigned long)(arg2); \
710 _argvec[3] = (unsigned long)(arg3); \
711 __asm__ volatile( \
712 "pushl 12(%%eax)\n\t" \
713 "pushl 8(%%eax)\n\t" \
714 "pushl 4(%%eax)\n\t" \
715 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
716 VALGRIND_CALL_NOREDIR_EAX \
717 "addl $12, %%esp\n" \
718 : /*out*/ "=a" (_res) \
719 : /*in*/ "a" (&_argvec[0]) \
720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
721 ); \
722 lval = (__typeof__(lval)) _res; \
723 } while (0)
724
725 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
726 do { \
727 volatile OrigFn _orig = (orig); \
728 volatile unsigned long _argvec[5]; \
729 volatile unsigned long _res; \
730 _argvec[0] = (unsigned long)_orig.nraddr; \
731 _argvec[1] = (unsigned long)(arg1); \
732 _argvec[2] = (unsigned long)(arg2); \
733 _argvec[3] = (unsigned long)(arg3); \
734 _argvec[4] = (unsigned long)(arg4); \
735 __asm__ volatile( \
736 "pushl 16(%%eax)\n\t" \
737 "pushl 12(%%eax)\n\t" \
738 "pushl 8(%%eax)\n\t" \
739 "pushl 4(%%eax)\n\t" \
740 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
741 VALGRIND_CALL_NOREDIR_EAX \
742 "addl $16, %%esp\n" \
743 : /*out*/ "=a" (_res) \
744 : /*in*/ "a" (&_argvec[0]) \
745 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
746 ); \
747 lval = (__typeof__(lval)) _res; \
748 } while (0)
749
750 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
751 do { \
752 volatile OrigFn _orig = (orig); \
753 volatile unsigned long _argvec[6]; \
754 volatile unsigned long _res; \
755 _argvec[0] = (unsigned long)_orig.nraddr; \
756 _argvec[1] = (unsigned long)(arg1); \
757 _argvec[2] = (unsigned long)(arg2); \
758 _argvec[3] = (unsigned long)(arg3); \
759 _argvec[4] = (unsigned long)(arg4); \
760 _argvec[5] = (unsigned long)(arg5); \
761 __asm__ volatile( \
762 "pushl 20(%%eax)\n\t" \
763 "pushl 16(%%eax)\n\t" \
764 "pushl 12(%%eax)\n\t" \
765 "pushl 8(%%eax)\n\t" \
766 "pushl 4(%%eax)\n\t" \
767 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
768 VALGRIND_CALL_NOREDIR_EAX \
769 "addl $20, %%esp\n" \
770 : /*out*/ "=a" (_res) \
771 : /*in*/ "a" (&_argvec[0]) \
772 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
773 ); \
774 lval = (__typeof__(lval)) _res; \
775 } while (0)
776
777 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
778 do { \
779 volatile OrigFn _orig = (orig); \
780 volatile unsigned long _argvec[7]; \
781 volatile unsigned long _res; \
782 _argvec[0] = (unsigned long)_orig.nraddr; \
783 _argvec[1] = (unsigned long)(arg1); \
784 _argvec[2] = (unsigned long)(arg2); \
785 _argvec[3] = (unsigned long)(arg3); \
786 _argvec[4] = (unsigned long)(arg4); \
787 _argvec[5] = (unsigned long)(arg5); \
788 _argvec[6] = (unsigned long)(arg6); \
789 __asm__ volatile( \
790 "pushl 24(%%eax)\n\t" \
791 "pushl 20(%%eax)\n\t" \
792 "pushl 16(%%eax)\n\t" \
793 "pushl 12(%%eax)\n\t" \
794 "pushl 8(%%eax)\n\t" \
795 "pushl 4(%%eax)\n\t" \
796 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
797 VALGRIND_CALL_NOREDIR_EAX \
798 "addl $24, %%esp\n" \
799 : /*out*/ "=a" (_res) \
800 : /*in*/ "a" (&_argvec[0]) \
801 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
802 ); \
803 lval = (__typeof__(lval)) _res; \
804 } while (0)
805
806 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
807 arg7) \
808 do { \
809 volatile OrigFn _orig = (orig); \
810 volatile unsigned long _argvec[8]; \
811 volatile unsigned long _res; \
812 _argvec[0] = (unsigned long)_orig.nraddr; \
813 _argvec[1] = (unsigned long)(arg1); \
814 _argvec[2] = (unsigned long)(arg2); \
815 _argvec[3] = (unsigned long)(arg3); \
816 _argvec[4] = (unsigned long)(arg4); \
817 _argvec[5] = (unsigned long)(arg5); \
818 _argvec[6] = (unsigned long)(arg6); \
819 _argvec[7] = (unsigned long)(arg7); \
820 __asm__ volatile( \
821 "pushl 28(%%eax)\n\t" \
822 "pushl 24(%%eax)\n\t" \
823 "pushl 20(%%eax)\n\t" \
824 "pushl 16(%%eax)\n\t" \
825 "pushl 12(%%eax)\n\t" \
826 "pushl 8(%%eax)\n\t" \
827 "pushl 4(%%eax)\n\t" \
828 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
829 VALGRIND_CALL_NOREDIR_EAX \
830 "addl $28, %%esp\n" \
831 : /*out*/ "=a" (_res) \
832 : /*in*/ "a" (&_argvec[0]) \
833 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
834 ); \
835 lval = (__typeof__(lval)) _res; \
836 } while (0)
837
838 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
839 arg7,arg8) \
840 do { \
841 volatile OrigFn _orig = (orig); \
842 volatile unsigned long _argvec[9]; \
843 volatile unsigned long _res; \
844 _argvec[0] = (unsigned long)_orig.nraddr; \
845 _argvec[1] = (unsigned long)(arg1); \
846 _argvec[2] = (unsigned long)(arg2); \
847 _argvec[3] = (unsigned long)(arg3); \
848 _argvec[4] = (unsigned long)(arg4); \
849 _argvec[5] = (unsigned long)(arg5); \
850 _argvec[6] = (unsigned long)(arg6); \
851 _argvec[7] = (unsigned long)(arg7); \
852 _argvec[8] = (unsigned long)(arg8); \
853 __asm__ volatile( \
854 "pushl 32(%%eax)\n\t" \
855 "pushl 28(%%eax)\n\t" \
856 "pushl 24(%%eax)\n\t" \
857 "pushl 20(%%eax)\n\t" \
858 "pushl 16(%%eax)\n\t" \
859 "pushl 12(%%eax)\n\t" \
860 "pushl 8(%%eax)\n\t" \
861 "pushl 4(%%eax)\n\t" \
862 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
863 VALGRIND_CALL_NOREDIR_EAX \
864 "addl $32, %%esp\n" \
865 : /*out*/ "=a" (_res) \
866 : /*in*/ "a" (&_argvec[0]) \
867 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
868 ); \
869 lval = (__typeof__(lval)) _res; \
870 } while (0)
871
872 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
873 arg7,arg8,arg9) \
874 do { \
875 volatile OrigFn _orig = (orig); \
876 volatile unsigned long _argvec[10]; \
877 volatile unsigned long _res; \
878 _argvec[0] = (unsigned long)_orig.nraddr; \
879 _argvec[1] = (unsigned long)(arg1); \
880 _argvec[2] = (unsigned long)(arg2); \
881 _argvec[3] = (unsigned long)(arg3); \
882 _argvec[4] = (unsigned long)(arg4); \
883 _argvec[5] = (unsigned long)(arg5); \
884 _argvec[6] = (unsigned long)(arg6); \
885 _argvec[7] = (unsigned long)(arg7); \
886 _argvec[8] = (unsigned long)(arg8); \
887 _argvec[9] = (unsigned long)(arg9); \
888 __asm__ volatile( \
889 "pushl 36(%%eax)\n\t" \
890 "pushl 32(%%eax)\n\t" \
891 "pushl 28(%%eax)\n\t" \
892 "pushl 24(%%eax)\n\t" \
893 "pushl 20(%%eax)\n\t" \
894 "pushl 16(%%eax)\n\t" \
895 "pushl 12(%%eax)\n\t" \
896 "pushl 8(%%eax)\n\t" \
897 "pushl 4(%%eax)\n\t" \
898 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
899 VALGRIND_CALL_NOREDIR_EAX \
900 "addl $36, %%esp\n" \
901 : /*out*/ "=a" (_res) \
902 : /*in*/ "a" (&_argvec[0]) \
903 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
904 ); \
905 lval = (__typeof__(lval)) _res; \
906 } while (0)
907
908 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
909 arg7,arg8,arg9,arg10) \
910 do { \
911 volatile OrigFn _orig = (orig); \
912 volatile unsigned long _argvec[11]; \
913 volatile unsigned long _res; \
914 _argvec[0] = (unsigned long)_orig.nraddr; \
915 _argvec[1] = (unsigned long)(arg1); \
916 _argvec[2] = (unsigned long)(arg2); \
917 _argvec[3] = (unsigned long)(arg3); \
918 _argvec[4] = (unsigned long)(arg4); \
919 _argvec[5] = (unsigned long)(arg5); \
920 _argvec[6] = (unsigned long)(arg6); \
921 _argvec[7] = (unsigned long)(arg7); \
922 _argvec[8] = (unsigned long)(arg8); \
923 _argvec[9] = (unsigned long)(arg9); \
924 _argvec[10] = (unsigned long)(arg10); \
925 __asm__ volatile( \
926 "pushl 40(%%eax)\n\t" \
927 "pushl 36(%%eax)\n\t" \
928 "pushl 32(%%eax)\n\t" \
929 "pushl 28(%%eax)\n\t" \
930 "pushl 24(%%eax)\n\t" \
931 "pushl 20(%%eax)\n\t" \
932 "pushl 16(%%eax)\n\t" \
933 "pushl 12(%%eax)\n\t" \
934 "pushl 8(%%eax)\n\t" \
935 "pushl 4(%%eax)\n\t" \
936 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
937 VALGRIND_CALL_NOREDIR_EAX \
938 "addl $40, %%esp\n" \
939 : /*out*/ "=a" (_res) \
940 : /*in*/ "a" (&_argvec[0]) \
941 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
942 ); \
943 lval = (__typeof__(lval)) _res; \
944 } while (0)
945
946 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
947 arg6,arg7,arg8,arg9,arg10, \
948 arg11) \
949 do { \
950 volatile OrigFn _orig = (orig); \
951 volatile unsigned long _argvec[12]; \
952 volatile unsigned long _res; \
953 _argvec[0] = (unsigned long)_orig.nraddr; \
954 _argvec[1] = (unsigned long)(arg1); \
955 _argvec[2] = (unsigned long)(arg2); \
956 _argvec[3] = (unsigned long)(arg3); \
957 _argvec[4] = (unsigned long)(arg4); \
958 _argvec[5] = (unsigned long)(arg5); \
959 _argvec[6] = (unsigned long)(arg6); \
960 _argvec[7] = (unsigned long)(arg7); \
961 _argvec[8] = (unsigned long)(arg8); \
962 _argvec[9] = (unsigned long)(arg9); \
963 _argvec[10] = (unsigned long)(arg10); \
964 _argvec[11] = (unsigned long)(arg11); \
965 __asm__ volatile( \
966 "pushl 44(%%eax)\n\t" \
967 "pushl 40(%%eax)\n\t" \
968 "pushl 36(%%eax)\n\t" \
969 "pushl 32(%%eax)\n\t" \
970 "pushl 28(%%eax)\n\t" \
971 "pushl 24(%%eax)\n\t" \
972 "pushl 20(%%eax)\n\t" \
973 "pushl 16(%%eax)\n\t" \
974 "pushl 12(%%eax)\n\t" \
975 "pushl 8(%%eax)\n\t" \
976 "pushl 4(%%eax)\n\t" \
977 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
978 VALGRIND_CALL_NOREDIR_EAX \
979 "addl $44, %%esp\n" \
980 : /*out*/ "=a" (_res) \
981 : /*in*/ "a" (&_argvec[0]) \
982 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
983 ); \
984 lval = (__typeof__(lval)) _res; \
985 } while (0)
986
987 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
988 arg6,arg7,arg8,arg9,arg10, \
989 arg11,arg12) \
990 do { \
991 volatile OrigFn _orig = (orig); \
992 volatile unsigned long _argvec[13]; \
993 volatile unsigned long _res; \
994 _argvec[0] = (unsigned long)_orig.nraddr; \
995 _argvec[1] = (unsigned long)(arg1); \
996 _argvec[2] = (unsigned long)(arg2); \
997 _argvec[3] = (unsigned long)(arg3); \
998 _argvec[4] = (unsigned long)(arg4); \
999 _argvec[5] = (unsigned long)(arg5); \
1000 _argvec[6] = (unsigned long)(arg6); \
1001 _argvec[7] = (unsigned long)(arg7); \
1002 _argvec[8] = (unsigned long)(arg8); \
1003 _argvec[9] = (unsigned long)(arg9); \
1004 _argvec[10] = (unsigned long)(arg10); \
1005 _argvec[11] = (unsigned long)(arg11); \
1006 _argvec[12] = (unsigned long)(arg12); \
1007 __asm__ volatile( \
1008 "pushl 48(%%eax)\n\t" \
1009 "pushl 44(%%eax)\n\t" \
1010 "pushl 40(%%eax)\n\t" \
1011 "pushl 36(%%eax)\n\t" \
1012 "pushl 32(%%eax)\n\t" \
1013 "pushl 28(%%eax)\n\t" \
1014 "pushl 24(%%eax)\n\t" \
1015 "pushl 20(%%eax)\n\t" \
1016 "pushl 16(%%eax)\n\t" \
1017 "pushl 12(%%eax)\n\t" \
1018 "pushl 8(%%eax)\n\t" \
1019 "pushl 4(%%eax)\n\t" \
1020 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1021 VALGRIND_CALL_NOREDIR_EAX \
1022 "addl $48, %%esp\n" \
1023 : /*out*/ "=a" (_res) \
1024 : /*in*/ "a" (&_argvec[0]) \
1025 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1026 ); \
1027 lval = (__typeof__(lval)) _res; \
1028 } while (0)
1029
1030 #endif /* PLAT_x86_linux || PLAT_x86_darwin */
1031
1032 /* ------------------------ amd64-{linux,darwin} --------------- */
1033
1034 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
1035
1036 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1037
1038 /* These regs are trashed by the hidden call. */
1039 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1040 "rdi", "r8", "r9", "r10", "r11"
1041
1042 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1043 long) == 8. */
1044
1045 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1046 macros. In order not to trash the stack redzone, we need to drop
1047 %rsp by 128 before the hidden call, and restore afterwards. The
1048 nastyness is that it is only by luck that the stack still appears
1049 to be unwindable during the hidden call - since then the behaviour
1050 of any routine using this macro does not match what the CFI data
1051 says. Sigh.
1052
1053 Why is this important? Imagine that a wrapper has a stack
1054 allocated local, and passes to the hidden call, a pointer to it.
1055 Because gcc does not know about the hidden call, it may allocate
1056 that local in the redzone. Unfortunately the hidden call may then
1057 trash it before it comes to use it. So we must step clear of the
1058 redzone, for the duration of the hidden call, to make it safe.
1059
1060 Probably the same problem afflicts the other redzone-style ABIs too
1061 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1062 self describing (none of this CFI nonsense) so at least messing
1063 with the stack pointer doesn't give a danger of non-unwindable
1064 stack. */
1065
1066 #define CALL_FN_W_v(lval, orig) \
1067 do { \
1068 volatile OrigFn _orig = (orig); \
1069 volatile unsigned long _argvec[1]; \
1070 volatile unsigned long _res; \
1071 _argvec[0] = (unsigned long)_orig.nraddr; \
1072 __asm__ volatile( \
1073 "subq $128,%%rsp\n\t" \
1074 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1075 VALGRIND_CALL_NOREDIR_RAX \
1076 "addq $128,%%rsp\n\t" \
1077 : /*out*/ "=a" (_res) \
1078 : /*in*/ "a" (&_argvec[0]) \
1079 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1080 ); \
1081 lval = (__typeof__(lval)) _res; \
1082 } while (0)
1083
1084 #define CALL_FN_W_W(lval, orig, arg1) \
1085 do { \
1086 volatile OrigFn _orig = (orig); \
1087 volatile unsigned long _argvec[2]; \
1088 volatile unsigned long _res; \
1089 _argvec[0] = (unsigned long)_orig.nraddr; \
1090 _argvec[1] = (unsigned long)(arg1); \
1091 __asm__ volatile( \
1092 "subq $128,%%rsp\n\t" \
1093 "movq 8(%%rax), %%rdi\n\t" \
1094 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1095 VALGRIND_CALL_NOREDIR_RAX \
1096 "addq $128,%%rsp\n\t" \
1097 : /*out*/ "=a" (_res) \
1098 : /*in*/ "a" (&_argvec[0]) \
1099 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1100 ); \
1101 lval = (__typeof__(lval)) _res; \
1102 } while (0)
1103
1104 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1105 do { \
1106 volatile OrigFn _orig = (orig); \
1107 volatile unsigned long _argvec[3]; \
1108 volatile unsigned long _res; \
1109 _argvec[0] = (unsigned long)_orig.nraddr; \
1110 _argvec[1] = (unsigned long)(arg1); \
1111 _argvec[2] = (unsigned long)(arg2); \
1112 __asm__ volatile( \
1113 "subq $128,%%rsp\n\t" \
1114 "movq 16(%%rax), %%rsi\n\t" \
1115 "movq 8(%%rax), %%rdi\n\t" \
1116 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1117 VALGRIND_CALL_NOREDIR_RAX \
1118 "addq $128,%%rsp\n\t" \
1119 : /*out*/ "=a" (_res) \
1120 : /*in*/ "a" (&_argvec[0]) \
1121 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1122 ); \
1123 lval = (__typeof__(lval)) _res; \
1124 } while (0)
1125
1126 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1127 do { \
1128 volatile OrigFn _orig = (orig); \
1129 volatile unsigned long _argvec[4]; \
1130 volatile unsigned long _res; \
1131 _argvec[0] = (unsigned long)_orig.nraddr; \
1132 _argvec[1] = (unsigned long)(arg1); \
1133 _argvec[2] = (unsigned long)(arg2); \
1134 _argvec[3] = (unsigned long)(arg3); \
1135 __asm__ volatile( \
1136 "subq $128,%%rsp\n\t" \
1137 "movq 24(%%rax), %%rdx\n\t" \
1138 "movq 16(%%rax), %%rsi\n\t" \
1139 "movq 8(%%rax), %%rdi\n\t" \
1140 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1141 VALGRIND_CALL_NOREDIR_RAX \
1142 "addq $128,%%rsp\n\t" \
1143 : /*out*/ "=a" (_res) \
1144 : /*in*/ "a" (&_argvec[0]) \
1145 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1146 ); \
1147 lval = (__typeof__(lval)) _res; \
1148 } while (0)
1149
1150 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1151 do { \
1152 volatile OrigFn _orig = (orig); \
1153 volatile unsigned long _argvec[5]; \
1154 volatile unsigned long _res; \
1155 _argvec[0] = (unsigned long)_orig.nraddr; \
1156 _argvec[1] = (unsigned long)(arg1); \
1157 _argvec[2] = (unsigned long)(arg2); \
1158 _argvec[3] = (unsigned long)(arg3); \
1159 _argvec[4] = (unsigned long)(arg4); \
1160 __asm__ volatile( \
1161 "subq $128,%%rsp\n\t" \
1162 "movq 32(%%rax), %%rcx\n\t" \
1163 "movq 24(%%rax), %%rdx\n\t" \
1164 "movq 16(%%rax), %%rsi\n\t" \
1165 "movq 8(%%rax), %%rdi\n\t" \
1166 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1167 VALGRIND_CALL_NOREDIR_RAX \
1168 "addq $128,%%rsp\n\t" \
1169 : /*out*/ "=a" (_res) \
1170 : /*in*/ "a" (&_argvec[0]) \
1171 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1172 ); \
1173 lval = (__typeof__(lval)) _res; \
1174 } while (0)
1175
1176 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1177 do { \
1178 volatile OrigFn _orig = (orig); \
1179 volatile unsigned long _argvec[6]; \
1180 volatile unsigned long _res; \
1181 _argvec[0] = (unsigned long)_orig.nraddr; \
1182 _argvec[1] = (unsigned long)(arg1); \
1183 _argvec[2] = (unsigned long)(arg2); \
1184 _argvec[3] = (unsigned long)(arg3); \
1185 _argvec[4] = (unsigned long)(arg4); \
1186 _argvec[5] = (unsigned long)(arg5); \
1187 __asm__ volatile( \
1188 "subq $128,%%rsp\n\t" \
1189 "movq 40(%%rax), %%r8\n\t" \
1190 "movq 32(%%rax), %%rcx\n\t" \
1191 "movq 24(%%rax), %%rdx\n\t" \
1192 "movq 16(%%rax), %%rsi\n\t" \
1193 "movq 8(%%rax), %%rdi\n\t" \
1194 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1195 VALGRIND_CALL_NOREDIR_RAX \
1196 "addq $128,%%rsp\n\t" \
1197 : /*out*/ "=a" (_res) \
1198 : /*in*/ "a" (&_argvec[0]) \
1199 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1200 ); \
1201 lval = (__typeof__(lval)) _res; \
1202 } while (0)
1203
1204 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1205 do { \
1206 volatile OrigFn _orig = (orig); \
1207 volatile unsigned long _argvec[7]; \
1208 volatile unsigned long _res; \
1209 _argvec[0] = (unsigned long)_orig.nraddr; \
1210 _argvec[1] = (unsigned long)(arg1); \
1211 _argvec[2] = (unsigned long)(arg2); \
1212 _argvec[3] = (unsigned long)(arg3); \
1213 _argvec[4] = (unsigned long)(arg4); \
1214 _argvec[5] = (unsigned long)(arg5); \
1215 _argvec[6] = (unsigned long)(arg6); \
1216 __asm__ volatile( \
1217 "subq $128,%%rsp\n\t" \
1218 "movq 48(%%rax), %%r9\n\t" \
1219 "movq 40(%%rax), %%r8\n\t" \
1220 "movq 32(%%rax), %%rcx\n\t" \
1221 "movq 24(%%rax), %%rdx\n\t" \
1222 "movq 16(%%rax), %%rsi\n\t" \
1223 "movq 8(%%rax), %%rdi\n\t" \
1224 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1225 "addq $128,%%rsp\n\t" \
1226 VALGRIND_CALL_NOREDIR_RAX \
1227 : /*out*/ "=a" (_res) \
1228 : /*in*/ "a" (&_argvec[0]) \
1229 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1230 ); \
1231 lval = (__typeof__(lval)) _res; \
1232 } while (0)
1233
1234 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1235 arg7) \
1236 do { \
1237 volatile OrigFn _orig = (orig); \
1238 volatile unsigned long _argvec[8]; \
1239 volatile unsigned long _res; \
1240 _argvec[0] = (unsigned long)_orig.nraddr; \
1241 _argvec[1] = (unsigned long)(arg1); \
1242 _argvec[2] = (unsigned long)(arg2); \
1243 _argvec[3] = (unsigned long)(arg3); \
1244 _argvec[4] = (unsigned long)(arg4); \
1245 _argvec[5] = (unsigned long)(arg5); \
1246 _argvec[6] = (unsigned long)(arg6); \
1247 _argvec[7] = (unsigned long)(arg7); \
1248 __asm__ volatile( \
1249 "subq $128,%%rsp\n\t" \
1250 "pushq 56(%%rax)\n\t" \
1251 "movq 48(%%rax), %%r9\n\t" \
1252 "movq 40(%%rax), %%r8\n\t" \
1253 "movq 32(%%rax), %%rcx\n\t" \
1254 "movq 24(%%rax), %%rdx\n\t" \
1255 "movq 16(%%rax), %%rsi\n\t" \
1256 "movq 8(%%rax), %%rdi\n\t" \
1257 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1258 VALGRIND_CALL_NOREDIR_RAX \
1259 "addq $8, %%rsp\n" \
1260 "addq $128,%%rsp\n\t" \
1261 : /*out*/ "=a" (_res) \
1262 : /*in*/ "a" (&_argvec[0]) \
1263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1264 ); \
1265 lval = (__typeof__(lval)) _res; \
1266 } while (0)
1267
1268 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1269 arg7,arg8) \
1270 do { \
1271 volatile OrigFn _orig = (orig); \
1272 volatile unsigned long _argvec[9]; \
1273 volatile unsigned long _res; \
1274 _argvec[0] = (unsigned long)_orig.nraddr; \
1275 _argvec[1] = (unsigned long)(arg1); \
1276 _argvec[2] = (unsigned long)(arg2); \
1277 _argvec[3] = (unsigned long)(arg3); \
1278 _argvec[4] = (unsigned long)(arg4); \
1279 _argvec[5] = (unsigned long)(arg5); \
1280 _argvec[6] = (unsigned long)(arg6); \
1281 _argvec[7] = (unsigned long)(arg7); \
1282 _argvec[8] = (unsigned long)(arg8); \
1283 __asm__ volatile( \
1284 "subq $128,%%rsp\n\t" \
1285 "pushq 64(%%rax)\n\t" \
1286 "pushq 56(%%rax)\n\t" \
1287 "movq 48(%%rax), %%r9\n\t" \
1288 "movq 40(%%rax), %%r8\n\t" \
1289 "movq 32(%%rax), %%rcx\n\t" \
1290 "movq 24(%%rax), %%rdx\n\t" \
1291 "movq 16(%%rax), %%rsi\n\t" \
1292 "movq 8(%%rax), %%rdi\n\t" \
1293 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1294 VALGRIND_CALL_NOREDIR_RAX \
1295 "addq $16, %%rsp\n" \
1296 "addq $128,%%rsp\n\t" \
1297 : /*out*/ "=a" (_res) \
1298 : /*in*/ "a" (&_argvec[0]) \
1299 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1300 ); \
1301 lval = (__typeof__(lval)) _res; \
1302 } while (0)
1303
1304 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1305 arg7,arg8,arg9) \
1306 do { \
1307 volatile OrigFn _orig = (orig); \
1308 volatile unsigned long _argvec[10]; \
1309 volatile unsigned long _res; \
1310 _argvec[0] = (unsigned long)_orig.nraddr; \
1311 _argvec[1] = (unsigned long)(arg1); \
1312 _argvec[2] = (unsigned long)(arg2); \
1313 _argvec[3] = (unsigned long)(arg3); \
1314 _argvec[4] = (unsigned long)(arg4); \
1315 _argvec[5] = (unsigned long)(arg5); \
1316 _argvec[6] = (unsigned long)(arg6); \
1317 _argvec[7] = (unsigned long)(arg7); \
1318 _argvec[8] = (unsigned long)(arg8); \
1319 _argvec[9] = (unsigned long)(arg9); \
1320 __asm__ volatile( \
1321 "subq $128,%%rsp\n\t" \
1322 "pushq 72(%%rax)\n\t" \
1323 "pushq 64(%%rax)\n\t" \
1324 "pushq 56(%%rax)\n\t" \
1325 "movq 48(%%rax), %%r9\n\t" \
1326 "movq 40(%%rax), %%r8\n\t" \
1327 "movq 32(%%rax), %%rcx\n\t" \
1328 "movq 24(%%rax), %%rdx\n\t" \
1329 "movq 16(%%rax), %%rsi\n\t" \
1330 "movq 8(%%rax), %%rdi\n\t" \
1331 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1332 VALGRIND_CALL_NOREDIR_RAX \
1333 "addq $24, %%rsp\n" \
1334 "addq $128,%%rsp\n\t" \
1335 : /*out*/ "=a" (_res) \
1336 : /*in*/ "a" (&_argvec[0]) \
1337 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1338 ); \
1339 lval = (__typeof__(lval)) _res; \
1340 } while (0)
1341
1342 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1343 arg7,arg8,arg9,arg10) \
1344 do { \
1345 volatile OrigFn _orig = (orig); \
1346 volatile unsigned long _argvec[11]; \
1347 volatile unsigned long _res; \
1348 _argvec[0] = (unsigned long)_orig.nraddr; \
1349 _argvec[1] = (unsigned long)(arg1); \
1350 _argvec[2] = (unsigned long)(arg2); \
1351 _argvec[3] = (unsigned long)(arg3); \
1352 _argvec[4] = (unsigned long)(arg4); \
1353 _argvec[5] = (unsigned long)(arg5); \
1354 _argvec[6] = (unsigned long)(arg6); \
1355 _argvec[7] = (unsigned long)(arg7); \
1356 _argvec[8] = (unsigned long)(arg8); \
1357 _argvec[9] = (unsigned long)(arg9); \
1358 _argvec[10] = (unsigned long)(arg10); \
1359 __asm__ volatile( \
1360 "subq $128,%%rsp\n\t" \
1361 "pushq 80(%%rax)\n\t" \
1362 "pushq 72(%%rax)\n\t" \
1363 "pushq 64(%%rax)\n\t" \
1364 "pushq 56(%%rax)\n\t" \
1365 "movq 48(%%rax), %%r9\n\t" \
1366 "movq 40(%%rax), %%r8\n\t" \
1367 "movq 32(%%rax), %%rcx\n\t" \
1368 "movq 24(%%rax), %%rdx\n\t" \
1369 "movq 16(%%rax), %%rsi\n\t" \
1370 "movq 8(%%rax), %%rdi\n\t" \
1371 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1372 VALGRIND_CALL_NOREDIR_RAX \
1373 "addq $32, %%rsp\n" \
1374 "addq $128,%%rsp\n\t" \
1375 : /*out*/ "=a" (_res) \
1376 : /*in*/ "a" (&_argvec[0]) \
1377 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1378 ); \
1379 lval = (__typeof__(lval)) _res; \
1380 } while (0)
1381
1382 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1383 arg7,arg8,arg9,arg10,arg11) \
1384 do { \
1385 volatile OrigFn _orig = (orig); \
1386 volatile unsigned long _argvec[12]; \
1387 volatile unsigned long _res; \
1388 _argvec[0] = (unsigned long)_orig.nraddr; \
1389 _argvec[1] = (unsigned long)(arg1); \
1390 _argvec[2] = (unsigned long)(arg2); \
1391 _argvec[3] = (unsigned long)(arg3); \
1392 _argvec[4] = (unsigned long)(arg4); \
1393 _argvec[5] = (unsigned long)(arg5); \
1394 _argvec[6] = (unsigned long)(arg6); \
1395 _argvec[7] = (unsigned long)(arg7); \
1396 _argvec[8] = (unsigned long)(arg8); \
1397 _argvec[9] = (unsigned long)(arg9); \
1398 _argvec[10] = (unsigned long)(arg10); \
1399 _argvec[11] = (unsigned long)(arg11); \
1400 __asm__ volatile( \
1401 "subq $128,%%rsp\n\t" \
1402 "pushq 88(%%rax)\n\t" \
1403 "pushq 80(%%rax)\n\t" \
1404 "pushq 72(%%rax)\n\t" \
1405 "pushq 64(%%rax)\n\t" \
1406 "pushq 56(%%rax)\n\t" \
1407 "movq 48(%%rax), %%r9\n\t" \
1408 "movq 40(%%rax), %%r8\n\t" \
1409 "movq 32(%%rax), %%rcx\n\t" \
1410 "movq 24(%%rax), %%rdx\n\t" \
1411 "movq 16(%%rax), %%rsi\n\t" \
1412 "movq 8(%%rax), %%rdi\n\t" \
1413 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1414 VALGRIND_CALL_NOREDIR_RAX \
1415 "addq $40, %%rsp\n" \
1416 "addq $128,%%rsp\n\t" \
1417 : /*out*/ "=a" (_res) \
1418 : /*in*/ "a" (&_argvec[0]) \
1419 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1420 ); \
1421 lval = (__typeof__(lval)) _res; \
1422 } while (0)
1423
1424 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1425 arg7,arg8,arg9,arg10,arg11,arg12) \
1426 do { \
1427 volatile OrigFn _orig = (orig); \
1428 volatile unsigned long _argvec[13]; \
1429 volatile unsigned long _res; \
1430 _argvec[0] = (unsigned long)_orig.nraddr; \
1431 _argvec[1] = (unsigned long)(arg1); \
1432 _argvec[2] = (unsigned long)(arg2); \
1433 _argvec[3] = (unsigned long)(arg3); \
1434 _argvec[4] = (unsigned long)(arg4); \
1435 _argvec[5] = (unsigned long)(arg5); \
1436 _argvec[6] = (unsigned long)(arg6); \
1437 _argvec[7] = (unsigned long)(arg7); \
1438 _argvec[8] = (unsigned long)(arg8); \
1439 _argvec[9] = (unsigned long)(arg9); \
1440 _argvec[10] = (unsigned long)(arg10); \
1441 _argvec[11] = (unsigned long)(arg11); \
1442 _argvec[12] = (unsigned long)(arg12); \
1443 __asm__ volatile( \
1444 "subq $128,%%rsp\n\t" \
1445 "pushq 96(%%rax)\n\t" \
1446 "pushq 88(%%rax)\n\t" \
1447 "pushq 80(%%rax)\n\t" \
1448 "pushq 72(%%rax)\n\t" \
1449 "pushq 64(%%rax)\n\t" \
1450 "pushq 56(%%rax)\n\t" \
1451 "movq 48(%%rax), %%r9\n\t" \
1452 "movq 40(%%rax), %%r8\n\t" \
1453 "movq 32(%%rax), %%rcx\n\t" \
1454 "movq 24(%%rax), %%rdx\n\t" \
1455 "movq 16(%%rax), %%rsi\n\t" \
1456 "movq 8(%%rax), %%rdi\n\t" \
1457 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1458 VALGRIND_CALL_NOREDIR_RAX \
1459 "addq $48, %%rsp\n" \
1460 "addq $128,%%rsp\n\t" \
1461 : /*out*/ "=a" (_res) \
1462 : /*in*/ "a" (&_argvec[0]) \
1463 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1464 ); \
1465 lval = (__typeof__(lval)) _res; \
1466 } while (0)
1467
1468 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
1469
1470 /* ------------------------ ppc32-linux ------------------------ */
1471
1472 #if defined(PLAT_ppc32_linux)
1473
1474 /* This is useful for finding out about the on-stack stuff:
1475
1476 extern int f9 ( int,int,int,int,int,int,int,int,int );
1477 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1478 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1479 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1480
1481 int g9 ( void ) {
1482 return f9(11,22,33,44,55,66,77,88,99);
1483 }
1484 int g10 ( void ) {
1485 return f10(11,22,33,44,55,66,77,88,99,110);
1486 }
1487 int g11 ( void ) {
1488 return f11(11,22,33,44,55,66,77,88,99,110,121);
1489 }
1490 int g12 ( void ) {
1491 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1492 }
1493 */
1494
1495 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1496
1497 /* These regs are trashed by the hidden call. */
1498 #define __CALLER_SAVED_REGS \
1499 "lr", "ctr", "xer", \
1500 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1501 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1502 "r11", "r12", "r13"
1503
1504 /* These CALL_FN_ macros assume that on ppc32-linux,
1505 sizeof(unsigned long) == 4. */
1506
1507 #define CALL_FN_W_v(lval, orig) \
1508 do { \
1509 volatile OrigFn _orig = (orig); \
1510 volatile unsigned long _argvec[1]; \
1511 volatile unsigned long _res; \
1512 _argvec[0] = (unsigned long)_orig.nraddr; \
1513 __asm__ volatile( \
1514 "mr 11,%1\n\t" \
1515 "lwz 11,0(11)\n\t" /* target->r11 */ \
1516 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1517 "mr %0,3" \
1518 : /*out*/ "=r" (_res) \
1519 : /*in*/ "r" (&_argvec[0]) \
1520 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1521 ); \
1522 lval = (__typeof__(lval)) _res; \
1523 } while (0)
1524
1525 #define CALL_FN_W_W(lval, orig, arg1) \
1526 do { \
1527 volatile OrigFn _orig = (orig); \
1528 volatile unsigned long _argvec[2]; \
1529 volatile unsigned long _res; \
1530 _argvec[0] = (unsigned long)_orig.nraddr; \
1531 _argvec[1] = (unsigned long)arg1; \
1532 __asm__ volatile( \
1533 "mr 11,%1\n\t" \
1534 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1535 "lwz 11,0(11)\n\t" /* target->r11 */ \
1536 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1537 "mr %0,3" \
1538 : /*out*/ "=r" (_res) \
1539 : /*in*/ "r" (&_argvec[0]) \
1540 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1541 ); \
1542 lval = (__typeof__(lval)) _res; \
1543 } while (0)
1544
1545 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1546 do { \
1547 volatile OrigFn _orig = (orig); \
1548 volatile unsigned long _argvec[3]; \
1549 volatile unsigned long _res; \
1550 _argvec[0] = (unsigned long)_orig.nraddr; \
1551 _argvec[1] = (unsigned long)arg1; \
1552 _argvec[2] = (unsigned long)arg2; \
1553 __asm__ volatile( \
1554 "mr 11,%1\n\t" \
1555 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1556 "lwz 4,8(11)\n\t" \
1557 "lwz 11,0(11)\n\t" /* target->r11 */ \
1558 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1559 "mr %0,3" \
1560 : /*out*/ "=r" (_res) \
1561 : /*in*/ "r" (&_argvec[0]) \
1562 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1563 ); \
1564 lval = (__typeof__(lval)) _res; \
1565 } while (0)
1566
1567 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1568 do { \
1569 volatile OrigFn _orig = (orig); \
1570 volatile unsigned long _argvec[4]; \
1571 volatile unsigned long _res; \
1572 _argvec[0] = (unsigned long)_orig.nraddr; \
1573 _argvec[1] = (unsigned long)arg1; \
1574 _argvec[2] = (unsigned long)arg2; \
1575 _argvec[3] = (unsigned long)arg3; \
1576 __asm__ volatile( \
1577 "mr 11,%1\n\t" \
1578 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1579 "lwz 4,8(11)\n\t" \
1580 "lwz 5,12(11)\n\t" \
1581 "lwz 11,0(11)\n\t" /* target->r11 */ \
1582 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1583 "mr %0,3" \
1584 : /*out*/ "=r" (_res) \
1585 : /*in*/ "r" (&_argvec[0]) \
1586 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1587 ); \
1588 lval = (__typeof__(lval)) _res; \
1589 } while (0)
1590
1591 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1592 do { \
1593 volatile OrigFn _orig = (orig); \
1594 volatile unsigned long _argvec[5]; \
1595 volatile unsigned long _res; \
1596 _argvec[0] = (unsigned long)_orig.nraddr; \
1597 _argvec[1] = (unsigned long)arg1; \
1598 _argvec[2] = (unsigned long)arg2; \
1599 _argvec[3] = (unsigned long)arg3; \
1600 _argvec[4] = (unsigned long)arg4; \
1601 __asm__ volatile( \
1602 "mr 11,%1\n\t" \
1603 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1604 "lwz 4,8(11)\n\t" \
1605 "lwz 5,12(11)\n\t" \
1606 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1607 "lwz 11,0(11)\n\t" /* target->r11 */ \
1608 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1609 "mr %0,3" \
1610 : /*out*/ "=r" (_res) \
1611 : /*in*/ "r" (&_argvec[0]) \
1612 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1613 ); \
1614 lval = (__typeof__(lval)) _res; \
1615 } while (0)
1616
1617 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1618 do { \
1619 volatile OrigFn _orig = (orig); \
1620 volatile unsigned long _argvec[6]; \
1621 volatile unsigned long _res; \
1622 _argvec[0] = (unsigned long)_orig.nraddr; \
1623 _argvec[1] = (unsigned long)arg1; \
1624 _argvec[2] = (unsigned long)arg2; \
1625 _argvec[3] = (unsigned long)arg3; \
1626 _argvec[4] = (unsigned long)arg4; \
1627 _argvec[5] = (unsigned long)arg5; \
1628 __asm__ volatile( \
1629 "mr 11,%1\n\t" \
1630 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1631 "lwz 4,8(11)\n\t" \
1632 "lwz 5,12(11)\n\t" \
1633 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1634 "lwz 7,20(11)\n\t" \
1635 "lwz 11,0(11)\n\t" /* target->r11 */ \
1636 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1637 "mr %0,3" \
1638 : /*out*/ "=r" (_res) \
1639 : /*in*/ "r" (&_argvec[0]) \
1640 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1641 ); \
1642 lval = (__typeof__(lval)) _res; \
1643 } while (0)
1644
1645 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1646 do { \
1647 volatile OrigFn _orig = (orig); \
1648 volatile unsigned long _argvec[7]; \
1649 volatile unsigned long _res; \
1650 _argvec[0] = (unsigned long)_orig.nraddr; \
1651 _argvec[1] = (unsigned long)arg1; \
1652 _argvec[2] = (unsigned long)arg2; \
1653 _argvec[3] = (unsigned long)arg3; \
1654 _argvec[4] = (unsigned long)arg4; \
1655 _argvec[5] = (unsigned long)arg5; \
1656 _argvec[6] = (unsigned long)arg6; \
1657 __asm__ volatile( \
1658 "mr 11,%1\n\t" \
1659 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1660 "lwz 4,8(11)\n\t" \
1661 "lwz 5,12(11)\n\t" \
1662 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1663 "lwz 7,20(11)\n\t" \
1664 "lwz 8,24(11)\n\t" \
1665 "lwz 11,0(11)\n\t" /* target->r11 */ \
1666 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1667 "mr %0,3" \
1668 : /*out*/ "=r" (_res) \
1669 : /*in*/ "r" (&_argvec[0]) \
1670 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1671 ); \
1672 lval = (__typeof__(lval)) _res; \
1673 } while (0)
1674
1675 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1676 arg7) \
1677 do { \
1678 volatile OrigFn _orig = (orig); \
1679 volatile unsigned long _argvec[8]; \
1680 volatile unsigned long _res; \
1681 _argvec[0] = (unsigned long)_orig.nraddr; \
1682 _argvec[1] = (unsigned long)arg1; \
1683 _argvec[2] = (unsigned long)arg2; \
1684 _argvec[3] = (unsigned long)arg3; \
1685 _argvec[4] = (unsigned long)arg4; \
1686 _argvec[5] = (unsigned long)arg5; \
1687 _argvec[6] = (unsigned long)arg6; \
1688 _argvec[7] = (unsigned long)arg7; \
1689 __asm__ volatile( \
1690 "mr 11,%1\n\t" \
1691 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1692 "lwz 4,8(11)\n\t" \
1693 "lwz 5,12(11)\n\t" \
1694 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1695 "lwz 7,20(11)\n\t" \
1696 "lwz 8,24(11)\n\t" \
1697 "lwz 9,28(11)\n\t" \
1698 "lwz 11,0(11)\n\t" /* target->r11 */ \
1699 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1700 "mr %0,3" \
1701 : /*out*/ "=r" (_res) \
1702 : /*in*/ "r" (&_argvec[0]) \
1703 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1704 ); \
1705 lval = (__typeof__(lval)) _res; \
1706 } while (0)
1707
1708 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1709 arg7,arg8) \
1710 do { \
1711 volatile OrigFn _orig = (orig); \
1712 volatile unsigned long _argvec[9]; \
1713 volatile unsigned long _res; \
1714 _argvec[0] = (unsigned long)_orig.nraddr; \
1715 _argvec[1] = (unsigned long)arg1; \
1716 _argvec[2] = (unsigned long)arg2; \
1717 _argvec[3] = (unsigned long)arg3; \
1718 _argvec[4] = (unsigned long)arg4; \
1719 _argvec[5] = (unsigned long)arg5; \
1720 _argvec[6] = (unsigned long)arg6; \
1721 _argvec[7] = (unsigned long)arg7; \
1722 _argvec[8] = (unsigned long)arg8; \
1723 __asm__ volatile( \
1724 "mr 11,%1\n\t" \
1725 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1726 "lwz 4,8(11)\n\t" \
1727 "lwz 5,12(11)\n\t" \
1728 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1729 "lwz 7,20(11)\n\t" \
1730 "lwz 8,24(11)\n\t" \
1731 "lwz 9,28(11)\n\t" \
1732 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1733 "lwz 11,0(11)\n\t" /* target->r11 */ \
1734 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1735 "mr %0,3" \
1736 : /*out*/ "=r" (_res) \
1737 : /*in*/ "r" (&_argvec[0]) \
1738 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1739 ); \
1740 lval = (__typeof__(lval)) _res; \
1741 } while (0)
1742
1743 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1744 arg7,arg8,arg9) \
1745 do { \
1746 volatile OrigFn _orig = (orig); \
1747 volatile unsigned long _argvec[10]; \
1748 volatile unsigned long _res; \
1749 _argvec[0] = (unsigned long)_orig.nraddr; \
1750 _argvec[1] = (unsigned long)arg1; \
1751 _argvec[2] = (unsigned long)arg2; \
1752 _argvec[3] = (unsigned long)arg3; \
1753 _argvec[4] = (unsigned long)arg4; \
1754 _argvec[5] = (unsigned long)arg5; \
1755 _argvec[6] = (unsigned long)arg6; \
1756 _argvec[7] = (unsigned long)arg7; \
1757 _argvec[8] = (unsigned long)arg8; \
1758 _argvec[9] = (unsigned long)arg9; \
1759 __asm__ volatile( \
1760 "mr 11,%1\n\t" \
1761 "addi 1,1,-16\n\t" \
1762 /* arg9 */ \
1763 "lwz 3,36(11)\n\t" \
1764 "stw 3,8(1)\n\t" \
1765 /* args1-8 */ \
1766 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1767 "lwz 4,8(11)\n\t" \
1768 "lwz 5,12(11)\n\t" \
1769 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1770 "lwz 7,20(11)\n\t" \
1771 "lwz 8,24(11)\n\t" \
1772 "lwz 9,28(11)\n\t" \
1773 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1774 "lwz 11,0(11)\n\t" /* target->r11 */ \
1775 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1776 "addi 1,1,16\n\t" \
1777 "mr %0,3" \
1778 : /*out*/ "=r" (_res) \
1779 : /*in*/ "r" (&_argvec[0]) \
1780 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1781 ); \
1782 lval = (__typeof__(lval)) _res; \
1783 } while (0)
1784
1785 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1786 arg7,arg8,arg9,arg10) \
1787 do { \
1788 volatile OrigFn _orig = (orig); \
1789 volatile unsigned long _argvec[11]; \
1790 volatile unsigned long _res; \
1791 _argvec[0] = (unsigned long)_orig.nraddr; \
1792 _argvec[1] = (unsigned long)arg1; \
1793 _argvec[2] = (unsigned long)arg2; \
1794 _argvec[3] = (unsigned long)arg3; \
1795 _argvec[4] = (unsigned long)arg4; \
1796 _argvec[5] = (unsigned long)arg5; \
1797 _argvec[6] = (unsigned long)arg6; \
1798 _argvec[7] = (unsigned long)arg7; \
1799 _argvec[8] = (unsigned long)arg8; \
1800 _argvec[9] = (unsigned long)arg9; \
1801 _argvec[10] = (unsigned long)arg10; \
1802 __asm__ volatile( \
1803 "mr 11,%1\n\t" \
1804 "addi 1,1,-16\n\t" \
1805 /* arg10 */ \
1806 "lwz 3,40(11)\n\t" \
1807 "stw 3,12(1)\n\t" \
1808 /* arg9 */ \
1809 "lwz 3,36(11)\n\t" \
1810 "stw 3,8(1)\n\t" \
1811 /* args1-8 */ \
1812 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1813 "lwz 4,8(11)\n\t" \
1814 "lwz 5,12(11)\n\t" \
1815 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1816 "lwz 7,20(11)\n\t" \
1817 "lwz 8,24(11)\n\t" \
1818 "lwz 9,28(11)\n\t" \
1819 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1820 "lwz 11,0(11)\n\t" /* target->r11 */ \
1821 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1822 "addi 1,1,16\n\t" \
1823 "mr %0,3" \
1824 : /*out*/ "=r" (_res) \
1825 : /*in*/ "r" (&_argvec[0]) \
1826 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1827 ); \
1828 lval = (__typeof__(lval)) _res; \
1829 } while (0)
1830
1831 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1832 arg7,arg8,arg9,arg10,arg11) \
1833 do { \
1834 volatile OrigFn _orig = (orig); \
1835 volatile unsigned long _argvec[12]; \
1836 volatile unsigned long _res; \
1837 _argvec[0] = (unsigned long)_orig.nraddr; \
1838 _argvec[1] = (unsigned long)arg1; \
1839 _argvec[2] = (unsigned long)arg2; \
1840 _argvec[3] = (unsigned long)arg3; \
1841 _argvec[4] = (unsigned long)arg4; \
1842 _argvec[5] = (unsigned long)arg5; \
1843 _argvec[6] = (unsigned long)arg6; \
1844 _argvec[7] = (unsigned long)arg7; \
1845 _argvec[8] = (unsigned long)arg8; \
1846 _argvec[9] = (unsigned long)arg9; \
1847 _argvec[10] = (unsigned long)arg10; \
1848 _argvec[11] = (unsigned long)arg11; \
1849 __asm__ volatile( \
1850 "mr 11,%1\n\t" \
1851 "addi 1,1,-32\n\t" \
1852 /* arg11 */ \
1853 "lwz 3,44(11)\n\t" \
1854 "stw 3,16(1)\n\t" \
1855 /* arg10 */ \
1856 "lwz 3,40(11)\n\t" \
1857 "stw 3,12(1)\n\t" \
1858 /* arg9 */ \
1859 "lwz 3,36(11)\n\t" \
1860 "stw 3,8(1)\n\t" \
1861 /* args1-8 */ \
1862 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1863 "lwz 4,8(11)\n\t" \
1864 "lwz 5,12(11)\n\t" \
1865 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1866 "lwz 7,20(11)\n\t" \
1867 "lwz 8,24(11)\n\t" \
1868 "lwz 9,28(11)\n\t" \
1869 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1870 "lwz 11,0(11)\n\t" /* target->r11 */ \
1871 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1872 "addi 1,1,32\n\t" \
1873 "mr %0,3" \
1874 : /*out*/ "=r" (_res) \
1875 : /*in*/ "r" (&_argvec[0]) \
1876 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1877 ); \
1878 lval = (__typeof__(lval)) _res; \
1879 } while (0)
1880
1881 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1882 arg7,arg8,arg9,arg10,arg11,arg12) \
1883 do { \
1884 volatile OrigFn _orig = (orig); \
1885 volatile unsigned long _argvec[13]; \
1886 volatile unsigned long _res; \
1887 _argvec[0] = (unsigned long)_orig.nraddr; \
1888 _argvec[1] = (unsigned long)arg1; \
1889 _argvec[2] = (unsigned long)arg2; \
1890 _argvec[3] = (unsigned long)arg3; \
1891 _argvec[4] = (unsigned long)arg4; \
1892 _argvec[5] = (unsigned long)arg5; \
1893 _argvec[6] = (unsigned long)arg6; \
1894 _argvec[7] = (unsigned long)arg7; \
1895 _argvec[8] = (unsigned long)arg8; \
1896 _argvec[9] = (unsigned long)arg9; \
1897 _argvec[10] = (unsigned long)arg10; \
1898 _argvec[11] = (unsigned long)arg11; \
1899 _argvec[12] = (unsigned long)arg12; \
1900 __asm__ volatile( \
1901 "mr 11,%1\n\t" \
1902 "addi 1,1,-32\n\t" \
1903 /* arg12 */ \
1904 "lwz 3,48(11)\n\t" \
1905 "stw 3,20(1)\n\t" \
1906 /* arg11 */ \
1907 "lwz 3,44(11)\n\t" \
1908 "stw 3,16(1)\n\t" \
1909 /* arg10 */ \
1910 "lwz 3,40(11)\n\t" \
1911 "stw 3,12(1)\n\t" \
1912 /* arg9 */ \
1913 "lwz 3,36(11)\n\t" \
1914 "stw 3,8(1)\n\t" \
1915 /* args1-8 */ \
1916 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1917 "lwz 4,8(11)\n\t" \
1918 "lwz 5,12(11)\n\t" \
1919 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1920 "lwz 7,20(11)\n\t" \
1921 "lwz 8,24(11)\n\t" \
1922 "lwz 9,28(11)\n\t" \
1923 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1924 "lwz 11,0(11)\n\t" /* target->r11 */ \
1925 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1926 "addi 1,1,32\n\t" \
1927 "mr %0,3" \
1928 : /*out*/ "=r" (_res) \
1929 : /*in*/ "r" (&_argvec[0]) \
1930 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1931 ); \
1932 lval = (__typeof__(lval)) _res; \
1933 } while (0)
1934
1935 #endif /* PLAT_ppc32_linux */
1936
1937 /* ------------------------ ppc64-linux ------------------------ */
1938
1939 #if defined(PLAT_ppc64_linux)
1940
1941 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1942
1943 /* These regs are trashed by the hidden call. */
1944 #define __CALLER_SAVED_REGS \
1945 "lr", "ctr", "xer", \
1946 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1947 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1948 "r11", "r12", "r13"
1949
1950 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1951 long) == 8. */
1952
1953 #define CALL_FN_W_v(lval, orig) \
1954 do { \
1955 volatile OrigFn _orig = (orig); \
1956 volatile unsigned long _argvec[3+0]; \
1957 volatile unsigned long _res; \
1958 /* _argvec[0] holds current r2 across the call */ \
1959 _argvec[1] = (unsigned long)_orig.r2; \
1960 _argvec[2] = (unsigned long)_orig.nraddr; \
1961 __asm__ volatile( \
1962 "mr 11,%1\n\t" \
1963 "std 2,-16(11)\n\t" /* save tocptr */ \
1964 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1965 "ld 11, 0(11)\n\t" /* target->r11 */ \
1966 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1967 "mr 11,%1\n\t" \
1968 "mr %0,3\n\t" \
1969 "ld 2,-16(11)" /* restore tocptr */ \
1970 : /*out*/ "=r" (_res) \
1971 : /*in*/ "r" (&_argvec[2]) \
1972 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1973 ); \
1974 lval = (__typeof__(lval)) _res; \
1975 } while (0)
1976
1977 #define CALL_FN_W_W(lval, orig, arg1) \
1978 do { \
1979 volatile OrigFn _orig = (orig); \
1980 volatile unsigned long _argvec[3+1]; \
1981 volatile unsigned long _res; \
1982 /* _argvec[0] holds current r2 across the call */ \
1983 _argvec[1] = (unsigned long)_orig.r2; \
1984 _argvec[2] = (unsigned long)_orig.nraddr; \
1985 _argvec[2+1] = (unsigned long)arg1; \
1986 __asm__ volatile( \
1987 "mr 11,%1\n\t" \
1988 "std 2,-16(11)\n\t" /* save tocptr */ \
1989 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1990 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1991 "ld 11, 0(11)\n\t" /* target->r11 */ \
1992 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1993 "mr 11,%1\n\t" \
1994 "mr %0,3\n\t" \
1995 "ld 2,-16(11)" /* restore tocptr */ \
1996 : /*out*/ "=r" (_res) \
1997 : /*in*/ "r" (&_argvec[2]) \
1998 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1999 ); \
2000 lval = (__typeof__(lval)) _res; \
2001 } while (0)
2002
2003 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2004 do { \
2005 volatile OrigFn _orig = (orig); \
2006 volatile unsigned long _argvec[3+2]; \
2007 volatile unsigned long _res; \
2008 /* _argvec[0] holds current r2 across the call */ \
2009 _argvec[1] = (unsigned long)_orig.r2; \
2010 _argvec[2] = (unsigned long)_orig.nraddr; \
2011 _argvec[2+1] = (unsigned long)arg1; \
2012 _argvec[2+2] = (unsigned long)arg2; \
2013 __asm__ volatile( \
2014 "mr 11,%1\n\t" \
2015 "std 2,-16(11)\n\t" /* save tocptr */ \
2016 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2017 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2018 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2019 "ld 11, 0(11)\n\t" /* target->r11 */ \
2020 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2021 "mr 11,%1\n\t" \
2022 "mr %0,3\n\t" \
2023 "ld 2,-16(11)" /* restore tocptr */ \
2024 : /*out*/ "=r" (_res) \
2025 : /*in*/ "r" (&_argvec[2]) \
2026 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2027 ); \
2028 lval = (__typeof__(lval)) _res; \
2029 } while (0)
2030
2031 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2032 do { \
2033 volatile OrigFn _orig = (orig); \
2034 volatile unsigned long _argvec[3+3]; \
2035 volatile unsigned long _res; \
2036 /* _argvec[0] holds current r2 across the call */ \
2037 _argvec[1] = (unsigned long)_orig.r2; \
2038 _argvec[2] = (unsigned long)_orig.nraddr; \
2039 _argvec[2+1] = (unsigned long)arg1; \
2040 _argvec[2+2] = (unsigned long)arg2; \
2041 _argvec[2+3] = (unsigned long)arg3; \
2042 __asm__ volatile( \
2043 "mr 11,%1\n\t" \
2044 "std 2,-16(11)\n\t" /* save tocptr */ \
2045 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2046 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2047 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2048 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2049 "ld 11, 0(11)\n\t" /* target->r11 */ \
2050 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2051 "mr 11,%1\n\t" \
2052 "mr %0,3\n\t" \
2053 "ld 2,-16(11)" /* restore tocptr */ \
2054 : /*out*/ "=r" (_res) \
2055 : /*in*/ "r" (&_argvec[2]) \
2056 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2057 ); \
2058 lval = (__typeof__(lval)) _res; \
2059 } while (0)
2060
2061 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2062 do { \
2063 volatile OrigFn _orig = (orig); \
2064 volatile unsigned long _argvec[3+4]; \
2065 volatile unsigned long _res; \
2066 /* _argvec[0] holds current r2 across the call */ \
2067 _argvec[1] = (unsigned long)_orig.r2; \
2068 _argvec[2] = (unsigned long)_orig.nraddr; \
2069 _argvec[2+1] = (unsigned long)arg1; \
2070 _argvec[2+2] = (unsigned long)arg2; \
2071 _argvec[2+3] = (unsigned long)arg3; \
2072 _argvec[2+4] = (unsigned long)arg4; \
2073 __asm__ volatile( \
2074 "mr 11,%1\n\t" \
2075 "std 2,-16(11)\n\t" /* save tocptr */ \
2076 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2077 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2078 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2079 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2080 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2081 "ld 11, 0(11)\n\t" /* target->r11 */ \
2082 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2083 "mr 11,%1\n\t" \
2084 "mr %0,3\n\t" \
2085 "ld 2,-16(11)" /* restore tocptr */ \
2086 : /*out*/ "=r" (_res) \
2087 : /*in*/ "r" (&_argvec[2]) \
2088 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2089 ); \
2090 lval = (__typeof__(lval)) _res; \
2091 } while (0)
2092
2093 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2094 do { \
2095 volatile OrigFn _orig = (orig); \
2096 volatile unsigned long _argvec[3+5]; \
2097 volatile unsigned long _res; \
2098 /* _argvec[0] holds current r2 across the call */ \
2099 _argvec[1] = (unsigned long)_orig.r2; \
2100 _argvec[2] = (unsigned long)_orig.nraddr; \
2101 _argvec[2+1] = (unsigned long)arg1; \
2102 _argvec[2+2] = (unsigned long)arg2; \
2103 _argvec[2+3] = (unsigned long)arg3; \
2104 _argvec[2+4] = (unsigned long)arg4; \
2105 _argvec[2+5] = (unsigned long)arg5; \
2106 __asm__ volatile( \
2107 "mr 11,%1\n\t" \
2108 "std 2,-16(11)\n\t" /* save tocptr */ \
2109 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2110 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2111 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2112 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2113 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2114 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2115 "ld 11, 0(11)\n\t" /* target->r11 */ \
2116 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2117 "mr 11,%1\n\t" \
2118 "mr %0,3\n\t" \
2119 "ld 2,-16(11)" /* restore tocptr */ \
2120 : /*out*/ "=r" (_res) \
2121 : /*in*/ "r" (&_argvec[2]) \
2122 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2123 ); \
2124 lval = (__typeof__(lval)) _res; \
2125 } while (0)
2126
2127 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2128 do { \
2129 volatile OrigFn _orig = (orig); \
2130 volatile unsigned long _argvec[3+6]; \
2131 volatile unsigned long _res; \
2132 /* _argvec[0] holds current r2 across the call */ \
2133 _argvec[1] = (unsigned long)_orig.r2; \
2134 _argvec[2] = (unsigned long)_orig.nraddr; \
2135 _argvec[2+1] = (unsigned long)arg1; \
2136 _argvec[2+2] = (unsigned long)arg2; \
2137 _argvec[2+3] = (unsigned long)arg3; \
2138 _argvec[2+4] = (unsigned long)arg4; \
2139 _argvec[2+5] = (unsigned long)arg5; \
2140 _argvec[2+6] = (unsigned long)arg6; \
2141 __asm__ volatile( \
2142 "mr 11,%1\n\t" \
2143 "std 2,-16(11)\n\t" /* save tocptr */ \
2144 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2145 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2146 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2147 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2148 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2149 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2150 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2151 "ld 11, 0(11)\n\t" /* target->r11 */ \
2152 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2153 "mr 11,%1\n\t" \
2154 "mr %0,3\n\t" \
2155 "ld 2,-16(11)" /* restore tocptr */ \
2156 : /*out*/ "=r" (_res) \
2157 : /*in*/ "r" (&_argvec[2]) \
2158 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2159 ); \
2160 lval = (__typeof__(lval)) _res; \
2161 } while (0)
2162
2163 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2164 arg7) \
2165 do { \
2166 volatile OrigFn _orig = (orig); \
2167 volatile unsigned long _argvec[3+7]; \
2168 volatile unsigned long _res; \
2169 /* _argvec[0] holds current r2 across the call */ \
2170 _argvec[1] = (unsigned long)_orig.r2; \
2171 _argvec[2] = (unsigned long)_orig.nraddr; \
2172 _argvec[2+1] = (unsigned long)arg1; \
2173 _argvec[2+2] = (unsigned long)arg2; \
2174 _argvec[2+3] = (unsigned long)arg3; \
2175 _argvec[2+4] = (unsigned long)arg4; \
2176 _argvec[2+5] = (unsigned long)arg5; \
2177 _argvec[2+6] = (unsigned long)arg6; \
2178 _argvec[2+7] = (unsigned long)arg7; \
2179 __asm__ volatile( \
2180 "mr 11,%1\n\t" \
2181 "std 2,-16(11)\n\t" /* save tocptr */ \
2182 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2183 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2184 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2185 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2186 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2187 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2188 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2189 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2190 "ld 11, 0(11)\n\t" /* target->r11 */ \
2191 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2192 "mr 11,%1\n\t" \
2193 "mr %0,3\n\t" \
2194 "ld 2,-16(11)" /* restore tocptr */ \
2195 : /*out*/ "=r" (_res) \
2196 : /*in*/ "r" (&_argvec[2]) \
2197 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2198 ); \
2199 lval = (__typeof__(lval)) _res; \
2200 } while (0)
2201
2202 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2203 arg7,arg8) \
2204 do { \
2205 volatile OrigFn _orig = (orig); \
2206 volatile unsigned long _argvec[3+8]; \
2207 volatile unsigned long _res; \
2208 /* _argvec[0] holds current r2 across the call */ \
2209 _argvec[1] = (unsigned long)_orig.r2; \
2210 _argvec[2] = (unsigned long)_orig.nraddr; \
2211 _argvec[2+1] = (unsigned long)arg1; \
2212 _argvec[2+2] = (unsigned long)arg2; \
2213 _argvec[2+3] = (unsigned long)arg3; \
2214 _argvec[2+4] = (unsigned long)arg4; \
2215 _argvec[2+5] = (unsigned long)arg5; \
2216 _argvec[2+6] = (unsigned long)arg6; \
2217 _argvec[2+7] = (unsigned long)arg7; \
2218 _argvec[2+8] = (unsigned long)arg8; \
2219 __asm__ volatile( \
2220 "mr 11,%1\n\t" \
2221 "std 2,-16(11)\n\t" /* save tocptr */ \
2222 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2223 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2224 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2225 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2226 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2227 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2228 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2229 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2230 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2231 "ld 11, 0(11)\n\t" /* target->r11 */ \
2232 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2233 "mr 11,%1\n\t" \
2234 "mr %0,3\n\t" \
2235 "ld 2,-16(11)" /* restore tocptr */ \
2236 : /*out*/ "=r" (_res) \
2237 : /*in*/ "r" (&_argvec[2]) \
2238 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2239 ); \
2240 lval = (__typeof__(lval)) _res; \
2241 } while (0)
2242
2243 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2244 arg7,arg8,arg9) \
2245 do { \
2246 volatile OrigFn _orig = (orig); \
2247 volatile unsigned long _argvec[3+9]; \
2248 volatile unsigned long _res; \
2249 /* _argvec[0] holds current r2 across the call */ \
2250 _argvec[1] = (unsigned long)_orig.r2; \
2251 _argvec[2] = (unsigned long)_orig.nraddr; \
2252 _argvec[2+1] = (unsigned long)arg1; \
2253 _argvec[2+2] = (unsigned long)arg2; \
2254 _argvec[2+3] = (unsigned long)arg3; \
2255 _argvec[2+4] = (unsigned long)arg4; \
2256 _argvec[2+5] = (unsigned long)arg5; \
2257 _argvec[2+6] = (unsigned long)arg6; \
2258 _argvec[2+7] = (unsigned long)arg7; \
2259 _argvec[2+8] = (unsigned long)arg8; \
2260 _argvec[2+9] = (unsigned long)arg9; \
2261 __asm__ volatile( \
2262 "mr 11,%1\n\t" \
2263 "std 2,-16(11)\n\t" /* save tocptr */ \
2264 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2265 "addi 1,1,-128\n\t" /* expand stack frame */ \
2266 /* arg9 */ \
2267 "ld 3,72(11)\n\t" \
2268 "std 3,112(1)\n\t" \
2269 /* args1-8 */ \
2270 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2271 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2272 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2273 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2274 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2275 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2276 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2277 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2278 "ld 11, 0(11)\n\t" /* target->r11 */ \
2279 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2280 "mr 11,%1\n\t" \
2281 "mr %0,3\n\t" \
2282 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2283 "addi 1,1,128" /* restore frame */ \
2284 : /*out*/ "=r" (_res) \
2285 : /*in*/ "r" (&_argvec[2]) \
2286 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2287 ); \
2288 lval = (__typeof__(lval)) _res; \
2289 } while (0)
2290
2291 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2292 arg7,arg8,arg9,arg10) \
2293 do { \
2294 volatile OrigFn _orig = (orig); \
2295 volatile unsigned long _argvec[3+10]; \
2296 volatile unsigned long _res; \
2297 /* _argvec[0] holds current r2 across the call */ \
2298 _argvec[1] = (unsigned long)_orig.r2; \
2299 _argvec[2] = (unsigned long)_orig.nraddr; \
2300 _argvec[2+1] = (unsigned long)arg1; \
2301 _argvec[2+2] = (unsigned long)arg2; \
2302 _argvec[2+3] = (unsigned long)arg3; \
2303 _argvec[2+4] = (unsigned long)arg4; \
2304 _argvec[2+5] = (unsigned long)arg5; \
2305 _argvec[2+6] = (unsigned long)arg6; \
2306 _argvec[2+7] = (unsigned long)arg7; \
2307 _argvec[2+8] = (unsigned long)arg8; \
2308 _argvec[2+9] = (unsigned long)arg9; \
2309 _argvec[2+10] = (unsigned long)arg10; \
2310 __asm__ volatile( \
2311 "mr 11,%1\n\t" \
2312 "std 2,-16(11)\n\t" /* save tocptr */ \
2313 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2314 "addi 1,1,-128\n\t" /* expand stack frame */ \
2315 /* arg10 */ \
2316 "ld 3,80(11)\n\t" \
2317 "std 3,120(1)\n\t" \
2318 /* arg9 */ \
2319 "ld 3,72(11)\n\t" \
2320 "std 3,112(1)\n\t" \
2321 /* args1-8 */ \
2322 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2323 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2324 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2325 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2326 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2327 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2328 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2329 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2330 "ld 11, 0(11)\n\t" /* target->r11 */ \
2331 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2332 "mr 11,%1\n\t" \
2333 "mr %0,3\n\t" \
2334 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2335 "addi 1,1,128" /* restore frame */ \
2336 : /*out*/ "=r" (_res) \
2337 : /*in*/ "r" (&_argvec[2]) \
2338 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2339 ); \
2340 lval = (__typeof__(lval)) _res; \
2341 } while (0)
2342
2343 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2344 arg7,arg8,arg9,arg10,arg11) \
2345 do { \
2346 volatile OrigFn _orig = (orig); \
2347 volatile unsigned long _argvec[3+11]; \
2348 volatile unsigned long _res; \
2349 /* _argvec[0] holds current r2 across the call */ \
2350 _argvec[1] = (unsigned long)_orig.r2; \
2351 _argvec[2] = (unsigned long)_orig.nraddr; \
2352 _argvec[2+1] = (unsigned long)arg1; \
2353 _argvec[2+2] = (unsigned long)arg2; \
2354 _argvec[2+3] = (unsigned long)arg3; \
2355 _argvec[2+4] = (unsigned long)arg4; \
2356 _argvec[2+5] = (unsigned long)arg5; \
2357 _argvec[2+6] = (unsigned long)arg6; \
2358 _argvec[2+7] = (unsigned long)arg7; \
2359 _argvec[2+8] = (unsigned long)arg8; \
2360 _argvec[2+9] = (unsigned long)arg9; \
2361 _argvec[2+10] = (unsigned long)arg10; \
2362 _argvec[2+11] = (unsigned long)arg11; \
2363 __asm__ volatile( \
2364 "mr 11,%1\n\t" \
2365 "std 2,-16(11)\n\t" /* save tocptr */ \
2366 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2367 "addi 1,1,-144\n\t" /* expand stack frame */ \
2368 /* arg11 */ \
2369 "ld 3,88(11)\n\t" \
2370 "std 3,128(1)\n\t" \
2371 /* arg10 */ \
2372 "ld 3,80(11)\n\t" \
2373 "std 3,120(1)\n\t" \
2374 /* arg9 */ \
2375 "ld 3,72(11)\n\t" \
2376 "std 3,112(1)\n\t" \
2377 /* args1-8 */ \
2378 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2379 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2380 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2381 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2382 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2383 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2384 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2385 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2386 "ld 11, 0(11)\n\t" /* target->r11 */ \
2387 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2388 "mr 11,%1\n\t" \
2389 "mr %0,3\n\t" \
2390 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2391 "addi 1,1,144" /* restore frame */ \
2392 : /*out*/ "=r" (_res) \
2393 : /*in*/ "r" (&_argvec[2]) \
2394 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2395 ); \
2396 lval = (__typeof__(lval)) _res; \
2397 } while (0)
2398
2399 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2400 arg7,arg8,arg9,arg10,arg11,arg12) \
2401 do { \
2402 volatile OrigFn _orig = (orig); \
2403 volatile unsigned long _argvec[3+12]; \
2404 volatile unsigned long _res; \
2405 /* _argvec[0] holds current r2 across the call */ \
2406 _argvec[1] = (unsigned long)_orig.r2; \
2407 _argvec[2] = (unsigned long)_orig.nraddr; \
2408 _argvec[2+1] = (unsigned long)arg1; \
2409 _argvec[2+2] = (unsigned long)arg2; \
2410 _argvec[2+3] = (unsigned long)arg3; \
2411 _argvec[2+4] = (unsigned long)arg4; \
2412 _argvec[2+5] = (unsigned long)arg5; \
2413 _argvec[2+6] = (unsigned long)arg6; \
2414 _argvec[2+7] = (unsigned long)arg7; \
2415 _argvec[2+8] = (unsigned long)arg8; \
2416 _argvec[2+9] = (unsigned long)arg9; \
2417 _argvec[2+10] = (unsigned long)arg10; \
2418 _argvec[2+11] = (unsigned long)arg11; \
2419 _argvec[2+12] = (unsigned long)arg12; \
2420 __asm__ volatile( \
2421 "mr 11,%1\n\t" \
2422 "std 2,-16(11)\n\t" /* save tocptr */ \
2423 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2424 "addi 1,1,-144\n\t" /* expand stack frame */ \
2425 /* arg12 */ \
2426 "ld 3,96(11)\n\t" \
2427 "std 3,136(1)\n\t" \
2428 /* arg11 */ \
2429 "ld 3,88(11)\n\t" \
2430 "std 3,128(1)\n\t" \
2431 /* arg10 */ \
2432 "ld 3,80(11)\n\t" \
2433 "std 3,120(1)\n\t" \
2434 /* arg9 */ \
2435 "ld 3,72(11)\n\t" \
2436 "std 3,112(1)\n\t" \
2437 /* args1-8 */ \
2438 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2439 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2440 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2441 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2442 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2443 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2444 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2445 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2446 "ld 11, 0(11)\n\t" /* target->r11 */ \
2447 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2448 "mr 11,%1\n\t" \
2449 "mr %0,3\n\t" \
2450 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2451 "addi 1,1,144" /* restore frame */ \
2452 : /*out*/ "=r" (_res) \
2453 : /*in*/ "r" (&_argvec[2]) \
2454 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2455 ); \
2456 lval = (__typeof__(lval)) _res; \
2457 } while (0)
2458
2459 #endif /* PLAT_ppc64_linux */
2460
2461 /* ------------------------ ppc32-aix5 ------------------------- */
2462
2463 #if defined(PLAT_ppc32_aix5)
2464
2465 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2466
2467 /* These regs are trashed by the hidden call. */
2468 #define __CALLER_SAVED_REGS \
2469 "lr", "ctr", "xer", \
2470 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2471 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2472 "r11", "r12", "r13"
2473
2474 /* Expand the stack frame, copying enough info that unwinding
2475 still works. Trashes r3. */
2476
2477 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2478 "addi 1,1,-" #_n_fr "\n\t" \
2479 "lwz 3," #_n_fr "(1)\n\t" \
2480 "stw 3,0(1)\n\t"
2481
2482 #define VG_CONTRACT_FRAME_BY(_n_fr) \
2483 "addi 1,1," #_n_fr "\n\t"
2484
2485 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2486 long) == 4. */
2487
2488 #define CALL_FN_W_v(lval, orig) \
2489 do { \
2490 volatile OrigFn _orig = (orig); \
2491 volatile unsigned long _argvec[3+0]; \
2492 volatile unsigned long _res; \
2493 /* _argvec[0] holds current r2 across the call */ \
2494 _argvec[1] = (unsigned long)_orig.r2; \
2495 _argvec[2] = (unsigned long)_orig.nraddr; \
2496 __asm__ volatile( \
2497 "mr 11,%1\n\t" \
2498 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2499 "stw 2,-8(11)\n\t" /* save tocptr */ \
2500 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2501 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2502 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2503 "mr 11,%1\n\t" \
2504 "mr %0,3\n\t" \
2505 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2506 VG_CONTRACT_FRAME_BY(512) \
2507 : /*out*/ "=r" (_res) \
2508 : /*in*/ "r" (&_argvec[2]) \
2509 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2510 ); \
2511 lval = (__typeof__(lval)) _res; \
2512 } while (0)
2513
2514 #define CALL_FN_W_W(lval, orig, arg1) \
2515 do { \
2516 volatile OrigFn _orig = (orig); \
2517 volatile unsigned long _argvec[3+1]; \
2518 volatile unsigned long _res; \
2519 /* _argvec[0] holds current r2 across the call */ \
2520 _argvec[1] = (unsigned long)_orig.r2; \
2521 _argvec[2] = (unsigned long)_orig.nraddr; \
2522 _argvec[2+1] = (unsigned long)arg1; \
2523 __asm__ volatile( \
2524 "mr 11,%1\n\t" \
2525 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2526 "stw 2,-8(11)\n\t" /* save tocptr */ \
2527 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2528 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2529 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2530 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2531 "mr 11,%1\n\t" \
2532 "mr %0,3\n\t" \
2533 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2534 VG_CONTRACT_FRAME_BY(512) \
2535 : /*out*/ "=r" (_res) \
2536 : /*in*/ "r" (&_argvec[2]) \
2537 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2538 ); \
2539 lval = (__typeof__(lval)) _res; \
2540 } while (0)
2541
2542 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2543 do { \
2544 volatile OrigFn _orig = (orig); \
2545 volatile unsigned long _argvec[3+2]; \
2546 volatile unsigned long _res; \
2547 /* _argvec[0] holds current r2 across the call */ \
2548 _argvec[1] = (unsigned long)_orig.r2; \
2549 _argvec[2] = (unsigned long)_orig.nraddr; \
2550 _argvec[2+1] = (unsigned long)arg1; \
2551 _argvec[2+2] = (unsigned long)arg2; \
2552 __asm__ volatile( \
2553 "mr 11,%1\n\t" \
2554 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2555 "stw 2,-8(11)\n\t" /* save tocptr */ \
2556 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2557 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2558 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2559 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2560 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2561 "mr 11,%1\n\t" \
2562 "mr %0,3\n\t" \
2563 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2564 VG_CONTRACT_FRAME_BY(512) \
2565 : /*out*/ "=r" (_res) \
2566 : /*in*/ "r" (&_argvec[2]) \
2567 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2568 ); \
2569 lval = (__typeof__(lval)) _res; \
2570 } while (0)
2571
2572 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2573 do { \
2574 volatile OrigFn _orig = (orig); \
2575 volatile unsigned long _argvec[3+3]; \
2576 volatile unsigned long _res; \
2577 /* _argvec[0] holds current r2 across the call */ \
2578 _argvec[1] = (unsigned long)_orig.r2; \
2579 _argvec[2] = (unsigned long)_orig.nraddr; \
2580 _argvec[2+1] = (unsigned long)arg1; \
2581 _argvec[2+2] = (unsigned long)arg2; \
2582 _argvec[2+3] = (unsigned long)arg3; \
2583 __asm__ volatile( \
2584 "mr 11,%1\n\t" \
2585 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2586 "stw 2,-8(11)\n\t" /* save tocptr */ \
2587 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2588 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2589 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2590 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2591 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2592 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2593 "mr 11,%1\n\t" \
2594 "mr %0,3\n\t" \
2595 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2596 VG_CONTRACT_FRAME_BY(512) \
2597 : /*out*/ "=r" (_res) \
2598 : /*in*/ "r" (&_argvec[2]) \
2599 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2600 ); \
2601 lval = (__typeof__(lval)) _res; \
2602 } while (0)
2603
2604 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2605 do { \
2606 volatile OrigFn _orig = (orig); \
2607 volatile unsigned long _argvec[3+4]; \
2608 volatile unsigned long _res; \
2609 /* _argvec[0] holds current r2 across the call */ \
2610 _argvec[1] = (unsigned long)_orig.r2; \
2611 _argvec[2] = (unsigned long)_orig.nraddr; \
2612 _argvec[2+1] = (unsigned long)arg1; \
2613 _argvec[2+2] = (unsigned long)arg2; \
2614 _argvec[2+3] = (unsigned long)arg3; \
2615 _argvec[2+4] = (unsigned long)arg4; \
2616 __asm__ volatile( \
2617 "mr 11,%1\n\t" \
2618 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2619 "stw 2,-8(11)\n\t" /* save tocptr */ \
2620 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2621 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2622 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2623 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2624 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2625 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2626 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2627 "mr 11,%1\n\t" \
2628 "mr %0,3\n\t" \
2629 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2630 VG_CONTRACT_FRAME_BY(512) \
2631 : /*out*/ "=r" (_res) \
2632 : /*in*/ "r" (&_argvec[2]) \
2633 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2634 ); \
2635 lval = (__typeof__(lval)) _res; \
2636 } while (0)
2637
2638 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2639 do { \
2640 volatile OrigFn _orig = (orig); \
2641 volatile unsigned long _argvec[3+5]; \
2642 volatile unsigned long _res; \
2643 /* _argvec[0] holds current r2 across the call */ \
2644 _argvec[1] = (unsigned long)_orig.r2; \
2645 _argvec[2] = (unsigned long)_orig.nraddr; \
2646 _argvec[2+1] = (unsigned long)arg1; \
2647 _argvec[2+2] = (unsigned long)arg2; \
2648 _argvec[2+3] = (unsigned long)arg3; \
2649 _argvec[2+4] = (unsigned long)arg4; \
2650 _argvec[2+5] = (unsigned long)arg5; \
2651 __asm__ volatile( \
2652 "mr 11,%1\n\t" \
2653 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2654 "stw 2,-8(11)\n\t" /* save tocptr */ \
2655 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2656 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2657 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2658 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2659 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2660 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2661 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2662 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2663 "mr 11,%1\n\t" \
2664 "mr %0,3\n\t" \
2665 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2666 VG_CONTRACT_FRAME_BY(512) \
2667 : /*out*/ "=r" (_res) \
2668 : /*in*/ "r" (&_argvec[2]) \
2669 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2670 ); \
2671 lval = (__typeof__(lval)) _res; \
2672 } while (0)
2673
2674 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2675 do { \
2676 volatile OrigFn _orig = (orig); \
2677 volatile unsigned long _argvec[3+6]; \
2678 volatile unsigned long _res; \
2679 /* _argvec[0] holds current r2 across the call */ \
2680 _argvec[1] = (unsigned long)_orig.r2; \
2681 _argvec[2] = (unsigned long)_orig.nraddr; \
2682 _argvec[2+1] = (unsigned long)arg1; \
2683 _argvec[2+2] = (unsigned long)arg2; \
2684 _argvec[2+3] = (unsigned long)arg3; \
2685 _argvec[2+4] = (unsigned long)arg4; \
2686 _argvec[2+5] = (unsigned long)arg5; \
2687 _argvec[2+6] = (unsigned long)arg6; \
2688 __asm__ volatile( \
2689 "mr 11,%1\n\t" \
2690 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2691 "stw 2,-8(11)\n\t" /* save tocptr */ \
2692 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2693 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2694 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2695 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2696 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2697 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2698 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2699 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2700 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2701 "mr 11,%1\n\t" \
2702 "mr %0,3\n\t" \
2703 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2704 VG_CONTRACT_FRAME_BY(512) \
2705 : /*out*/ "=r" (_res) \
2706 : /*in*/ "r" (&_argvec[2]) \
2707 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2708 ); \
2709 lval = (__typeof__(lval)) _res; \
2710 } while (0)
2711
2712 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2713 arg7) \
2714 do { \
2715 volatile OrigFn _orig = (orig); \
2716 volatile unsigned long _argvec[3+7]; \
2717 volatile unsigned long _res; \
2718 /* _argvec[0] holds current r2 across the call */ \
2719 _argvec[1] = (unsigned long)_orig.r2; \
2720 _argvec[2] = (unsigned long)_orig.nraddr; \
2721 _argvec[2+1] = (unsigned long)arg1; \
2722 _argvec[2+2] = (unsigned long)arg2; \
2723 _argvec[2+3] = (unsigned long)arg3; \
2724 _argvec[2+4] = (unsigned long)arg4; \
2725 _argvec[2+5] = (unsigned long)arg5; \
2726 _argvec[2+6] = (unsigned long)arg6; \
2727 _argvec[2+7] = (unsigned long)arg7; \
2728 __asm__ volatile( \
2729 "mr 11,%1\n\t" \
2730 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2731 "stw 2,-8(11)\n\t" /* save tocptr */ \
2732 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2733 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2734 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2735 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2736 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2737 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2738 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2739 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2740 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2741 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2742 "mr 11,%1\n\t" \
2743 "mr %0,3\n\t" \
2744 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2745 VG_CONTRACT_FRAME_BY(512) \
2746 : /*out*/ "=r" (_res) \
2747 : /*in*/ "r" (&_argvec[2]) \
2748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2749 ); \
2750 lval = (__typeof__(lval)) _res; \
2751 } while (0)
2752
2753 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2754 arg7,arg8) \
2755 do { \
2756 volatile OrigFn _orig = (orig); \
2757 volatile unsigned long _argvec[3+8]; \
2758 volatile unsigned long _res; \
2759 /* _argvec[0] holds current r2 across the call */ \
2760 _argvec[1] = (unsigned long)_orig.r2; \
2761 _argvec[2] = (unsigned long)_orig.nraddr; \
2762 _argvec[2+1] = (unsigned long)arg1; \
2763 _argvec[2+2] = (unsigned long)arg2; \
2764 _argvec[2+3] = (unsigned long)arg3; \
2765 _argvec[2+4] = (unsigned long)arg4; \
2766 _argvec[2+5] = (unsigned long)arg5; \
2767 _argvec[2+6] = (unsigned long)arg6; \
2768 _argvec[2+7] = (unsigned long)arg7; \
2769 _argvec[2+8] = (unsigned long)arg8; \
2770 __asm__ volatile( \
2771 "mr 11,%1\n\t" \
2772 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2773 "stw 2,-8(11)\n\t" /* save tocptr */ \
2774 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2775 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2776 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2777 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2778 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2779 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2780 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2781 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2782 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2783 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2784 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2785 "mr 11,%1\n\t" \
2786 "mr %0,3\n\t" \
2787 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2788 VG_CONTRACT_FRAME_BY(512) \
2789 : /*out*/ "=r" (_res) \
2790 : /*in*/ "r" (&_argvec[2]) \
2791 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2792 ); \
2793 lval = (__typeof__(lval)) _res; \
2794 } while (0)
2795
2796 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2797 arg7,arg8,arg9) \
2798 do { \
2799 volatile OrigFn _orig = (orig); \
2800 volatile unsigned long _argvec[3+9]; \
2801 volatile unsigned long _res; \
2802 /* _argvec[0] holds current r2 across the call */ \
2803 _argvec[1] = (unsigned long)_orig.r2; \
2804 _argvec[2] = (unsigned long)_orig.nraddr; \
2805 _argvec[2+1] = (unsigned long)arg1; \
2806 _argvec[2+2] = (unsigned long)arg2; \
2807 _argvec[2+3] = (unsigned long)arg3; \
2808 _argvec[2+4] = (unsigned long)arg4; \
2809 _argvec[2+5] = (unsigned long)arg5; \
2810 _argvec[2+6] = (unsigned long)arg6; \
2811 _argvec[2+7] = (unsigned long)arg7; \
2812 _argvec[2+8] = (unsigned long)arg8; \
2813 _argvec[2+9] = (unsigned long)arg9; \
2814 __asm__ volatile( \
2815 "mr 11,%1\n\t" \
2816 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2817 "stw 2,-8(11)\n\t" /* save tocptr */ \
2818 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2819 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2820 /* arg9 */ \
2821 "lwz 3,36(11)\n\t" \
2822 "stw 3,56(1)\n\t" \
2823 /* args1-8 */ \
2824 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2825 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2826 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2827 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2828 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2829 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2830 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2831 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2832 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2833 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2834 "mr 11,%1\n\t" \
2835 "mr %0,3\n\t" \
2836 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2837 VG_CONTRACT_FRAME_BY(64) \
2838 VG_CONTRACT_FRAME_BY(512) \
2839 : /*out*/ "=r" (_res) \
2840 : /*in*/ "r" (&_argvec[2]) \
2841 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2842 ); \
2843 lval = (__typeof__(lval)) _res; \
2844 } while (0)
2845
2846 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2847 arg7,arg8,arg9,arg10) \
2848 do { \
2849 volatile OrigFn _orig = (orig); \
2850 volatile unsigned long _argvec[3+10]; \
2851 volatile unsigned long _res; \
2852 /* _argvec[0] holds current r2 across the call */ \
2853 _argvec[1] = (unsigned long)_orig.r2; \
2854 _argvec[2] = (unsigned long)_orig.nraddr; \
2855 _argvec[2+1] = (unsigned long)arg1; \
2856 _argvec[2+2] = (unsigned long)arg2; \
2857 _argvec[2+3] = (unsigned long)arg3; \
2858 _argvec[2+4] = (unsigned long)arg4; \
2859 _argvec[2+5] = (unsigned long)arg5; \
2860 _argvec[2+6] = (unsigned long)arg6; \
2861 _argvec[2+7] = (unsigned long)arg7; \
2862 _argvec[2+8] = (unsigned long)arg8; \
2863 _argvec[2+9] = (unsigned long)arg9; \
2864 _argvec[2+10] = (unsigned long)arg10; \
2865 __asm__ volatile( \
2866 "mr 11,%1\n\t" \
2867 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2868 "stw 2,-8(11)\n\t" /* save tocptr */ \
2869 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2870 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2871 /* arg10 */ \
2872 "lwz 3,40(11)\n\t" \
2873 "stw 3,60(1)\n\t" \
2874 /* arg9 */ \
2875 "lwz 3,36(11)\n\t" \
2876 "stw 3,56(1)\n\t" \
2877 /* args1-8 */ \
2878 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2879 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2880 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2881 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2882 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2883 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2884 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2885 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2886 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2887 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2888 "mr 11,%1\n\t" \
2889 "mr %0,3\n\t" \
2890 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2891 VG_CONTRACT_FRAME_BY(64) \
2892 VG_CONTRACT_FRAME_BY(512) \
2893 : /*out*/ "=r" (_res) \
2894 : /*in*/ "r" (&_argvec[2]) \
2895 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2896 ); \
2897 lval = (__typeof__(lval)) _res; \
2898 } while (0)
2899
2900 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2901 arg7,arg8,arg9,arg10,arg11) \
2902 do { \
2903 volatile OrigFn _orig = (orig); \
2904 volatile unsigned long _argvec[3+11]; \
2905 volatile unsigned long _res; \
2906 /* _argvec[0] holds current r2 across the call */ \
2907 _argvec[1] = (unsigned long)_orig.r2; \
2908 _argvec[2] = (unsigned long)_orig.nraddr; \
2909 _argvec[2+1] = (unsigned long)arg1; \
2910 _argvec[2+2] = (unsigned long)arg2; \
2911 _argvec[2+3] = (unsigned long)arg3; \
2912 _argvec[2+4] = (unsigned long)arg4; \
2913 _argvec[2+5] = (unsigned long)arg5; \
2914 _argvec[2+6] = (unsigned long)arg6; \
2915 _argvec[2+7] = (unsigned long)arg7; \
2916 _argvec[2+8] = (unsigned long)arg8; \
2917 _argvec[2+9] = (unsigned long)arg9; \
2918 _argvec[2+10] = (unsigned long)arg10; \
2919 _argvec[2+11] = (unsigned long)arg11; \
2920 __asm__ volatile( \
2921 "mr 11,%1\n\t" \
2922 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2923 "stw 2,-8(11)\n\t" /* save tocptr */ \
2924 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2925 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2926 /* arg11 */ \
2927 "lwz 3,44(11)\n\t" \
2928 "stw 3,64(1)\n\t" \
2929 /* arg10 */ \
2930 "lwz 3,40(11)\n\t" \
2931 "stw 3,60(1)\n\t" \
2932 /* arg9 */ \
2933 "lwz 3,36(11)\n\t" \
2934 "stw 3,56(1)\n\t" \
2935 /* args1-8 */ \
2936 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2937 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2938 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2939 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2940 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2941 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2942 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2943 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2944 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2945 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2946 "mr 11,%1\n\t" \
2947 "mr %0,3\n\t" \
2948 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2949 VG_CONTRACT_FRAME_BY(72) \
2950 VG_CONTRACT_FRAME_BY(512) \
2951 : /*out*/ "=r" (_res) \
2952 : /*in*/ "r" (&_argvec[2]) \
2953 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2954 ); \
2955 lval = (__typeof__(lval)) _res; \
2956 } while (0)
2957
2958 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2959 arg7,arg8,arg9,arg10,arg11,arg12) \
2960 do { \
2961 volatile OrigFn _orig = (orig); \
2962 volatile unsigned long _argvec[3+12]; \
2963 volatile unsigned long _res; \
2964 /* _argvec[0] holds current r2 across the call */ \
2965 _argvec[1] = (unsigned long)_orig.r2; \
2966 _argvec[2] = (unsigned long)_orig.nraddr; \
2967 _argvec[2+1] = (unsigned long)arg1; \
2968 _argvec[2+2] = (unsigned long)arg2; \
2969 _argvec[2+3] = (unsigned long)arg3; \
2970 _argvec[2+4] = (unsigned long)arg4; \
2971 _argvec[2+5] = (unsigned long)arg5; \
2972 _argvec[2+6] = (unsigned long)arg6; \
2973 _argvec[2+7] = (unsigned long)arg7; \
2974 _argvec[2+8] = (unsigned long)arg8; \
2975 _argvec[2+9] = (unsigned long)arg9; \
2976 _argvec[2+10] = (unsigned long)arg10; \
2977 _argvec[2+11] = (unsigned long)arg11; \
2978 _argvec[2+12] = (unsigned long)arg12; \
2979 __asm__ volatile( \
2980 "mr 11,%1\n\t" \
2981 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2982 "stw 2,-8(11)\n\t" /* save tocptr */ \
2983 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2984 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2985 /* arg12 */ \
2986 "lwz 3,48(11)\n\t" \
2987 "stw 3,68(1)\n\t" \
2988 /* arg11 */ \
2989 "lwz 3,44(11)\n\t" \
2990 "stw 3,64(1)\n\t" \
2991 /* arg10 */ \
2992 "lwz 3,40(11)\n\t" \
2993 "stw 3,60(1)\n\t" \
2994 /* arg9 */ \
2995 "lwz 3,36(11)\n\t" \
2996 "stw 3,56(1)\n\t" \
2997 /* args1-8 */ \
2998 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2999 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3000 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3001 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3002 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3003 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3004 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3005 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3006 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3007 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3008 "mr 11,%1\n\t" \
3009 "mr %0,3\n\t" \
3010 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3011 VG_CONTRACT_FRAME_BY(72) \
3012 VG_CONTRACT_FRAME_BY(512) \
3013 : /*out*/ "=r" (_res) \
3014 : /*in*/ "r" (&_argvec[2]) \
3015 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3016 ); \
3017 lval = (__typeof__(lval)) _res; \
3018 } while (0)
3019
3020 #endif /* PLAT_ppc32_aix5 */
3021
3022 /* ------------------------ ppc64-aix5 ------------------------- */
3023
3024 #if defined(PLAT_ppc64_aix5)
3025
3026 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3027
3028 /* These regs are trashed by the hidden call. */
3029 #define __CALLER_SAVED_REGS \
3030 "lr", "ctr", "xer", \
3031 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3032 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3033 "r11", "r12", "r13"
3034
3035 /* Expand the stack frame, copying enough info that unwinding
3036 still works. Trashes r3. */
3037
3038 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3039 "addi 1,1,-" #_n_fr "\n\t" \
3040 "ld 3," #_n_fr "(1)\n\t" \
3041 "std 3,0(1)\n\t"
3042
3043 #define VG_CONTRACT_FRAME_BY(_n_fr) \
3044 "addi 1,1," #_n_fr "\n\t"
3045
3046 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3047 long) == 8. */
3048
3049 #define CALL_FN_W_v(lval, orig) \
3050 do { \
3051 volatile OrigFn _orig = (orig); \
3052 volatile unsigned long _argvec[3+0]; \
3053 volatile unsigned long _res; \
3054 /* _argvec[0] holds current r2 across the call */ \
3055 _argvec[1] = (unsigned long)_orig.r2; \
3056 _argvec[2] = (unsigned long)_orig.nraddr; \
3057 __asm__ volatile( \
3058 "mr 11,%1\n\t" \
3059 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3060 "std 2,-16(11)\n\t" /* save tocptr */ \
3061 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3062 "ld 11, 0(11)\n\t" /* target->r11 */ \
3063 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3064 "mr 11,%1\n\t" \
3065 "mr %0,3\n\t" \
3066 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3067 VG_CONTRACT_FRAME_BY(512) \
3068 : /*out*/ "=r" (_res) \
3069 : /*in*/ "r" (&_argvec[2]) \
3070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3071 ); \
3072 lval = (__typeof__(lval)) _res; \
3073 } while (0)
3074
3075 #define CALL_FN_W_W(lval, orig, arg1) \
3076 do { \
3077 volatile OrigFn _orig = (orig); \