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