blob: 61f8803f709650aa93789fca8ef981ffa725b1e5 [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001/* -*- c -*-
njn25e49d8e72002-09-23 09:36:25 +00002 ----------------------------------------------------------------
3
4 Notice that the following BSD-style license applies to this one
njn7fd15d62006-03-31 12:05:04 +00005 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.
njn25e49d8e72002-09-23 09:36:25 +00009
10 ----------------------------------------------------------------
11
njnb9c427c2004-12-01 14:14:42 +000012 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
sewardjde4a1d02002-03-22 01:27:54 +000014
sewardj9eecbbb2010-05-03 21:37:12 +000015 Copyright (C) 2000-2010 Julian Seward. All rights reserved.
sewardjde4a1d02002-03-22 01:27:54 +000016
njn25e49d8e72002-09-23 09:36:25 +000017 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
sewardjde4a1d02002-03-22 01:27:54 +000020
njn25e49d8e72002-09-23 09:36:25 +000021 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
sewardjde4a1d02002-03-22 01:27:54 +000023
njn25e49d8e72002-09-23 09:36:25 +000024 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.
sewardjde4a1d02002-03-22 01:27:54 +000028
njn25e49d8e72002-09-23 09:36:25 +000029 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 ----------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000056*/
57
58
njn30d76c62005-06-18 15:07:39 +000059/* 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
sewardj0ec07f32006-01-12 12:32:32 +000067 consumes very few (eg. 7) instructions, so the resulting performance
njn30d76c62005-06-18 15:07:39 +000068 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
sewardjde4a1d02002-03-22 01:27:54 +000073#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
sewardj71044162010-03-03 22:57:47 +000076
77/* ------------------------------------------------------------------ */
78/* VERSION NUMBER OF VALGRIND */
79/* ------------------------------------------------------------------ */
80
81/* Specify Valgrind's version number, so that user code can
sewardj0fe1d4c2010-04-19 08:43:26 +000082 conditionally compile based on our version number. Note that these
83 were introduced at version 3.6 and so do not exist in version 3.5
84 or earlier. The recommended way to use them to check for "version
85 X.Y or later" is (eg)
86
87#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
88 && (__VALGRIND_MAJOR__ > 3 \
89 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
90*/
91#define __VALGRIND_MAJOR__ 3
sewardj71044162010-03-03 22:57:47 +000092#define __VALGRIND_MINOR__ 6
93
94
fitzhardinge39de4b42003-10-31 07:12:21 +000095#include <stdarg.h>
96
njn3dd0a912005-06-28 19:44:10 +000097/* Nb: this file might be included in a file compiled with -ansi. So
98 we can't use C++ style "//" comments nor the "asm" keyword (instead
99 use "__asm__"). */
100
sewardjf5c1a7f2006-10-17 01:32:48 +0000101/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +0000102 that in this file we're using the compiler's CPP symbols for
103 identifying architectures, which are different to the ones we use
104 within the rest of Valgrind. Note, __powerpc__ is active for both
105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardj59570ff2010-01-01 11:59:33 +0000106 latter (on Linux, that is).
107
108 Misc note: how to find out what's predefined in gcc by default:
109 gcc -Wp,-dM somefile.c
110*/
sewardj7af32302010-01-02 10:37:58 +0000111#undef PLAT_ppc64_aix5
112#undef PLAT_ppc32_aix5
113#undef PLAT_x86_darwin
114#undef PLAT_amd64_darwin
bart7f489812010-08-27 10:05:27 +0000115#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +0000116#undef PLAT_x86_linux
117#undef PLAT_amd64_linux
118#undef PLAT_ppc32_linux
119#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000120#undef PLAT_arm_linux
sewardj0ec07f32006-01-12 12:32:32 +0000121
njnf76d27a2009-05-28 01:53:07 +0000122#if defined(_AIX) && defined(__64BIT__)
sewardjf5c1a7f2006-10-17 01:32:48 +0000123# define PLAT_ppc64_aix5 1
124#elif defined(_AIX) && !defined(__64BIT__)
125# define PLAT_ppc32_aix5 1
njnf76d27a2009-05-28 01:53:07 +0000126#elif defined(__APPLE__) && defined(__i386__)
127# define PLAT_x86_darwin 1
128#elif defined(__APPLE__) && defined(__x86_64__)
129# define PLAT_amd64_darwin 1
bart7f489812010-08-27 10:05:27 +0000130#elif defined(__MINGW32__) || defined(__CYGWIN32__) || defined(_WIN32) && defined(_M_IX86)
131# define PLAT_x86_win32 1
sewardj59570ff2010-01-01 11:59:33 +0000132#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000133# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000134#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000135# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000136#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000137# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000138#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000139# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000140#elif defined(__linux__) && defined(__arm__)
141# define PLAT_arm_linux 1
njnf76d27a2009-05-28 01:53:07 +0000142#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000143/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000144 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000145# if !defined(NVALGRIND)
146# define NVALGRIND 1
147# endif
148#endif
149
150
njn30d76c62005-06-18 15:07:39 +0000151/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000152/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
153/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000154/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000155
sewardj0ec07f32006-01-12 12:32:32 +0000156#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000157
158/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000159 from the compiled code (analogous to NDEBUG's effects on
160 assert()) */
161#define VALGRIND_DO_CLIENT_REQUEST( \
162 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000163 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000164 { \
165 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000166 }
167
sewardj0ec07f32006-01-12 12:32:32 +0000168#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000169
sewardj0ec07f32006-01-12 12:32:32 +0000170/* The following defines the magic code sequences which the JITter
171 spots and handles magically. Don't look too closely at them as
172 they will rot your brain.
173
174 The assembly code sequences for all architectures is in this one
175 file. This is because this file must be stand-alone, and we don't
176 want to have multiple files.
177
178 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
179 value gets put in the return slot, so that everything works when
180 this is executed not under Valgrind. Args are passed in a memory
181 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000182 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000183
nethercote54265442004-10-26 12:56:58 +0000184 The macro args are:
185 _zzq_rlval result lvalue
186 _zzq_default default value (result returned when running on real CPU)
187 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000188 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000189
sewardj0ec07f32006-01-12 12:32:32 +0000190 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000191 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
192 guest's NRADDR pseudo-register and whatever other information is
193 needed to safely run the call original from the wrapper: on
194 ppc64-linux, the R2 value at the divert point is also needed. This
195 information is abstracted into a user-visible type, OrigFn.
196
197 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
198 guest, but guarantees that the branch instruction will not be
199 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
200 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
201 complete inline asm, since it needs to be combined with more magic
202 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000203*/
204
njnf76d27a2009-05-28 01:53:07 +0000205/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000206
sewardj520a03a2010-10-07 10:46:15 +0000207#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000208 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000209
210typedef
211 struct {
212 unsigned int nraddr; /* where's the code? */
213 }
214 OrigFn;
215
sewardj0ec07f32006-01-12 12:32:32 +0000216#define __SPECIAL_INSTRUCTION_PREAMBLE \
217 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000218 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000219
sewardj0ec07f32006-01-12 12:32:32 +0000220#define VALGRIND_DO_CLIENT_REQUEST( \
221 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000222 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
223 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000224 volatile unsigned int _zzq_result; \
225 _zzq_args[0] = (unsigned int)(_zzq_request); \
226 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
227 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
228 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
229 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000230 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000231 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
232 /* %EDX = client_request ( %EAX ) */ \
233 "xchgl %%ebx,%%ebx" \
234 : "=d" (_zzq_result) \
235 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
236 : "cc", "memory" \
237 ); \
238 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000239 }
sewardj2c48c7b2005-11-29 13:05:56 +0000240
sewardjc8858442006-01-20 15:17:20 +0000241#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
242 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
243 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000244 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
245 /* %EAX = guest_NRADDR */ \
246 "xchgl %%ecx,%%ecx" \
247 : "=a" (__addr) \
248 : \
249 : "cc", "memory" \
250 ); \
sewardjc8858442006-01-20 15:17:20 +0000251 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000252 }
sewardj0ec07f32006-01-12 12:32:32 +0000253
254#define VALGRIND_CALL_NOREDIR_EAX \
255 __SPECIAL_INSTRUCTION_PREAMBLE \
256 /* call-noredir *%EAX */ \
257 "xchgl %%edx,%%edx\n\t"
sewardj60227842010-10-07 10:00:56 +0000258#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000259
260/* ------------------------- x86-Win32 ------------------------- */
261
262#if defined(PLAT_x86_win32) && !defined(__GNUC__)
263
264typedef
265 struct {
266 unsigned int nraddr; /* where's the code? */
267 }
268 OrigFn;
269
270#if defined(_MSC_VER)
271
272#define __SPECIAL_INSTRUCTION_PREAMBLE \
273 __asm rol edi, 3 __asm rol edi, 13 \
274 __asm rol edi, 29 __asm rol edi, 19
275
276#define VALGRIND_DO_CLIENT_REQUEST( \
277 _zzq_rlval, _zzq_default, _zzq_request, \
278 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bartfa5115a2010-09-02 09:33:02 +0000279 { volatile uintptr_t _zzq_args[6]; \
bart7f489812010-08-27 10:05:27 +0000280 volatile unsigned int _zzq_result; \
bartfa5115a2010-09-02 09:33:02 +0000281 _zzq_args[0] = (uintptr_t)(_zzq_request); \
282 _zzq_args[1] = (uintptr_t)(_zzq_arg1); \
283 _zzq_args[2] = (uintptr_t)(_zzq_arg2); \
284 _zzq_args[3] = (uintptr_t)(_zzq_arg3); \
285 _zzq_args[4] = (uintptr_t)(_zzq_arg4); \
286 _zzq_args[5] = (uintptr_t)(_zzq_arg5); \
bart7f489812010-08-27 10:05:27 +0000287 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default \
288 __SPECIAL_INSTRUCTION_PREAMBLE \
289 /* %EDX = client_request ( %EAX ) */ \
290 __asm xchg ebx,ebx \
291 __asm mov _zzq_result, edx \
292 } \
293 _zzq_rlval = _zzq_result; \
294 }
295
296#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
297 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
298 volatile unsigned int __addr; \
299 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
300 /* %EAX = guest_NRADDR */ \
301 __asm xchg ecx,ecx \
302 __asm mov __addr, eax \
303 } \
304 _zzq_orig->nraddr = __addr; \
305 }
306
307#define VALGRIND_CALL_NOREDIR_EAX ERROR
308
309#else
310#error Unsupported compiler.
311#endif
312
313#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000314
njnf76d27a2009-05-28 01:53:07 +0000315/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000316
njnf76d27a2009-05-28 01:53:07 +0000317#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000318
319typedef
320 struct {
321 unsigned long long int nraddr; /* where's the code? */
322 }
323 OrigFn;
324
sewardj0ec07f32006-01-12 12:32:32 +0000325#define __SPECIAL_INSTRUCTION_PREAMBLE \
326 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000327 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000328
329#define VALGRIND_DO_CLIENT_REQUEST( \
330 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000331 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
332 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000333 volatile unsigned long long int _zzq_result; \
334 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
335 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
336 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
337 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
338 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000339 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000340 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
341 /* %RDX = client_request ( %RAX ) */ \
342 "xchgq %%rbx,%%rbx" \
343 : "=d" (_zzq_result) \
344 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
345 : "cc", "memory" \
346 ); \
347 _zzq_rlval = _zzq_result; \
348 }
349
sewardjc8858442006-01-20 15:17:20 +0000350#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
351 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
352 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000353 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
354 /* %RAX = guest_NRADDR */ \
355 "xchgq %%rcx,%%rcx" \
356 : "=a" (__addr) \
357 : \
358 : "cc", "memory" \
359 ); \
sewardjc8858442006-01-20 15:17:20 +0000360 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000361 }
362
363#define VALGRIND_CALL_NOREDIR_RAX \
364 __SPECIAL_INSTRUCTION_PREAMBLE \
365 /* call-noredir *%RAX */ \
366 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000367#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000368
sewardjf5c1a7f2006-10-17 01:32:48 +0000369/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000370
sewardjf5c1a7f2006-10-17 01:32:48 +0000371#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000372
373typedef
374 struct {
sewardjc8858442006-01-20 15:17:20 +0000375 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000376 }
377 OrigFn;
378
sewardj0ec07f32006-01-12 12:32:32 +0000379#define __SPECIAL_INSTRUCTION_PREAMBLE \
380 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000381 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000382
383#define VALGRIND_DO_CLIENT_REQUEST( \
384 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000385 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000386 \
sewardj9af10a12006-02-01 14:59:42 +0000387 { unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000388 unsigned int _zzq_result; \
389 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000390 _zzq_args[0] = (unsigned int)(_zzq_request); \
391 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
392 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
393 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
394 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000395 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000396 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000397 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
398 "mr 4,%2\n\t" /*ptr*/ \
399 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000400 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000401 "or 1,1,1\n\t" \
402 "mr %0,3" /*result*/ \
403 : "=b" (_zzq_result) \
404 : "b" (_zzq_default), "b" (_zzq_ptr) \
405 : "cc", "memory", "r3", "r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000406 _zzq_rlval = _zzq_result; \
407 }
408
sewardjd68ac3e2006-01-20 14:31:57 +0000409#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
410 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000411 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000412 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
413 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000414 "or 2,2,2\n\t" \
415 "mr %0,3" \
416 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000417 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000418 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000419 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000420 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000421 }
422
423#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
424 __SPECIAL_INSTRUCTION_PREAMBLE \
425 /* branch-and-link-to-noredir *%R11 */ \
426 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000427#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000428
sewardjf5c1a7f2006-10-17 01:32:48 +0000429/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000430
sewardjf5c1a7f2006-10-17 01:32:48 +0000431#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000432
433typedef
434 struct {
435 unsigned long long int nraddr; /* where's the code? */
436 unsigned long long int r2; /* what tocptr do we need? */
437 }
438 OrigFn;
439
sewardj1a85f4f2006-01-12 21:15:35 +0000440#define __SPECIAL_INSTRUCTION_PREAMBLE \
441 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
442 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
443
sewardj0ec07f32006-01-12 12:32:32 +0000444#define VALGRIND_DO_CLIENT_REQUEST( \
445 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000446 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000447 \
sewardj9af10a12006-02-01 14:59:42 +0000448 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000449 register unsigned long long int _zzq_result __asm__("r3"); \
450 register unsigned long long int* _zzq_ptr __asm__("r4"); \
451 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
452 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
453 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
454 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
455 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000456 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000457 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000458 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
459 /* %R3 = client_request ( %R4 ) */ \
460 "or 1,1,1" \
461 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000462 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000463 : "cc", "memory"); \
464 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000465 }
sewardj1a85f4f2006-01-12 21:15:35 +0000466
sewardjd68ac3e2006-01-20 14:31:57 +0000467#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
468 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
469 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000470 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
471 /* %R3 = guest_NRADDR */ \
472 "or 2,2,2" \
473 : "=r" (__addr) \
474 : \
475 : "cc", "memory" \
476 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000477 _zzq_orig->nraddr = __addr; \
478 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
479 /* %R3 = guest_NRADDR_GPR2 */ \
480 "or 4,4,4" \
481 : "=r" (__addr) \
482 : \
483 : "cc", "memory" \
484 ); \
485 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000486 }
487
488#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
489 __SPECIAL_INSTRUCTION_PREAMBLE \
490 /* branch-and-link-to-noredir *%R11 */ \
491 "or 3,3,3\n\t"
492
sewardjf5c1a7f2006-10-17 01:32:48 +0000493#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000494
sewardj59570ff2010-01-01 11:59:33 +0000495/* ------------------------- arm-linux ------------------------- */
496
497#if defined(PLAT_arm_linux)
498
499typedef
500 struct {
501 unsigned int nraddr; /* where's the code? */
502 }
503 OrigFn;
504
505#define __SPECIAL_INSTRUCTION_PREAMBLE \
506 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
507 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
508
509#define VALGRIND_DO_CLIENT_REQUEST( \
510 _zzq_rlval, _zzq_default, _zzq_request, \
511 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
512 \
513 { volatile unsigned int _zzq_args[6]; \
514 volatile unsigned int _zzq_result; \
515 _zzq_args[0] = (unsigned int)(_zzq_request); \
516 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
517 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
518 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
519 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
520 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
521 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
522 "mov r4, %2\n\t" /*ptr*/ \
523 __SPECIAL_INSTRUCTION_PREAMBLE \
524 /* R3 = client_request ( R4 ) */ \
525 "orr r10, r10, r10\n\t" \
526 "mov %0, r3" /*result*/ \
527 : "=r" (_zzq_result) \
528 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
529 : "cc","memory", "r3", "r4"); \
530 _zzq_rlval = _zzq_result; \
531 }
532
533#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
534 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
535 unsigned int __addr; \
536 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
537 /* R3 = guest_NRADDR */ \
538 "orr r11, r11, r11\n\t" \
539 "mov %0, r3" \
540 : "=r" (__addr) \
541 : \
542 : "cc", "memory", "r3" \
543 ); \
544 _zzq_orig->nraddr = __addr; \
545 }
546
547#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
548 __SPECIAL_INSTRUCTION_PREAMBLE \
549 /* branch-and-link-to-noredir *%R4 */ \
550 "orr r12, r12, r12\n\t"
551
552#endif /* PLAT_arm_linux */
553
sewardjf5c1a7f2006-10-17 01:32:48 +0000554/* ------------------------ ppc32-aix5 ------------------------- */
555
556#if defined(PLAT_ppc32_aix5)
557
558typedef
559 struct {
560 unsigned int nraddr; /* where's the code? */
561 unsigned int r2; /* what tocptr do we need? */
562 }
563 OrigFn;
564
565#define __SPECIAL_INSTRUCTION_PREAMBLE \
566 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
567 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
568
569#define VALGRIND_DO_CLIENT_REQUEST( \
570 _zzq_rlval, _zzq_default, _zzq_request, \
571 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
572 \
573 { unsigned int _zzq_args[7]; \
574 register unsigned int _zzq_result; \
575 register unsigned int* _zzq_ptr; \
576 _zzq_args[0] = (unsigned int)(_zzq_request); \
577 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
578 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
579 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
580 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
581 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
582 _zzq_args[6] = (unsigned int)(_zzq_default); \
583 _zzq_ptr = _zzq_args; \
584 __asm__ volatile("mr 4,%1\n\t" \
585 "lwz 3, 24(4)\n\t" \
586 __SPECIAL_INSTRUCTION_PREAMBLE \
587 /* %R3 = client_request ( %R4 ) */ \
588 "or 1,1,1\n\t" \
589 "mr %0,3" \
590 : "=b" (_zzq_result) \
591 : "b" (_zzq_ptr) \
592 : "r3", "r4", "cc", "memory"); \
593 _zzq_rlval = _zzq_result; \
594 }
595
596#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
597 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
598 register unsigned int __addr; \
599 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
600 /* %R3 = guest_NRADDR */ \
601 "or 2,2,2\n\t" \
602 "mr %0,3" \
603 : "=b" (__addr) \
604 : \
605 : "r3", "cc", "memory" \
606 ); \
607 _zzq_orig->nraddr = __addr; \
608 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
609 /* %R3 = guest_NRADDR_GPR2 */ \
610 "or 4,4,4\n\t" \
611 "mr %0,3" \
612 : "=b" (__addr) \
613 : \
614 : "r3", "cc", "memory" \
615 ); \
616 _zzq_orig->r2 = __addr; \
617 }
618
619#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
620 __SPECIAL_INSTRUCTION_PREAMBLE \
621 /* branch-and-link-to-noredir *%R11 */ \
622 "or 3,3,3\n\t"
623
624#endif /* PLAT_ppc32_aix5 */
625
626/* ------------------------ ppc64-aix5 ------------------------- */
627
628#if defined(PLAT_ppc64_aix5)
629
630typedef
631 struct {
632 unsigned long long int nraddr; /* where's the code? */
633 unsigned long long int r2; /* what tocptr do we need? */
634 }
635 OrigFn;
636
637#define __SPECIAL_INSTRUCTION_PREAMBLE \
638 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
639 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
640
641#define VALGRIND_DO_CLIENT_REQUEST( \
642 _zzq_rlval, _zzq_default, _zzq_request, \
643 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
644 \
645 { unsigned long long int _zzq_args[7]; \
646 register unsigned long long int _zzq_result; \
647 register unsigned long long int* _zzq_ptr; \
648 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
649 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
650 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
651 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
652 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
653 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
654 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
655 _zzq_ptr = _zzq_args; \
656 __asm__ volatile("mr 4,%1\n\t" \
657 "ld 3, 48(4)\n\t" \
658 __SPECIAL_INSTRUCTION_PREAMBLE \
659 /* %R3 = client_request ( %R4 ) */ \
660 "or 1,1,1\n\t" \
661 "mr %0,3" \
662 : "=b" (_zzq_result) \
663 : "b" (_zzq_ptr) \
664 : "r3", "r4", "cc", "memory"); \
665 _zzq_rlval = _zzq_result; \
666 }
667
668#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
669 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
670 register unsigned long long int __addr; \
671 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
672 /* %R3 = guest_NRADDR */ \
673 "or 2,2,2\n\t" \
674 "mr %0,3" \
675 : "=b" (__addr) \
676 : \
677 : "r3", "cc", "memory" \
678 ); \
679 _zzq_orig->nraddr = __addr; \
680 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
681 /* %R3 = guest_NRADDR_GPR2 */ \
682 "or 4,4,4\n\t" \
683 "mr %0,3" \
684 : "=b" (__addr) \
685 : \
686 : "r3", "cc", "memory" \
687 ); \
688 _zzq_orig->r2 = __addr; \
689 }
690
691#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
692 __SPECIAL_INSTRUCTION_PREAMBLE \
693 /* branch-and-link-to-noredir *%R11 */ \
694 "or 3,3,3\n\t"
695
696#endif /* PLAT_ppc64_aix5 */
697
698/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000699
sewardj37091fb2002-11-16 11:06:50 +0000700#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000701
nethercote69d9c462004-10-26 13:00:12 +0000702
njn30d76c62005-06-18 15:07:39 +0000703/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000704/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000705/* ugly. It's the least-worst tradeoff I can think of. */
706/* ------------------------------------------------------------------ */
707
708/* This section defines magic (a.k.a appalling-hack) macros for doing
709 guaranteed-no-redirection macros, so as to get from function
710 wrappers to the functions they are wrapping. The whole point is to
711 construct standard call sequences, but to do the call itself with a
712 special no-redirect call pseudo-instruction that the JIT
713 understands and handles specially. This section is long and
714 repetitious, and I can't see a way to make it shorter.
715
716 The naming scheme is as follows:
717
718 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
719
720 'W' stands for "word" and 'v' for "void". Hence there are
721 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
722 and for each, the possibility of returning a word-typed result, or
723 no result.
724*/
725
726/* Use these to write the name of your wrapper. NOTE: duplicates
727 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
728
njn5f5ef2a2009-05-11 08:01:09 +0000729/* Use an extra level of macroisation so as to ensure the soname/fnname
730 args are fully macro-expanded before pasting them together. */
731#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
732
sewardj0ec07f32006-01-12 12:32:32 +0000733#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000734 VG_CONCAT4(_vgwZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000735
736#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000737 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000738
sewardjd68ac3e2006-01-20 14:31:57 +0000739/* Use this macro from within a wrapper function to collect the
740 context (address and possibly other info) of the original function.
741 Once you have that you can then use it in one of the CALL_FN_
742 macros. The type of the argument _lval is OrigFn. */
743#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000744
745/* Derivatives of the main macros below, for calling functions
746 returning void. */
747
748#define CALL_FN_v_v(fnptr) \
749 do { volatile unsigned long _junk; \
750 CALL_FN_W_v(_junk,fnptr); } while (0)
751
752#define CALL_FN_v_W(fnptr, arg1) \
753 do { volatile unsigned long _junk; \
754 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
755
756#define CALL_FN_v_WW(fnptr, arg1,arg2) \
757 do { volatile unsigned long _junk; \
758 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
759
sewardj5ce4b152006-03-11 12:57:41 +0000760#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
761 do { volatile unsigned long _junk; \
762 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
763
njn2b5f0a92009-05-19 01:24:50 +0000764#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
765 do { volatile unsigned long _junk; \
766 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
767
768#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
769 do { volatile unsigned long _junk; \
770 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
771
772#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
773 do { volatile unsigned long _junk; \
774 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
775
776#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
777 do { volatile unsigned long _junk; \
778 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
779
njnf76d27a2009-05-28 01:53:07 +0000780/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000781
njnf76d27a2009-05-28 01:53:07 +0000782#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000783
784/* These regs are trashed by the hidden call. No need to mention eax
785 as gcc can already see that, plus causes gcc to bomb. */
786#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
787
788/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
789 long) == 4. */
790
sewardj66226cc2006-01-20 15:46:46 +0000791#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000792 do { \
sewardj66226cc2006-01-20 15:46:46 +0000793 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000794 volatile unsigned long _argvec[1]; \
795 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000796 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000797 __asm__ volatile( \
798 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
799 VALGRIND_CALL_NOREDIR_EAX \
800 : /*out*/ "=a" (_res) \
801 : /*in*/ "a" (&_argvec[0]) \
802 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
803 ); \
804 lval = (__typeof__(lval)) _res; \
805 } while (0)
806
sewardj66226cc2006-01-20 15:46:46 +0000807#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000808 do { \
sewardj66226cc2006-01-20 15:46:46 +0000809 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000810 volatile unsigned long _argvec[2]; \
811 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000812 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000813 _argvec[1] = (unsigned long)(arg1); \
814 __asm__ volatile( \
815 "pushl 4(%%eax)\n\t" \
816 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
817 VALGRIND_CALL_NOREDIR_EAX \
818 "addl $4, %%esp\n" \
819 : /*out*/ "=a" (_res) \
820 : /*in*/ "a" (&_argvec[0]) \
821 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
822 ); \
823 lval = (__typeof__(lval)) _res; \
824 } while (0)
825
sewardj66226cc2006-01-20 15:46:46 +0000826#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000827 do { \
sewardj66226cc2006-01-20 15:46:46 +0000828 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000829 volatile unsigned long _argvec[3]; \
830 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000831 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000832 _argvec[1] = (unsigned long)(arg1); \
833 _argvec[2] = (unsigned long)(arg2); \
834 __asm__ volatile( \
835 "pushl 8(%%eax)\n\t" \
836 "pushl 4(%%eax)\n\t" \
837 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
838 VALGRIND_CALL_NOREDIR_EAX \
839 "addl $8, %%esp\n" \
840 : /*out*/ "=a" (_res) \
841 : /*in*/ "a" (&_argvec[0]) \
842 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
843 ); \
844 lval = (__typeof__(lval)) _res; \
845 } while (0)
846
sewardj9e8b07a2006-02-18 21:13:29 +0000847#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
848 do { \
849 volatile OrigFn _orig = (orig); \
850 volatile unsigned long _argvec[4]; \
851 volatile unsigned long _res; \
852 _argvec[0] = (unsigned long)_orig.nraddr; \
853 _argvec[1] = (unsigned long)(arg1); \
854 _argvec[2] = (unsigned long)(arg2); \
855 _argvec[3] = (unsigned long)(arg3); \
856 __asm__ volatile( \
857 "pushl 12(%%eax)\n\t" \
858 "pushl 8(%%eax)\n\t" \
859 "pushl 4(%%eax)\n\t" \
860 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
861 VALGRIND_CALL_NOREDIR_EAX \
862 "addl $12, %%esp\n" \
863 : /*out*/ "=a" (_res) \
864 : /*in*/ "a" (&_argvec[0]) \
865 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
866 ); \
867 lval = (__typeof__(lval)) _res; \
868 } while (0)
869
sewardj66226cc2006-01-20 15:46:46 +0000870#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000871 do { \
sewardj66226cc2006-01-20 15:46:46 +0000872 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000873 volatile unsigned long _argvec[5]; \
874 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000875 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000876 _argvec[1] = (unsigned long)(arg1); \
877 _argvec[2] = (unsigned long)(arg2); \
878 _argvec[3] = (unsigned long)(arg3); \
879 _argvec[4] = (unsigned long)(arg4); \
880 __asm__ volatile( \
881 "pushl 16(%%eax)\n\t" \
882 "pushl 12(%%eax)\n\t" \
883 "pushl 8(%%eax)\n\t" \
884 "pushl 4(%%eax)\n\t" \
885 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
886 VALGRIND_CALL_NOREDIR_EAX \
887 "addl $16, %%esp\n" \
888 : /*out*/ "=a" (_res) \
889 : /*in*/ "a" (&_argvec[0]) \
890 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
891 ); \
892 lval = (__typeof__(lval)) _res; \
893 } while (0)
894
sewardj66226cc2006-01-20 15:46:46 +0000895#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000896 do { \
sewardj66226cc2006-01-20 15:46:46 +0000897 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000898 volatile unsigned long _argvec[6]; \
899 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000900 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000901 _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 __asm__ volatile( \
907 "pushl 20(%%eax)\n\t" \
908 "pushl 16(%%eax)\n\t" \
909 "pushl 12(%%eax)\n\t" \
910 "pushl 8(%%eax)\n\t" \
911 "pushl 4(%%eax)\n\t" \
912 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
913 VALGRIND_CALL_NOREDIR_EAX \
914 "addl $20, %%esp\n" \
915 : /*out*/ "=a" (_res) \
916 : /*in*/ "a" (&_argvec[0]) \
917 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
918 ); \
919 lval = (__typeof__(lval)) _res; \
920 } while (0)
921
sewardj66226cc2006-01-20 15:46:46 +0000922#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000923 do { \
sewardj66226cc2006-01-20 15:46:46 +0000924 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000925 volatile unsigned long _argvec[7]; \
926 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000927 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000928 _argvec[1] = (unsigned long)(arg1); \
929 _argvec[2] = (unsigned long)(arg2); \
930 _argvec[3] = (unsigned long)(arg3); \
931 _argvec[4] = (unsigned long)(arg4); \
932 _argvec[5] = (unsigned long)(arg5); \
933 _argvec[6] = (unsigned long)(arg6); \
934 __asm__ volatile( \
935 "pushl 24(%%eax)\n\t" \
936 "pushl 20(%%eax)\n\t" \
937 "pushl 16(%%eax)\n\t" \
938 "pushl 12(%%eax)\n\t" \
939 "pushl 8(%%eax)\n\t" \
940 "pushl 4(%%eax)\n\t" \
941 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
942 VALGRIND_CALL_NOREDIR_EAX \
943 "addl $24, %%esp\n" \
944 : /*out*/ "=a" (_res) \
945 : /*in*/ "a" (&_argvec[0]) \
946 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
947 ); \
948 lval = (__typeof__(lval)) _res; \
949 } while (0)
950
sewardj66226cc2006-01-20 15:46:46 +0000951#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
952 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000953 do { \
sewardj66226cc2006-01-20 15:46:46 +0000954 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000955 volatile unsigned long _argvec[8]; \
956 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000957 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000958 _argvec[1] = (unsigned long)(arg1); \
959 _argvec[2] = (unsigned long)(arg2); \
960 _argvec[3] = (unsigned long)(arg3); \
961 _argvec[4] = (unsigned long)(arg4); \
962 _argvec[5] = (unsigned long)(arg5); \
963 _argvec[6] = (unsigned long)(arg6); \
964 _argvec[7] = (unsigned long)(arg7); \
965 __asm__ volatile( \
966 "pushl 28(%%eax)\n\t" \
967 "pushl 24(%%eax)\n\t" \
968 "pushl 20(%%eax)\n\t" \
969 "pushl 16(%%eax)\n\t" \
970 "pushl 12(%%eax)\n\t" \
971 "pushl 8(%%eax)\n\t" \
972 "pushl 4(%%eax)\n\t" \
973 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
974 VALGRIND_CALL_NOREDIR_EAX \
975 "addl $28, %%esp\n" \
976 : /*out*/ "=a" (_res) \
977 : /*in*/ "a" (&_argvec[0]) \
978 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
979 ); \
980 lval = (__typeof__(lval)) _res; \
981 } while (0)
982
sewardj66226cc2006-01-20 15:46:46 +0000983#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
984 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000985 do { \
sewardj66226cc2006-01-20 15:46:46 +0000986 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000987 volatile unsigned long _argvec[9]; \
988 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000989 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000990 _argvec[1] = (unsigned long)(arg1); \
991 _argvec[2] = (unsigned long)(arg2); \
992 _argvec[3] = (unsigned long)(arg3); \
993 _argvec[4] = (unsigned long)(arg4); \
994 _argvec[5] = (unsigned long)(arg5); \
995 _argvec[6] = (unsigned long)(arg6); \
996 _argvec[7] = (unsigned long)(arg7); \
997 _argvec[8] = (unsigned long)(arg8); \
998 __asm__ volatile( \
999 "pushl 32(%%eax)\n\t" \
1000 "pushl 28(%%eax)\n\t" \
1001 "pushl 24(%%eax)\n\t" \
1002 "pushl 20(%%eax)\n\t" \
1003 "pushl 16(%%eax)\n\t" \
1004 "pushl 12(%%eax)\n\t" \
1005 "pushl 8(%%eax)\n\t" \
1006 "pushl 4(%%eax)\n\t" \
1007 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1008 VALGRIND_CALL_NOREDIR_EAX \
1009 "addl $32, %%esp\n" \
1010 : /*out*/ "=a" (_res) \
1011 : /*in*/ "a" (&_argvec[0]) \
1012 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1013 ); \
1014 lval = (__typeof__(lval)) _res; \
1015 } while (0)
1016
sewardj45fa5b02006-03-09 19:06:23 +00001017#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1018 arg7,arg8,arg9) \
1019 do { \
1020 volatile OrigFn _orig = (orig); \
1021 volatile unsigned long _argvec[10]; \
1022 volatile unsigned long _res; \
1023 _argvec[0] = (unsigned long)_orig.nraddr; \
1024 _argvec[1] = (unsigned long)(arg1); \
1025 _argvec[2] = (unsigned long)(arg2); \
1026 _argvec[3] = (unsigned long)(arg3); \
1027 _argvec[4] = (unsigned long)(arg4); \
1028 _argvec[5] = (unsigned long)(arg5); \
1029 _argvec[6] = (unsigned long)(arg6); \
1030 _argvec[7] = (unsigned long)(arg7); \
1031 _argvec[8] = (unsigned long)(arg8); \
1032 _argvec[9] = (unsigned long)(arg9); \
1033 __asm__ volatile( \
1034 "pushl 36(%%eax)\n\t" \
1035 "pushl 32(%%eax)\n\t" \
1036 "pushl 28(%%eax)\n\t" \
1037 "pushl 24(%%eax)\n\t" \
1038 "pushl 20(%%eax)\n\t" \
1039 "pushl 16(%%eax)\n\t" \
1040 "pushl 12(%%eax)\n\t" \
1041 "pushl 8(%%eax)\n\t" \
1042 "pushl 4(%%eax)\n\t" \
1043 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1044 VALGRIND_CALL_NOREDIR_EAX \
1045 "addl $36, %%esp\n" \
1046 : /*out*/ "=a" (_res) \
1047 : /*in*/ "a" (&_argvec[0]) \
1048 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1049 ); \
1050 lval = (__typeof__(lval)) _res; \
1051 } while (0)
1052
1053#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1054 arg7,arg8,arg9,arg10) \
1055 do { \
1056 volatile OrigFn _orig = (orig); \
1057 volatile unsigned long _argvec[11]; \
1058 volatile unsigned long _res; \
1059 _argvec[0] = (unsigned long)_orig.nraddr; \
1060 _argvec[1] = (unsigned long)(arg1); \
1061 _argvec[2] = (unsigned long)(arg2); \
1062 _argvec[3] = (unsigned long)(arg3); \
1063 _argvec[4] = (unsigned long)(arg4); \
1064 _argvec[5] = (unsigned long)(arg5); \
1065 _argvec[6] = (unsigned long)(arg6); \
1066 _argvec[7] = (unsigned long)(arg7); \
1067 _argvec[8] = (unsigned long)(arg8); \
1068 _argvec[9] = (unsigned long)(arg9); \
1069 _argvec[10] = (unsigned long)(arg10); \
1070 __asm__ volatile( \
1071 "pushl 40(%%eax)\n\t" \
1072 "pushl 36(%%eax)\n\t" \
1073 "pushl 32(%%eax)\n\t" \
1074 "pushl 28(%%eax)\n\t" \
1075 "pushl 24(%%eax)\n\t" \
1076 "pushl 20(%%eax)\n\t" \
1077 "pushl 16(%%eax)\n\t" \
1078 "pushl 12(%%eax)\n\t" \
1079 "pushl 8(%%eax)\n\t" \
1080 "pushl 4(%%eax)\n\t" \
1081 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1082 VALGRIND_CALL_NOREDIR_EAX \
1083 "addl $40, %%esp\n" \
1084 : /*out*/ "=a" (_res) \
1085 : /*in*/ "a" (&_argvec[0]) \
1086 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1087 ); \
1088 lval = (__typeof__(lval)) _res; \
1089 } while (0)
1090
sewardj5ce4b152006-03-11 12:57:41 +00001091#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1092 arg6,arg7,arg8,arg9,arg10, \
1093 arg11) \
1094 do { \
1095 volatile OrigFn _orig = (orig); \
1096 volatile unsigned long _argvec[12]; \
1097 volatile unsigned long _res; \
1098 _argvec[0] = (unsigned long)_orig.nraddr; \
1099 _argvec[1] = (unsigned long)(arg1); \
1100 _argvec[2] = (unsigned long)(arg2); \
1101 _argvec[3] = (unsigned long)(arg3); \
1102 _argvec[4] = (unsigned long)(arg4); \
1103 _argvec[5] = (unsigned long)(arg5); \
1104 _argvec[6] = (unsigned long)(arg6); \
1105 _argvec[7] = (unsigned long)(arg7); \
1106 _argvec[8] = (unsigned long)(arg8); \
1107 _argvec[9] = (unsigned long)(arg9); \
1108 _argvec[10] = (unsigned long)(arg10); \
1109 _argvec[11] = (unsigned long)(arg11); \
1110 __asm__ volatile( \
1111 "pushl 44(%%eax)\n\t" \
1112 "pushl 40(%%eax)\n\t" \
1113 "pushl 36(%%eax)\n\t" \
1114 "pushl 32(%%eax)\n\t" \
1115 "pushl 28(%%eax)\n\t" \
1116 "pushl 24(%%eax)\n\t" \
1117 "pushl 20(%%eax)\n\t" \
1118 "pushl 16(%%eax)\n\t" \
1119 "pushl 12(%%eax)\n\t" \
1120 "pushl 8(%%eax)\n\t" \
1121 "pushl 4(%%eax)\n\t" \
1122 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1123 VALGRIND_CALL_NOREDIR_EAX \
1124 "addl $44, %%esp\n" \
1125 : /*out*/ "=a" (_res) \
1126 : /*in*/ "a" (&_argvec[0]) \
1127 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1128 ); \
1129 lval = (__typeof__(lval)) _res; \
1130 } while (0)
1131
sewardj66226cc2006-01-20 15:46:46 +00001132#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1133 arg6,arg7,arg8,arg9,arg10, \
1134 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001135 do { \
sewardj66226cc2006-01-20 15:46:46 +00001136 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001137 volatile unsigned long _argvec[13]; \
1138 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001139 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001140 _argvec[1] = (unsigned long)(arg1); \
1141 _argvec[2] = (unsigned long)(arg2); \
1142 _argvec[3] = (unsigned long)(arg3); \
1143 _argvec[4] = (unsigned long)(arg4); \
1144 _argvec[5] = (unsigned long)(arg5); \
1145 _argvec[6] = (unsigned long)(arg6); \
1146 _argvec[7] = (unsigned long)(arg7); \
1147 _argvec[8] = (unsigned long)(arg8); \
1148 _argvec[9] = (unsigned long)(arg9); \
1149 _argvec[10] = (unsigned long)(arg10); \
1150 _argvec[11] = (unsigned long)(arg11); \
1151 _argvec[12] = (unsigned long)(arg12); \
1152 __asm__ volatile( \
1153 "pushl 48(%%eax)\n\t" \
1154 "pushl 44(%%eax)\n\t" \
1155 "pushl 40(%%eax)\n\t" \
1156 "pushl 36(%%eax)\n\t" \
1157 "pushl 32(%%eax)\n\t" \
1158 "pushl 28(%%eax)\n\t" \
1159 "pushl 24(%%eax)\n\t" \
1160 "pushl 20(%%eax)\n\t" \
1161 "pushl 16(%%eax)\n\t" \
1162 "pushl 12(%%eax)\n\t" \
1163 "pushl 8(%%eax)\n\t" \
1164 "pushl 4(%%eax)\n\t" \
1165 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1166 VALGRIND_CALL_NOREDIR_EAX \
1167 "addl $48, %%esp\n" \
1168 : /*out*/ "=a" (_res) \
1169 : /*in*/ "a" (&_argvec[0]) \
1170 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1171 ); \
1172 lval = (__typeof__(lval)) _res; \
1173 } while (0)
1174
njnf76d27a2009-05-28 01:53:07 +00001175#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001176
njnf76d27a2009-05-28 01:53:07 +00001177/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001178
njnf76d27a2009-05-28 01:53:07 +00001179#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001180
1181/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1182
1183/* These regs are trashed by the hidden call. */
1184#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1185 "rdi", "r8", "r9", "r10", "r11"
1186
sewardjdfa55cf2010-10-06 22:07:06 +00001187/* This is all pretty complex. It's so as to make stack unwinding
1188 work reliably. See bug 243270. The basic problem is the sub and
1189 add of 128 of %rsp in all of the following macros. If gcc believes
1190 the CFA is in %rsp, then unwinding may fail, because what's at the
1191 CFA is not what gcc "expected" when it constructs the CFIs for the
1192 places where the macros are instantiated.
1193
1194 But we can't just add a CFI annotation to increase the CFA offset
1195 by 128, to match the sub of 128 from %rsp, because we don't know
1196 whether gcc has chosen %rsp as the CFA at that point, or whether it
1197 has chosen some other register (eg, %rbp). In the latter case,
1198 adding a CFI annotation to change the CFA offset is simply wrong.
1199
1200 So the solution is to get hold of the CFA using
1201 __builtin_frame_address(0), put it in a known register, and add a
1202 CFI annotation to say what the register is. We choose %rbp for
1203 this (perhaps perversely), because:
1204
1205 (1) %rbp is already subject to unwinding. If a new register was
1206 chosen then the unwinder would have to unwind it in all stack
1207 traces, which is expensive, and
1208
1209 (2) %rbp is already subject to precise exception updates in the
1210 JIT. If a new register was chosen, we'd have to have precise
1211 exceptions for it too, which reduces performance of the
1212 generated code.
1213
1214 However .. one extra complication. We can't just whack the result
1215 of __builtin_frame_address(0) into %rbp and then add %rbp to the
1216 list of trashed registers at the end of the inline assembly
1217 fragments; gcc won't allow %rbp to appear in that list. Hence
1218 instead we need to stash %rbp in %r15 for the duration of the asm,
1219 and say that %r15 is trashed instead. gcc seems happy to go with
1220 that.
1221
1222 Oh .. and this all needs to be conditionalised so that it is
1223 unchanged from before this commit, when compiled with older gccs
sewardj0681bdd2010-10-07 10:00:04 +00001224 that don't support __builtin_frame_address. And also, skip
1225 it on Darwin (at least for the moment) since I can't figure out
1226 how to do the .cfi directives there.
sewardjdfa55cf2010-10-06 22:07:06 +00001227*/
sewardj0681bdd2010-10-07 10:00:04 +00001228#if HAVE_BUILTIN_FRAME_ADDRESS && !defined(PLAT_amd64_darwin)
sewardjdfa55cf2010-10-06 22:07:06 +00001229# define __FRAME_POINTER \
1230 ,"r"(__builtin_frame_address(0))
1231# define VALGRIND_CFI_PROLOGUE \
1232 ".cfi_remember_state\n\t" \
1233 "movq %%rbp, %%r15\n\t" \
1234 "movq %0, %%rbp\n\t" \
1235 ".cfi_def_cfa rbp, 0\n\t"
1236# define VALGRIND_CFI_EPILOGUE \
1237 "movq %%r15, %%rbp\n\t" \
1238 ".cfi_restore_state\n\t"
1239#else
1240# define __FRAME_POINTER
1241# define VALGRIND_CFI_PROLOGUE
1242# define VALGRIND_CFI_EPILOGUE
1243#endif
1244
1245
sewardj0ec07f32006-01-12 12:32:32 +00001246/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1247 long) == 8. */
1248
sewardja07c2e12007-11-09 23:09:50 +00001249/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1250 macros. In order not to trash the stack redzone, we need to drop
1251 %rsp by 128 before the hidden call, and restore afterwards. The
1252 nastyness is that it is only by luck that the stack still appears
1253 to be unwindable during the hidden call - since then the behaviour
1254 of any routine using this macro does not match what the CFI data
1255 says. Sigh.
1256
1257 Why is this important? Imagine that a wrapper has a stack
1258 allocated local, and passes to the hidden call, a pointer to it.
1259 Because gcc does not know about the hidden call, it may allocate
1260 that local in the redzone. Unfortunately the hidden call may then
1261 trash it before it comes to use it. So we must step clear of the
1262 redzone, for the duration of the hidden call, to make it safe.
1263
1264 Probably the same problem afflicts the other redzone-style ABIs too
1265 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1266 self describing (none of this CFI nonsense) so at least messing
1267 with the stack pointer doesn't give a danger of non-unwindable
1268 stack. */
1269
sewardjc8858442006-01-20 15:17:20 +00001270#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001271 do { \
sewardjc8858442006-01-20 15:17:20 +00001272 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001273 volatile unsigned long _argvec[1]; \
1274 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001275 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001276 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001277 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001278 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001279 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1280 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001281 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001282 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001283 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001284 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1285 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001286 ); \
1287 lval = (__typeof__(lval)) _res; \
1288 } while (0)
1289
sewardjc8858442006-01-20 15:17:20 +00001290#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001291 do { \
sewardjc8858442006-01-20 15:17:20 +00001292 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001293 volatile unsigned long _argvec[2]; \
1294 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001295 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001296 _argvec[1] = (unsigned long)(arg1); \
1297 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001298 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001299 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001300 "movq 8(%%rax), %%rdi\n\t" \
1301 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1302 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001303 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001304 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001305 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001306 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1307 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001308 ); \
1309 lval = (__typeof__(lval)) _res; \
1310 } while (0)
1311
sewardjc8858442006-01-20 15:17:20 +00001312#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001313 do { \
sewardjc8858442006-01-20 15:17:20 +00001314 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001315 volatile unsigned long _argvec[3]; \
1316 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001317 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001318 _argvec[1] = (unsigned long)(arg1); \
1319 _argvec[2] = (unsigned long)(arg2); \
1320 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001321 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001322 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001323 "movq 16(%%rax), %%rsi\n\t" \
1324 "movq 8(%%rax), %%rdi\n\t" \
1325 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1326 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001327 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001328 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001329 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001330 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1331 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001332 ); \
1333 lval = (__typeof__(lval)) _res; \
1334 } while (0)
1335
sewardja50f9dc2006-03-11 16:19:14 +00001336#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1337 do { \
1338 volatile OrigFn _orig = (orig); \
1339 volatile unsigned long _argvec[4]; \
1340 volatile unsigned long _res; \
1341 _argvec[0] = (unsigned long)_orig.nraddr; \
1342 _argvec[1] = (unsigned long)(arg1); \
1343 _argvec[2] = (unsigned long)(arg2); \
1344 _argvec[3] = (unsigned long)(arg3); \
1345 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001346 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001347 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001348 "movq 24(%%rax), %%rdx\n\t" \
1349 "movq 16(%%rax), %%rsi\n\t" \
1350 "movq 8(%%rax), %%rdi\n\t" \
1351 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1352 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001353 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001354 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001355 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001356 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1357 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001358 ); \
1359 lval = (__typeof__(lval)) _res; \
1360 } while (0)
1361
1362#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1363 do { \
1364 volatile OrigFn _orig = (orig); \
1365 volatile unsigned long _argvec[5]; \
1366 volatile unsigned long _res; \
1367 _argvec[0] = (unsigned long)_orig.nraddr; \
1368 _argvec[1] = (unsigned long)(arg1); \
1369 _argvec[2] = (unsigned long)(arg2); \
1370 _argvec[3] = (unsigned long)(arg3); \
1371 _argvec[4] = (unsigned long)(arg4); \
1372 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001373 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001374 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001375 "movq 32(%%rax), %%rcx\n\t" \
1376 "movq 24(%%rax), %%rdx\n\t" \
1377 "movq 16(%%rax), %%rsi\n\t" \
1378 "movq 8(%%rax), %%rdi\n\t" \
1379 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1380 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001381 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001382 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001383 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001384 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1385 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001386 ); \
1387 lval = (__typeof__(lval)) _res; \
1388 } while (0)
1389
1390#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1391 do { \
1392 volatile OrigFn _orig = (orig); \
1393 volatile unsigned long _argvec[6]; \
1394 volatile unsigned long _res; \
1395 _argvec[0] = (unsigned long)_orig.nraddr; \
1396 _argvec[1] = (unsigned long)(arg1); \
1397 _argvec[2] = (unsigned long)(arg2); \
1398 _argvec[3] = (unsigned long)(arg3); \
1399 _argvec[4] = (unsigned long)(arg4); \
1400 _argvec[5] = (unsigned long)(arg5); \
1401 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001402 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001403 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001404 "movq 40(%%rax), %%r8\n\t" \
1405 "movq 32(%%rax), %%rcx\n\t" \
1406 "movq 24(%%rax), %%rdx\n\t" \
1407 "movq 16(%%rax), %%rsi\n\t" \
1408 "movq 8(%%rax), %%rdi\n\t" \
1409 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1410 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001411 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001412 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001413 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001414 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1415 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001416 ); \
1417 lval = (__typeof__(lval)) _res; \
1418 } while (0)
1419
1420#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1421 do { \
1422 volatile OrigFn _orig = (orig); \
1423 volatile unsigned long _argvec[7]; \
1424 volatile unsigned long _res; \
1425 _argvec[0] = (unsigned long)_orig.nraddr; \
1426 _argvec[1] = (unsigned long)(arg1); \
1427 _argvec[2] = (unsigned long)(arg2); \
1428 _argvec[3] = (unsigned long)(arg3); \
1429 _argvec[4] = (unsigned long)(arg4); \
1430 _argvec[5] = (unsigned long)(arg5); \
1431 _argvec[6] = (unsigned long)(arg6); \
1432 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001433 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001434 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001435 "movq 48(%%rax), %%r9\n\t" \
1436 "movq 40(%%rax), %%r8\n\t" \
1437 "movq 32(%%rax), %%rcx\n\t" \
1438 "movq 24(%%rax), %%rdx\n\t" \
1439 "movq 16(%%rax), %%rsi\n\t" \
1440 "movq 8(%%rax), %%rdi\n\t" \
1441 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1442 VALGRIND_CALL_NOREDIR_RAX \
bart2823aac2010-09-05 12:10:25 +00001443 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001444 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001445 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001446 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1447 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001448 ); \
1449 lval = (__typeof__(lval)) _res; \
1450 } while (0)
1451
1452#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1453 arg7) \
1454 do { \
1455 volatile OrigFn _orig = (orig); \
1456 volatile unsigned long _argvec[8]; \
1457 volatile unsigned long _res; \
1458 _argvec[0] = (unsigned long)_orig.nraddr; \
1459 _argvec[1] = (unsigned long)(arg1); \
1460 _argvec[2] = (unsigned long)(arg2); \
1461 _argvec[3] = (unsigned long)(arg3); \
1462 _argvec[4] = (unsigned long)(arg4); \
1463 _argvec[5] = (unsigned long)(arg5); \
1464 _argvec[6] = (unsigned long)(arg6); \
1465 _argvec[7] = (unsigned long)(arg7); \
1466 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001467 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001468 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001469 "pushq 56(%%rax)\n\t" \
1470 "movq 48(%%rax), %%r9\n\t" \
1471 "movq 40(%%rax), %%r8\n\t" \
1472 "movq 32(%%rax), %%rcx\n\t" \
1473 "movq 24(%%rax), %%rdx\n\t" \
1474 "movq 16(%%rax), %%rsi\n\t" \
1475 "movq 8(%%rax), %%rdi\n\t" \
1476 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1477 VALGRIND_CALL_NOREDIR_RAX \
1478 "addq $8, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001479 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001480 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001481 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001482 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1483 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001484 ); \
1485 lval = (__typeof__(lval)) _res; \
1486 } while (0)
1487
1488#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1489 arg7,arg8) \
1490 do { \
1491 volatile OrigFn _orig = (orig); \
1492 volatile unsigned long _argvec[9]; \
1493 volatile unsigned long _res; \
1494 _argvec[0] = (unsigned long)_orig.nraddr; \
1495 _argvec[1] = (unsigned long)(arg1); \
1496 _argvec[2] = (unsigned long)(arg2); \
1497 _argvec[3] = (unsigned long)(arg3); \
1498 _argvec[4] = (unsigned long)(arg4); \
1499 _argvec[5] = (unsigned long)(arg5); \
1500 _argvec[6] = (unsigned long)(arg6); \
1501 _argvec[7] = (unsigned long)(arg7); \
1502 _argvec[8] = (unsigned long)(arg8); \
1503 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001504 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001505 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001506 "pushq 64(%%rax)\n\t" \
1507 "pushq 56(%%rax)\n\t" \
1508 "movq 48(%%rax), %%r9\n\t" \
1509 "movq 40(%%rax), %%r8\n\t" \
1510 "movq 32(%%rax), %%rcx\n\t" \
1511 "movq 24(%%rax), %%rdx\n\t" \
1512 "movq 16(%%rax), %%rsi\n\t" \
1513 "movq 8(%%rax), %%rdi\n\t" \
1514 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1515 VALGRIND_CALL_NOREDIR_RAX \
1516 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001517 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001518 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001519 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001520 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1521 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001522 ); \
1523 lval = (__typeof__(lval)) _res; \
1524 } while (0)
1525
1526#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1527 arg7,arg8,arg9) \
1528 do { \
1529 volatile OrigFn _orig = (orig); \
1530 volatile unsigned long _argvec[10]; \
1531 volatile unsigned long _res; \
1532 _argvec[0] = (unsigned long)_orig.nraddr; \
1533 _argvec[1] = (unsigned long)(arg1); \
1534 _argvec[2] = (unsigned long)(arg2); \
1535 _argvec[3] = (unsigned long)(arg3); \
1536 _argvec[4] = (unsigned long)(arg4); \
1537 _argvec[5] = (unsigned long)(arg5); \
1538 _argvec[6] = (unsigned long)(arg6); \
1539 _argvec[7] = (unsigned long)(arg7); \
1540 _argvec[8] = (unsigned long)(arg8); \
1541 _argvec[9] = (unsigned long)(arg9); \
1542 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001543 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001544 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001545 "pushq 72(%%rax)\n\t" \
1546 "pushq 64(%%rax)\n\t" \
1547 "pushq 56(%%rax)\n\t" \
1548 "movq 48(%%rax), %%r9\n\t" \
1549 "movq 40(%%rax), %%r8\n\t" \
1550 "movq 32(%%rax), %%rcx\n\t" \
1551 "movq 24(%%rax), %%rdx\n\t" \
1552 "movq 16(%%rax), %%rsi\n\t" \
1553 "movq 8(%%rax), %%rdi\n\t" \
1554 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1555 VALGRIND_CALL_NOREDIR_RAX \
1556 "addq $24, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001557 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001558 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001559 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001560 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1561 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001562 ); \
1563 lval = (__typeof__(lval)) _res; \
1564 } while (0)
1565
1566#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1567 arg7,arg8,arg9,arg10) \
1568 do { \
1569 volatile OrigFn _orig = (orig); \
1570 volatile unsigned long _argvec[11]; \
1571 volatile unsigned long _res; \
1572 _argvec[0] = (unsigned long)_orig.nraddr; \
1573 _argvec[1] = (unsigned long)(arg1); \
1574 _argvec[2] = (unsigned long)(arg2); \
1575 _argvec[3] = (unsigned long)(arg3); \
1576 _argvec[4] = (unsigned long)(arg4); \
1577 _argvec[5] = (unsigned long)(arg5); \
1578 _argvec[6] = (unsigned long)(arg6); \
1579 _argvec[7] = (unsigned long)(arg7); \
1580 _argvec[8] = (unsigned long)(arg8); \
1581 _argvec[9] = (unsigned long)(arg9); \
1582 _argvec[10] = (unsigned long)(arg10); \
1583 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001584 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001585 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001586 "pushq 80(%%rax)\n\t" \
1587 "pushq 72(%%rax)\n\t" \
1588 "pushq 64(%%rax)\n\t" \
1589 "pushq 56(%%rax)\n\t" \
1590 "movq 48(%%rax), %%r9\n\t" \
1591 "movq 40(%%rax), %%r8\n\t" \
1592 "movq 32(%%rax), %%rcx\n\t" \
1593 "movq 24(%%rax), %%rdx\n\t" \
1594 "movq 16(%%rax), %%rsi\n\t" \
1595 "movq 8(%%rax), %%rdi\n\t" \
1596 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1597 VALGRIND_CALL_NOREDIR_RAX \
1598 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001599 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001600 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001601 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001602 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1603 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001604 ); \
1605 lval = (__typeof__(lval)) _res; \
1606 } while (0)
1607
1608#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1609 arg7,arg8,arg9,arg10,arg11) \
1610 do { \
1611 volatile OrigFn _orig = (orig); \
1612 volatile unsigned long _argvec[12]; \
1613 volatile unsigned long _res; \
1614 _argvec[0] = (unsigned long)_orig.nraddr; \
1615 _argvec[1] = (unsigned long)(arg1); \
1616 _argvec[2] = (unsigned long)(arg2); \
1617 _argvec[3] = (unsigned long)(arg3); \
1618 _argvec[4] = (unsigned long)(arg4); \
1619 _argvec[5] = (unsigned long)(arg5); \
1620 _argvec[6] = (unsigned long)(arg6); \
1621 _argvec[7] = (unsigned long)(arg7); \
1622 _argvec[8] = (unsigned long)(arg8); \
1623 _argvec[9] = (unsigned long)(arg9); \
1624 _argvec[10] = (unsigned long)(arg10); \
1625 _argvec[11] = (unsigned long)(arg11); \
1626 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001627 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001628 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001629 "pushq 88(%%rax)\n\t" \
1630 "pushq 80(%%rax)\n\t" \
1631 "pushq 72(%%rax)\n\t" \
1632 "pushq 64(%%rax)\n\t" \
1633 "pushq 56(%%rax)\n\t" \
1634 "movq 48(%%rax), %%r9\n\t" \
1635 "movq 40(%%rax), %%r8\n\t" \
1636 "movq 32(%%rax), %%rcx\n\t" \
1637 "movq 24(%%rax), %%rdx\n\t" \
1638 "movq 16(%%rax), %%rsi\n\t" \
1639 "movq 8(%%rax), %%rdi\n\t" \
1640 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1641 VALGRIND_CALL_NOREDIR_RAX \
1642 "addq $40, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001643 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001644 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001645 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001646 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1647 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001648 ); \
1649 lval = (__typeof__(lval)) _res; \
1650 } while (0)
1651
1652#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1653 arg7,arg8,arg9,arg10,arg11,arg12) \
1654 do { \
1655 volatile OrigFn _orig = (orig); \
1656 volatile unsigned long _argvec[13]; \
1657 volatile unsigned long _res; \
1658 _argvec[0] = (unsigned long)_orig.nraddr; \
1659 _argvec[1] = (unsigned long)(arg1); \
1660 _argvec[2] = (unsigned long)(arg2); \
1661 _argvec[3] = (unsigned long)(arg3); \
1662 _argvec[4] = (unsigned long)(arg4); \
1663 _argvec[5] = (unsigned long)(arg5); \
1664 _argvec[6] = (unsigned long)(arg6); \
1665 _argvec[7] = (unsigned long)(arg7); \
1666 _argvec[8] = (unsigned long)(arg8); \
1667 _argvec[9] = (unsigned long)(arg9); \
1668 _argvec[10] = (unsigned long)(arg10); \
1669 _argvec[11] = (unsigned long)(arg11); \
1670 _argvec[12] = (unsigned long)(arg12); \
1671 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001672 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001673 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001674 "pushq 96(%%rax)\n\t" \
1675 "pushq 88(%%rax)\n\t" \
1676 "pushq 80(%%rax)\n\t" \
1677 "pushq 72(%%rax)\n\t" \
1678 "pushq 64(%%rax)\n\t" \
1679 "pushq 56(%%rax)\n\t" \
1680 "movq 48(%%rax), %%r9\n\t" \
1681 "movq 40(%%rax), %%r8\n\t" \
1682 "movq 32(%%rax), %%rcx\n\t" \
1683 "movq 24(%%rax), %%rdx\n\t" \
1684 "movq 16(%%rax), %%rsi\n\t" \
1685 "movq 8(%%rax), %%rdi\n\t" \
1686 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1687 VALGRIND_CALL_NOREDIR_RAX \
1688 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001689 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001690 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001691 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001692 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1693 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001694 ); \
1695 lval = (__typeof__(lval)) _res; \
1696 } while (0)
1697
njnf76d27a2009-05-28 01:53:07 +00001698#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001699
sewardjf5c1a7f2006-10-17 01:32:48 +00001700/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001701
sewardjf5c1a7f2006-10-17 01:32:48 +00001702#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001703
sewardjead61df2006-03-12 13:39:15 +00001704/* This is useful for finding out about the on-stack stuff:
1705
1706 extern int f9 ( int,int,int,int,int,int,int,int,int );
1707 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1708 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1709 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1710
1711 int g9 ( void ) {
1712 return f9(11,22,33,44,55,66,77,88,99);
1713 }
1714 int g10 ( void ) {
1715 return f10(11,22,33,44,55,66,77,88,99,110);
1716 }
1717 int g11 ( void ) {
1718 return f11(11,22,33,44,55,66,77,88,99,110,121);
1719 }
1720 int g12 ( void ) {
1721 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1722 }
1723*/
1724
sewardj0ec07f32006-01-12 12:32:32 +00001725/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1726
1727/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001728#define __CALLER_SAVED_REGS \
1729 "lr", "ctr", "xer", \
1730 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1731 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1732 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001733
sewardjead61df2006-03-12 13:39:15 +00001734/* These CALL_FN_ macros assume that on ppc32-linux,
1735 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001736
sewardj38de0992006-01-20 16:46:34 +00001737#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001738 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001739 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001740 volatile unsigned long _argvec[1]; \
1741 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001742 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001743 __asm__ volatile( \
1744 "mr 11,%1\n\t" \
1745 "lwz 11,0(11)\n\t" /* target->r11 */ \
1746 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1747 "mr %0,3" \
1748 : /*out*/ "=r" (_res) \
1749 : /*in*/ "r" (&_argvec[0]) \
1750 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1751 ); \
1752 lval = (__typeof__(lval)) _res; \
1753 } while (0)
1754
sewardj38de0992006-01-20 16:46:34 +00001755#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001756 do { \
sewardj38de0992006-01-20 16:46:34 +00001757 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001758 volatile unsigned long _argvec[2]; \
1759 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001760 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001761 _argvec[1] = (unsigned long)arg1; \
1762 __asm__ volatile( \
1763 "mr 11,%1\n\t" \
1764 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1765 "lwz 11,0(11)\n\t" /* target->r11 */ \
1766 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1767 "mr %0,3" \
1768 : /*out*/ "=r" (_res) \
1769 : /*in*/ "r" (&_argvec[0]) \
1770 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1771 ); \
1772 lval = (__typeof__(lval)) _res; \
1773 } while (0)
1774
sewardj38de0992006-01-20 16:46:34 +00001775#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001776 do { \
sewardj38de0992006-01-20 16:46:34 +00001777 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001778 volatile unsigned long _argvec[3]; \
1779 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001780 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001781 _argvec[1] = (unsigned long)arg1; \
1782 _argvec[2] = (unsigned long)arg2; \
1783 __asm__ volatile( \
1784 "mr 11,%1\n\t" \
1785 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1786 "lwz 4,8(11)\n\t" \
1787 "lwz 11,0(11)\n\t" /* target->r11 */ \
1788 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1789 "mr %0,3" \
1790 : /*out*/ "=r" (_res) \
1791 : /*in*/ "r" (&_argvec[0]) \
1792 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1793 ); \
1794 lval = (__typeof__(lval)) _res; \
1795 } while (0)
1796
sewardjead61df2006-03-12 13:39:15 +00001797#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1798 do { \
1799 volatile OrigFn _orig = (orig); \
1800 volatile unsigned long _argvec[4]; \
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 __asm__ volatile( \
1807 "mr 11,%1\n\t" \
1808 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1809 "lwz 4,8(11)\n\t" \
1810 "lwz 5,12(11)\n\t" \
1811 "lwz 11,0(11)\n\t" /* target->r11 */ \
1812 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1813 "mr %0,3" \
1814 : /*out*/ "=r" (_res) \
1815 : /*in*/ "r" (&_argvec[0]) \
1816 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1817 ); \
1818 lval = (__typeof__(lval)) _res; \
1819 } while (0)
1820
1821#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1822 do { \
1823 volatile OrigFn _orig = (orig); \
1824 volatile unsigned long _argvec[5]; \
1825 volatile unsigned long _res; \
1826 _argvec[0] = (unsigned long)_orig.nraddr; \
1827 _argvec[1] = (unsigned long)arg1; \
1828 _argvec[2] = (unsigned long)arg2; \
1829 _argvec[3] = (unsigned long)arg3; \
1830 _argvec[4] = (unsigned long)arg4; \
1831 __asm__ volatile( \
1832 "mr 11,%1\n\t" \
1833 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1834 "lwz 4,8(11)\n\t" \
1835 "lwz 5,12(11)\n\t" \
1836 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1837 "lwz 11,0(11)\n\t" /* target->r11 */ \
1838 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1839 "mr %0,3" \
1840 : /*out*/ "=r" (_res) \
1841 : /*in*/ "r" (&_argvec[0]) \
1842 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1843 ); \
1844 lval = (__typeof__(lval)) _res; \
1845 } while (0)
1846
1847#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1848 do { \
1849 volatile OrigFn _orig = (orig); \
1850 volatile unsigned long _argvec[6]; \
1851 volatile unsigned long _res; \
1852 _argvec[0] = (unsigned long)_orig.nraddr; \
1853 _argvec[1] = (unsigned long)arg1; \
1854 _argvec[2] = (unsigned long)arg2; \
1855 _argvec[3] = (unsigned long)arg3; \
1856 _argvec[4] = (unsigned long)arg4; \
1857 _argvec[5] = (unsigned long)arg5; \
1858 __asm__ volatile( \
1859 "mr 11,%1\n\t" \
1860 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1861 "lwz 4,8(11)\n\t" \
1862 "lwz 5,12(11)\n\t" \
1863 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1864 "lwz 7,20(11)\n\t" \
1865 "lwz 11,0(11)\n\t" /* target->r11 */ \
1866 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1867 "mr %0,3" \
1868 : /*out*/ "=r" (_res) \
1869 : /*in*/ "r" (&_argvec[0]) \
1870 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1871 ); \
1872 lval = (__typeof__(lval)) _res; \
1873 } while (0)
1874
1875#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1876 do { \
1877 volatile OrigFn _orig = (orig); \
1878 volatile unsigned long _argvec[7]; \
1879 volatile unsigned long _res; \
1880 _argvec[0] = (unsigned long)_orig.nraddr; \
1881 _argvec[1] = (unsigned long)arg1; \
1882 _argvec[2] = (unsigned long)arg2; \
1883 _argvec[3] = (unsigned long)arg3; \
1884 _argvec[4] = (unsigned long)arg4; \
1885 _argvec[5] = (unsigned long)arg5; \
1886 _argvec[6] = (unsigned long)arg6; \
1887 __asm__ volatile( \
1888 "mr 11,%1\n\t" \
1889 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1890 "lwz 4,8(11)\n\t" \
1891 "lwz 5,12(11)\n\t" \
1892 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1893 "lwz 7,20(11)\n\t" \
1894 "lwz 8,24(11)\n\t" \
1895 "lwz 11,0(11)\n\t" /* target->r11 */ \
1896 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1897 "mr %0,3" \
1898 : /*out*/ "=r" (_res) \
1899 : /*in*/ "r" (&_argvec[0]) \
1900 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1901 ); \
1902 lval = (__typeof__(lval)) _res; \
1903 } while (0)
1904
1905#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1906 arg7) \
1907 do { \
1908 volatile OrigFn _orig = (orig); \
1909 volatile unsigned long _argvec[8]; \
1910 volatile unsigned long _res; \
1911 _argvec[0] = (unsigned long)_orig.nraddr; \
1912 _argvec[1] = (unsigned long)arg1; \
1913 _argvec[2] = (unsigned long)arg2; \
1914 _argvec[3] = (unsigned long)arg3; \
1915 _argvec[4] = (unsigned long)arg4; \
1916 _argvec[5] = (unsigned long)arg5; \
1917 _argvec[6] = (unsigned long)arg6; \
1918 _argvec[7] = (unsigned long)arg7; \
1919 __asm__ volatile( \
1920 "mr 11,%1\n\t" \
1921 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1922 "lwz 4,8(11)\n\t" \
1923 "lwz 5,12(11)\n\t" \
1924 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1925 "lwz 7,20(11)\n\t" \
1926 "lwz 8,24(11)\n\t" \
1927 "lwz 9,28(11)\n\t" \
1928 "lwz 11,0(11)\n\t" /* target->r11 */ \
1929 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1930 "mr %0,3" \
1931 : /*out*/ "=r" (_res) \
1932 : /*in*/ "r" (&_argvec[0]) \
1933 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1934 ); \
1935 lval = (__typeof__(lval)) _res; \
1936 } while (0)
1937
1938#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1939 arg7,arg8) \
1940 do { \
1941 volatile OrigFn _orig = (orig); \
1942 volatile unsigned long _argvec[9]; \
1943 volatile unsigned long _res; \
1944 _argvec[0] = (unsigned long)_orig.nraddr; \
1945 _argvec[1] = (unsigned long)arg1; \
1946 _argvec[2] = (unsigned long)arg2; \
1947 _argvec[3] = (unsigned long)arg3; \
1948 _argvec[4] = (unsigned long)arg4; \
1949 _argvec[5] = (unsigned long)arg5; \
1950 _argvec[6] = (unsigned long)arg6; \
1951 _argvec[7] = (unsigned long)arg7; \
1952 _argvec[8] = (unsigned long)arg8; \
1953 __asm__ volatile( \
1954 "mr 11,%1\n\t" \
1955 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1956 "lwz 4,8(11)\n\t" \
1957 "lwz 5,12(11)\n\t" \
1958 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1959 "lwz 7,20(11)\n\t" \
1960 "lwz 8,24(11)\n\t" \
1961 "lwz 9,28(11)\n\t" \
1962 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1963 "lwz 11,0(11)\n\t" /* target->r11 */ \
1964 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1965 "mr %0,3" \
1966 : /*out*/ "=r" (_res) \
1967 : /*in*/ "r" (&_argvec[0]) \
1968 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1969 ); \
1970 lval = (__typeof__(lval)) _res; \
1971 } while (0)
1972
1973#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1974 arg7,arg8,arg9) \
1975 do { \
1976 volatile OrigFn _orig = (orig); \
1977 volatile unsigned long _argvec[10]; \
1978 volatile unsigned long _res; \
1979 _argvec[0] = (unsigned long)_orig.nraddr; \
1980 _argvec[1] = (unsigned long)arg1; \
1981 _argvec[2] = (unsigned long)arg2; \
1982 _argvec[3] = (unsigned long)arg3; \
1983 _argvec[4] = (unsigned long)arg4; \
1984 _argvec[5] = (unsigned long)arg5; \
1985 _argvec[6] = (unsigned long)arg6; \
1986 _argvec[7] = (unsigned long)arg7; \
1987 _argvec[8] = (unsigned long)arg8; \
1988 _argvec[9] = (unsigned long)arg9; \
1989 __asm__ volatile( \
1990 "mr 11,%1\n\t" \
1991 "addi 1,1,-16\n\t" \
1992 /* arg9 */ \
1993 "lwz 3,36(11)\n\t" \
1994 "stw 3,8(1)\n\t" \
1995 /* args1-8 */ \
1996 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1997 "lwz 4,8(11)\n\t" \
1998 "lwz 5,12(11)\n\t" \
1999 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2000 "lwz 7,20(11)\n\t" \
2001 "lwz 8,24(11)\n\t" \
2002 "lwz 9,28(11)\n\t" \
2003 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2004 "lwz 11,0(11)\n\t" /* target->r11 */ \
2005 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2006 "addi 1,1,16\n\t" \
2007 "mr %0,3" \
2008 : /*out*/ "=r" (_res) \
2009 : /*in*/ "r" (&_argvec[0]) \
2010 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2011 ); \
2012 lval = (__typeof__(lval)) _res; \
2013 } while (0)
2014
2015#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2016 arg7,arg8,arg9,arg10) \
2017 do { \
2018 volatile OrigFn _orig = (orig); \
2019 volatile unsigned long _argvec[11]; \
2020 volatile unsigned long _res; \
2021 _argvec[0] = (unsigned long)_orig.nraddr; \
2022 _argvec[1] = (unsigned long)arg1; \
2023 _argvec[2] = (unsigned long)arg2; \
2024 _argvec[3] = (unsigned long)arg3; \
2025 _argvec[4] = (unsigned long)arg4; \
2026 _argvec[5] = (unsigned long)arg5; \
2027 _argvec[6] = (unsigned long)arg6; \
2028 _argvec[7] = (unsigned long)arg7; \
2029 _argvec[8] = (unsigned long)arg8; \
2030 _argvec[9] = (unsigned long)arg9; \
2031 _argvec[10] = (unsigned long)arg10; \
2032 __asm__ volatile( \
2033 "mr 11,%1\n\t" \
2034 "addi 1,1,-16\n\t" \
2035 /* arg10 */ \
2036 "lwz 3,40(11)\n\t" \
2037 "stw 3,12(1)\n\t" \
2038 /* arg9 */ \
2039 "lwz 3,36(11)\n\t" \
2040 "stw 3,8(1)\n\t" \
2041 /* args1-8 */ \
2042 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2043 "lwz 4,8(11)\n\t" \
2044 "lwz 5,12(11)\n\t" \
2045 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2046 "lwz 7,20(11)\n\t" \
2047 "lwz 8,24(11)\n\t" \
2048 "lwz 9,28(11)\n\t" \
2049 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2050 "lwz 11,0(11)\n\t" /* target->r11 */ \
2051 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2052 "addi 1,1,16\n\t" \
2053 "mr %0,3" \
2054 : /*out*/ "=r" (_res) \
2055 : /*in*/ "r" (&_argvec[0]) \
2056 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2057 ); \
2058 lval = (__typeof__(lval)) _res; \
2059 } while (0)
2060
2061#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2062 arg7,arg8,arg9,arg10,arg11) \
2063 do { \
2064 volatile OrigFn _orig = (orig); \
2065 volatile unsigned long _argvec[12]; \
2066 volatile unsigned long _res; \
2067 _argvec[0] = (unsigned long)_orig.nraddr; \
2068 _argvec[1] = (unsigned long)arg1; \
2069 _argvec[2] = (unsigned long)arg2; \
2070 _argvec[3] = (unsigned long)arg3; \
2071 _argvec[4] = (unsigned long)arg4; \
2072 _argvec[5] = (unsigned long)arg5; \
2073 _argvec[6] = (unsigned long)arg6; \
2074 _argvec[7] = (unsigned long)arg7; \
2075 _argvec[8] = (unsigned long)arg8; \
2076 _argvec[9] = (unsigned long)arg9; \
2077 _argvec[10] = (unsigned long)arg10; \
2078 _argvec[11] = (unsigned long)arg11; \
2079 __asm__ volatile( \
2080 "mr 11,%1\n\t" \
2081 "addi 1,1,-32\n\t" \
2082 /* arg11 */ \
2083 "lwz 3,44(11)\n\t" \
2084 "stw 3,16(1)\n\t" \
2085 /* arg10 */ \
2086 "lwz 3,40(11)\n\t" \
2087 "stw 3,12(1)\n\t" \
2088 /* arg9 */ \
2089 "lwz 3,36(11)\n\t" \
2090 "stw 3,8(1)\n\t" \
2091 /* args1-8 */ \
2092 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2093 "lwz 4,8(11)\n\t" \
2094 "lwz 5,12(11)\n\t" \
2095 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2096 "lwz 7,20(11)\n\t" \
2097 "lwz 8,24(11)\n\t" \
2098 "lwz 9,28(11)\n\t" \
2099 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2100 "lwz 11,0(11)\n\t" /* target->r11 */ \
2101 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2102 "addi 1,1,32\n\t" \
2103 "mr %0,3" \
2104 : /*out*/ "=r" (_res) \
2105 : /*in*/ "r" (&_argvec[0]) \
2106 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2107 ); \
2108 lval = (__typeof__(lval)) _res; \
2109 } while (0)
2110
2111#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2112 arg7,arg8,arg9,arg10,arg11,arg12) \
2113 do { \
2114 volatile OrigFn _orig = (orig); \
2115 volatile unsigned long _argvec[13]; \
2116 volatile unsigned long _res; \
2117 _argvec[0] = (unsigned long)_orig.nraddr; \
2118 _argvec[1] = (unsigned long)arg1; \
2119 _argvec[2] = (unsigned long)arg2; \
2120 _argvec[3] = (unsigned long)arg3; \
2121 _argvec[4] = (unsigned long)arg4; \
2122 _argvec[5] = (unsigned long)arg5; \
2123 _argvec[6] = (unsigned long)arg6; \
2124 _argvec[7] = (unsigned long)arg7; \
2125 _argvec[8] = (unsigned long)arg8; \
2126 _argvec[9] = (unsigned long)arg9; \
2127 _argvec[10] = (unsigned long)arg10; \
2128 _argvec[11] = (unsigned long)arg11; \
2129 _argvec[12] = (unsigned long)arg12; \
2130 __asm__ volatile( \
2131 "mr 11,%1\n\t" \
2132 "addi 1,1,-32\n\t" \
2133 /* arg12 */ \
2134 "lwz 3,48(11)\n\t" \
2135 "stw 3,20(1)\n\t" \
2136 /* arg11 */ \
2137 "lwz 3,44(11)\n\t" \
2138 "stw 3,16(1)\n\t" \
2139 /* arg10 */ \
2140 "lwz 3,40(11)\n\t" \
2141 "stw 3,12(1)\n\t" \
2142 /* arg9 */ \
2143 "lwz 3,36(11)\n\t" \
2144 "stw 3,8(1)\n\t" \
2145 /* args1-8 */ \
2146 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2147 "lwz 4,8(11)\n\t" \
2148 "lwz 5,12(11)\n\t" \
2149 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2150 "lwz 7,20(11)\n\t" \
2151 "lwz 8,24(11)\n\t" \
2152 "lwz 9,28(11)\n\t" \
2153 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2154 "lwz 11,0(11)\n\t" /* target->r11 */ \
2155 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2156 "addi 1,1,32\n\t" \
2157 "mr %0,3" \
2158 : /*out*/ "=r" (_res) \
2159 : /*in*/ "r" (&_argvec[0]) \
2160 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2161 ); \
2162 lval = (__typeof__(lval)) _res; \
2163 } while (0)
2164
sewardjf5c1a7f2006-10-17 01:32:48 +00002165#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002166
sewardjf5c1a7f2006-10-17 01:32:48 +00002167/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002168
sewardjf5c1a7f2006-10-17 01:32:48 +00002169#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002170
2171/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2172
2173/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002174#define __CALLER_SAVED_REGS \
2175 "lr", "ctr", "xer", \
2176 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2177 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2178 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002179
2180/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2181 long) == 8. */
2182
sewardjd68ac3e2006-01-20 14:31:57 +00002183#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002184 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002185 volatile OrigFn _orig = (orig); \
2186 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002187 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002188 /* _argvec[0] holds current r2 across the call */ \
2189 _argvec[1] = (unsigned long)_orig.r2; \
2190 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002191 __asm__ volatile( \
2192 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002193 "std 2,-16(11)\n\t" /* save tocptr */ \
2194 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2195 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002196 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2197 "mr 11,%1\n\t" \
2198 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002199 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002200 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002201 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002202 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2203 ); \
2204 lval = (__typeof__(lval)) _res; \
2205 } while (0)
2206
sewardjd68ac3e2006-01-20 14:31:57 +00002207#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002208 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002209 volatile OrigFn _orig = (orig); \
2210 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002211 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002212 /* _argvec[0] holds current r2 across the call */ \
2213 _argvec[1] = (unsigned long)_orig.r2; \
2214 _argvec[2] = (unsigned long)_orig.nraddr; \
2215 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002216 __asm__ volatile( \
2217 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002218 "std 2,-16(11)\n\t" /* save tocptr */ \
2219 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2220 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2221 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002222 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2223 "mr 11,%1\n\t" \
2224 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002225 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002226 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002227 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002228 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2229 ); \
2230 lval = (__typeof__(lval)) _res; \
2231 } while (0)
2232
sewardjd68ac3e2006-01-20 14:31:57 +00002233#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002234 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002235 volatile OrigFn _orig = (orig); \
2236 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002237 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002238 /* _argvec[0] holds current r2 across the call */ \
2239 _argvec[1] = (unsigned long)_orig.r2; \
2240 _argvec[2] = (unsigned long)_orig.nraddr; \
2241 _argvec[2+1] = (unsigned long)arg1; \
2242 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002243 __asm__ volatile( \
2244 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002245 "std 2,-16(11)\n\t" /* save tocptr */ \
2246 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2247 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002248 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002249 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002250 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2251 "mr 11,%1\n\t" \
2252 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002253 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002254 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002255 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002256 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2257 ); \
2258 lval = (__typeof__(lval)) _res; \
2259 } while (0)
2260
sewardjcd636392006-03-12 16:48:14 +00002261#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2262 do { \
2263 volatile OrigFn _orig = (orig); \
2264 volatile unsigned long _argvec[3+3]; \
2265 volatile unsigned long _res; \
2266 /* _argvec[0] holds current r2 across the call */ \
2267 _argvec[1] = (unsigned long)_orig.r2; \
2268 _argvec[2] = (unsigned long)_orig.nraddr; \
2269 _argvec[2+1] = (unsigned long)arg1; \
2270 _argvec[2+2] = (unsigned long)arg2; \
2271 _argvec[2+3] = (unsigned long)arg3; \
2272 __asm__ volatile( \
2273 "mr 11,%1\n\t" \
2274 "std 2,-16(11)\n\t" /* save tocptr */ \
2275 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2276 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2277 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2278 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2279 "ld 11, 0(11)\n\t" /* target->r11 */ \
2280 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2281 "mr 11,%1\n\t" \
2282 "mr %0,3\n\t" \
2283 "ld 2,-16(11)" /* restore tocptr */ \
2284 : /*out*/ "=r" (_res) \
2285 : /*in*/ "r" (&_argvec[2]) \
2286 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2287 ); \
2288 lval = (__typeof__(lval)) _res; \
2289 } while (0)
2290
2291#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2292 do { \
2293 volatile OrigFn _orig = (orig); \
2294 volatile unsigned long _argvec[3+4]; \
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 __asm__ volatile( \
2304 "mr 11,%1\n\t" \
2305 "std 2,-16(11)\n\t" /* save tocptr */ \
2306 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2307 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2308 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2309 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2310 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2311 "ld 11, 0(11)\n\t" /* target->r11 */ \
2312 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2313 "mr 11,%1\n\t" \
2314 "mr %0,3\n\t" \
2315 "ld 2,-16(11)" /* restore tocptr */ \
2316 : /*out*/ "=r" (_res) \
2317 : /*in*/ "r" (&_argvec[2]) \
2318 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2319 ); \
2320 lval = (__typeof__(lval)) _res; \
2321 } while (0)
2322
2323#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2324 do { \
2325 volatile OrigFn _orig = (orig); \
2326 volatile unsigned long _argvec[3+5]; \
2327 volatile unsigned long _res; \
2328 /* _argvec[0] holds current r2 across the call */ \
2329 _argvec[1] = (unsigned long)_orig.r2; \
2330 _argvec[2] = (unsigned long)_orig.nraddr; \
2331 _argvec[2+1] = (unsigned long)arg1; \
2332 _argvec[2+2] = (unsigned long)arg2; \
2333 _argvec[2+3] = (unsigned long)arg3; \
2334 _argvec[2+4] = (unsigned long)arg4; \
2335 _argvec[2+5] = (unsigned long)arg5; \
2336 __asm__ volatile( \
2337 "mr 11,%1\n\t" \
2338 "std 2,-16(11)\n\t" /* save tocptr */ \
2339 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2340 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2341 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2342 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2343 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2344 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2345 "ld 11, 0(11)\n\t" /* target->r11 */ \
2346 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2347 "mr 11,%1\n\t" \
2348 "mr %0,3\n\t" \
2349 "ld 2,-16(11)" /* restore tocptr */ \
2350 : /*out*/ "=r" (_res) \
2351 : /*in*/ "r" (&_argvec[2]) \
2352 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2353 ); \
2354 lval = (__typeof__(lval)) _res; \
2355 } while (0)
2356
2357#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2358 do { \
2359 volatile OrigFn _orig = (orig); \
2360 volatile unsigned long _argvec[3+6]; \
2361 volatile unsigned long _res; \
2362 /* _argvec[0] holds current r2 across the call */ \
2363 _argvec[1] = (unsigned long)_orig.r2; \
2364 _argvec[2] = (unsigned long)_orig.nraddr; \
2365 _argvec[2+1] = (unsigned long)arg1; \
2366 _argvec[2+2] = (unsigned long)arg2; \
2367 _argvec[2+3] = (unsigned long)arg3; \
2368 _argvec[2+4] = (unsigned long)arg4; \
2369 _argvec[2+5] = (unsigned long)arg5; \
2370 _argvec[2+6] = (unsigned long)arg6; \
2371 __asm__ volatile( \
2372 "mr 11,%1\n\t" \
2373 "std 2,-16(11)\n\t" /* save tocptr */ \
2374 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2375 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2376 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2377 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2378 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2379 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2380 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2381 "ld 11, 0(11)\n\t" /* target->r11 */ \
2382 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2383 "mr 11,%1\n\t" \
2384 "mr %0,3\n\t" \
2385 "ld 2,-16(11)" /* restore tocptr */ \
2386 : /*out*/ "=r" (_res) \
2387 : /*in*/ "r" (&_argvec[2]) \
2388 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2389 ); \
2390 lval = (__typeof__(lval)) _res; \
2391 } while (0)
2392
2393#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2394 arg7) \
2395 do { \
2396 volatile OrigFn _orig = (orig); \
2397 volatile unsigned long _argvec[3+7]; \
2398 volatile unsigned long _res; \
2399 /* _argvec[0] holds current r2 across the call */ \
2400 _argvec[1] = (unsigned long)_orig.r2; \
2401 _argvec[2] = (unsigned long)_orig.nraddr; \
2402 _argvec[2+1] = (unsigned long)arg1; \
2403 _argvec[2+2] = (unsigned long)arg2; \
2404 _argvec[2+3] = (unsigned long)arg3; \
2405 _argvec[2+4] = (unsigned long)arg4; \
2406 _argvec[2+5] = (unsigned long)arg5; \
2407 _argvec[2+6] = (unsigned long)arg6; \
2408 _argvec[2+7] = (unsigned long)arg7; \
2409 __asm__ volatile( \
2410 "mr 11,%1\n\t" \
2411 "std 2,-16(11)\n\t" /* save tocptr */ \
2412 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2413 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2414 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2415 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2416 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2417 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2418 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2419 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2420 "ld 11, 0(11)\n\t" /* target->r11 */ \
2421 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2422 "mr 11,%1\n\t" \
2423 "mr %0,3\n\t" \
2424 "ld 2,-16(11)" /* restore tocptr */ \
2425 : /*out*/ "=r" (_res) \
2426 : /*in*/ "r" (&_argvec[2]) \
2427 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2428 ); \
2429 lval = (__typeof__(lval)) _res; \
2430 } while (0)
2431
2432#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2433 arg7,arg8) \
2434 do { \
2435 volatile OrigFn _orig = (orig); \
2436 volatile unsigned long _argvec[3+8]; \
2437 volatile unsigned long _res; \
2438 /* _argvec[0] holds current r2 across the call */ \
2439 _argvec[1] = (unsigned long)_orig.r2; \
2440 _argvec[2] = (unsigned long)_orig.nraddr; \
2441 _argvec[2+1] = (unsigned long)arg1; \
2442 _argvec[2+2] = (unsigned long)arg2; \
2443 _argvec[2+3] = (unsigned long)arg3; \
2444 _argvec[2+4] = (unsigned long)arg4; \
2445 _argvec[2+5] = (unsigned long)arg5; \
2446 _argvec[2+6] = (unsigned long)arg6; \
2447 _argvec[2+7] = (unsigned long)arg7; \
2448 _argvec[2+8] = (unsigned long)arg8; \
2449 __asm__ volatile( \
2450 "mr 11,%1\n\t" \
2451 "std 2,-16(11)\n\t" /* save tocptr */ \
2452 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2453 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2454 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2455 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2456 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2457 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2458 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2459 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2460 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2461 "ld 11, 0(11)\n\t" /* target->r11 */ \
2462 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2463 "mr 11,%1\n\t" \
2464 "mr %0,3\n\t" \
2465 "ld 2,-16(11)" /* restore tocptr */ \
2466 : /*out*/ "=r" (_res) \
2467 : /*in*/ "r" (&_argvec[2]) \
2468 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2469 ); \
2470 lval = (__typeof__(lval)) _res; \
2471 } while (0)
2472
2473#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2474 arg7,arg8,arg9) \
2475 do { \
2476 volatile OrigFn _orig = (orig); \
2477 volatile unsigned long _argvec[3+9]; \
2478 volatile unsigned long _res; \
2479 /* _argvec[0] holds current r2 across the call */ \
2480 _argvec[1] = (unsigned long)_orig.r2; \
2481 _argvec[2] = (unsigned long)_orig.nraddr; \
2482 _argvec[2+1] = (unsigned long)arg1; \
2483 _argvec[2+2] = (unsigned long)arg2; \
2484 _argvec[2+3] = (unsigned long)arg3; \
2485 _argvec[2+4] = (unsigned long)arg4; \
2486 _argvec[2+5] = (unsigned long)arg5; \
2487 _argvec[2+6] = (unsigned long)arg6; \
2488 _argvec[2+7] = (unsigned long)arg7; \
2489 _argvec[2+8] = (unsigned long)arg8; \
2490 _argvec[2+9] = (unsigned long)arg9; \
2491 __asm__ volatile( \
2492 "mr 11,%1\n\t" \
2493 "std 2,-16(11)\n\t" /* save tocptr */ \
2494 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2495 "addi 1,1,-128\n\t" /* expand stack frame */ \
2496 /* arg9 */ \
2497 "ld 3,72(11)\n\t" \
2498 "std 3,112(1)\n\t" \
2499 /* args1-8 */ \
2500 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2501 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2502 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2503 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2504 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2505 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2506 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2507 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2508 "ld 11, 0(11)\n\t" /* target->r11 */ \
2509 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2510 "mr 11,%1\n\t" \
2511 "mr %0,3\n\t" \
2512 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2513 "addi 1,1,128" /* restore frame */ \
2514 : /*out*/ "=r" (_res) \
2515 : /*in*/ "r" (&_argvec[2]) \
2516 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2517 ); \
2518 lval = (__typeof__(lval)) _res; \
2519 } while (0)
2520
2521#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2522 arg7,arg8,arg9,arg10) \
2523 do { \
2524 volatile OrigFn _orig = (orig); \
2525 volatile unsigned long _argvec[3+10]; \
2526 volatile unsigned long _res; \
2527 /* _argvec[0] holds current r2 across the call */ \
2528 _argvec[1] = (unsigned long)_orig.r2; \
2529 _argvec[2] = (unsigned long)_orig.nraddr; \
2530 _argvec[2+1] = (unsigned long)arg1; \
2531 _argvec[2+2] = (unsigned long)arg2; \
2532 _argvec[2+3] = (unsigned long)arg3; \
2533 _argvec[2+4] = (unsigned long)arg4; \
2534 _argvec[2+5] = (unsigned long)arg5; \
2535 _argvec[2+6] = (unsigned long)arg6; \
2536 _argvec[2+7] = (unsigned long)arg7; \
2537 _argvec[2+8] = (unsigned long)arg8; \
2538 _argvec[2+9] = (unsigned long)arg9; \
2539 _argvec[2+10] = (unsigned long)arg10; \
2540 __asm__ volatile( \
2541 "mr 11,%1\n\t" \
2542 "std 2,-16(11)\n\t" /* save tocptr */ \
2543 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2544 "addi 1,1,-128\n\t" /* expand stack frame */ \
2545 /* arg10 */ \
2546 "ld 3,80(11)\n\t" \
2547 "std 3,120(1)\n\t" \
2548 /* arg9 */ \
2549 "ld 3,72(11)\n\t" \
2550 "std 3,112(1)\n\t" \
2551 /* args1-8 */ \
2552 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2553 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2554 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2555 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2556 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2557 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2558 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2559 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2560 "ld 11, 0(11)\n\t" /* target->r11 */ \
2561 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2562 "mr 11,%1\n\t" \
2563 "mr %0,3\n\t" \
2564 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2565 "addi 1,1,128" /* restore frame */ \
2566 : /*out*/ "=r" (_res) \
2567 : /*in*/ "r" (&_argvec[2]) \
2568 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2569 ); \
2570 lval = (__typeof__(lval)) _res; \
2571 } while (0)
2572
2573#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2574 arg7,arg8,arg9,arg10,arg11) \
2575 do { \
2576 volatile OrigFn _orig = (orig); \
2577 volatile unsigned long _argvec[3+11]; \
2578 volatile unsigned long _res; \
2579 /* _argvec[0] holds current r2 across the call */ \
2580 _argvec[1] = (unsigned long)_orig.r2; \
2581 _argvec[2] = (unsigned long)_orig.nraddr; \
2582 _argvec[2+1] = (unsigned long)arg1; \
2583 _argvec[2+2] = (unsigned long)arg2; \
2584 _argvec[2+3] = (unsigned long)arg3; \
2585 _argvec[2+4] = (unsigned long)arg4; \
2586 _argvec[2+5] = (unsigned long)arg5; \
2587 _argvec[2+6] = (unsigned long)arg6; \
2588 _argvec[2+7] = (unsigned long)arg7; \
2589 _argvec[2+8] = (unsigned long)arg8; \
2590 _argvec[2+9] = (unsigned long)arg9; \
2591 _argvec[2+10] = (unsigned long)arg10; \
2592 _argvec[2+11] = (unsigned long)arg11; \
2593 __asm__ volatile( \
2594 "mr 11,%1\n\t" \
2595 "std 2,-16(11)\n\t" /* save tocptr */ \
2596 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2597 "addi 1,1,-144\n\t" /* expand stack frame */ \
2598 /* arg11 */ \
2599 "ld 3,88(11)\n\t" \
2600 "std 3,128(1)\n\t" \
2601 /* arg10 */ \
2602 "ld 3,80(11)\n\t" \
2603 "std 3,120(1)\n\t" \
2604 /* arg9 */ \
2605 "ld 3,72(11)\n\t" \
2606 "std 3,112(1)\n\t" \
2607 /* args1-8 */ \
2608 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2609 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2610 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2611 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2612 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2613 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2614 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2615 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2616 "ld 11, 0(11)\n\t" /* target->r11 */ \
2617 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2618 "mr 11,%1\n\t" \
2619 "mr %0,3\n\t" \
2620 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2621 "addi 1,1,144" /* restore frame */ \
2622 : /*out*/ "=r" (_res) \
2623 : /*in*/ "r" (&_argvec[2]) \
2624 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2625 ); \
2626 lval = (__typeof__(lval)) _res; \
2627 } while (0)
2628
2629#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2630 arg7,arg8,arg9,arg10,arg11,arg12) \
2631 do { \
2632 volatile OrigFn _orig = (orig); \
2633 volatile unsigned long _argvec[3+12]; \
2634 volatile unsigned long _res; \
2635 /* _argvec[0] holds current r2 across the call */ \
2636 _argvec[1] = (unsigned long)_orig.r2; \
2637 _argvec[2] = (unsigned long)_orig.nraddr; \
2638 _argvec[2+1] = (unsigned long)arg1; \
2639 _argvec[2+2] = (unsigned long)arg2; \
2640 _argvec[2+3] = (unsigned long)arg3; \
2641 _argvec[2+4] = (unsigned long)arg4; \
2642 _argvec[2+5] = (unsigned long)arg5; \
2643 _argvec[2+6] = (unsigned long)arg6; \
2644 _argvec[2+7] = (unsigned long)arg7; \
2645 _argvec[2+8] = (unsigned long)arg8; \
2646 _argvec[2+9] = (unsigned long)arg9; \
2647 _argvec[2+10] = (unsigned long)arg10; \
2648 _argvec[2+11] = (unsigned long)arg11; \
2649 _argvec[2+12] = (unsigned long)arg12; \
2650 __asm__ volatile( \
2651 "mr 11,%1\n\t" \
2652 "std 2,-16(11)\n\t" /* save tocptr */ \
2653 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2654 "addi 1,1,-144\n\t" /* expand stack frame */ \
2655 /* arg12 */ \
2656 "ld 3,96(11)\n\t" \
2657 "std 3,136(1)\n\t" \
2658 /* arg11 */ \
2659 "ld 3,88(11)\n\t" \
2660 "std 3,128(1)\n\t" \
2661 /* arg10 */ \
2662 "ld 3,80(11)\n\t" \
2663 "std 3,120(1)\n\t" \
2664 /* arg9 */ \
2665 "ld 3,72(11)\n\t" \
2666 "std 3,112(1)\n\t" \
2667 /* args1-8 */ \
2668 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2669 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2670 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2671 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2672 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2673 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2674 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2675 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2676 "ld 11, 0(11)\n\t" /* target->r11 */ \
2677 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2678 "mr 11,%1\n\t" \
2679 "mr %0,3\n\t" \
2680 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2681 "addi 1,1,144" /* restore frame */ \
2682 : /*out*/ "=r" (_res) \
2683 : /*in*/ "r" (&_argvec[2]) \
2684 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2685 ); \
2686 lval = (__typeof__(lval)) _res; \
2687 } while (0)
2688
sewardjf5c1a7f2006-10-17 01:32:48 +00002689#endif /* PLAT_ppc64_linux */
2690
sewardj59570ff2010-01-01 11:59:33 +00002691/* ------------------------- arm-linux ------------------------- */
2692
2693#if defined(PLAT_arm_linux)
2694
2695/* These regs are trashed by the hidden call. */
2696#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2697
2698/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2699 long) == 4. */
2700
2701#define CALL_FN_W_v(lval, orig) \
2702 do { \
2703 volatile OrigFn _orig = (orig); \
2704 volatile unsigned long _argvec[1]; \
2705 volatile unsigned long _res; \
2706 _argvec[0] = (unsigned long)_orig.nraddr; \
2707 __asm__ volatile( \
2708 "ldr r4, [%1] \n\t" /* target->r4 */ \
2709 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2710 "mov %0, r0\n" \
2711 : /*out*/ "=r" (_res) \
2712 : /*in*/ "0" (&_argvec[0]) \
2713 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2714 ); \
2715 lval = (__typeof__(lval)) _res; \
2716 } while (0)
2717
2718#define CALL_FN_W_W(lval, orig, arg1) \
2719 do { \
2720 volatile OrigFn _orig = (orig); \
2721 volatile unsigned long _argvec[2]; \
2722 volatile unsigned long _res; \
2723 _argvec[0] = (unsigned long)_orig.nraddr; \
2724 _argvec[1] = (unsigned long)(arg1); \
2725 __asm__ volatile( \
2726 "ldr r0, [%1, #4] \n\t" \
2727 "ldr r4, [%1] \n\t" /* target->r4 */ \
2728 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2729 "mov %0, r0\n" \
2730 : /*out*/ "=r" (_res) \
2731 : /*in*/ "0" (&_argvec[0]) \
2732 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2733 ); \
2734 lval = (__typeof__(lval)) _res; \
2735 } while (0)
2736
2737#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2738 do { \
2739 volatile OrigFn _orig = (orig); \
2740 volatile unsigned long _argvec[3]; \
2741 volatile unsigned long _res; \
2742 _argvec[0] = (unsigned long)_orig.nraddr; \
2743 _argvec[1] = (unsigned long)(arg1); \
2744 _argvec[2] = (unsigned long)(arg2); \
2745 __asm__ volatile( \
2746 "ldr r0, [%1, #4] \n\t" \
2747 "ldr r1, [%1, #8] \n\t" \
2748 "ldr r4, [%1] \n\t" /* target->r4 */ \
2749 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2750 "mov %0, r0\n" \
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_WWW(lval, orig, arg1,arg2,arg3) \
2759 do { \
2760 volatile OrigFn _orig = (orig); \
2761 volatile unsigned long _argvec[4]; \
2762 volatile unsigned long _res; \
2763 _argvec[0] = (unsigned long)_orig.nraddr; \
2764 _argvec[1] = (unsigned long)(arg1); \
2765 _argvec[2] = (unsigned long)(arg2); \
2766 _argvec[3] = (unsigned long)(arg3); \
2767 __asm__ volatile( \
2768 "ldr r0, [%1, #4] \n\t" \
2769 "ldr r1, [%1, #8] \n\t" \
2770 "ldr r2, [%1, #12] \n\t" \
2771 "ldr r4, [%1] \n\t" /* target->r4 */ \
2772 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2773 "mov %0, r0\n" \
2774 : /*out*/ "=r" (_res) \
2775 : /*in*/ "0" (&_argvec[0]) \
2776 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2777 ); \
2778 lval = (__typeof__(lval)) _res; \
2779 } while (0)
2780
2781#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2782 do { \
2783 volatile OrigFn _orig = (orig); \
2784 volatile unsigned long _argvec[5]; \
2785 volatile unsigned long _res; \
2786 _argvec[0] = (unsigned long)_orig.nraddr; \
2787 _argvec[1] = (unsigned long)(arg1); \
2788 _argvec[2] = (unsigned long)(arg2); \
2789 _argvec[3] = (unsigned long)(arg3); \
2790 _argvec[4] = (unsigned long)(arg4); \
2791 __asm__ volatile( \
2792 "ldr r0, [%1, #4] \n\t" \
2793 "ldr r1, [%1, #8] \n\t" \
2794 "ldr r2, [%1, #12] \n\t" \
2795 "ldr r3, [%1, #16] \n\t" \
2796 "ldr r4, [%1] \n\t" /* target->r4 */ \
2797 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2798 "mov %0, r0" \
2799 : /*out*/ "=r" (_res) \
2800 : /*in*/ "0" (&_argvec[0]) \
2801 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2802 ); \
2803 lval = (__typeof__(lval)) _res; \
2804 } while (0)
2805
2806#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2807 do { \
2808 volatile OrigFn _orig = (orig); \
2809 volatile unsigned long _argvec[6]; \
2810 volatile unsigned long _res; \
2811 _argvec[0] = (unsigned long)_orig.nraddr; \
2812 _argvec[1] = (unsigned long)(arg1); \
2813 _argvec[2] = (unsigned long)(arg2); \
2814 _argvec[3] = (unsigned long)(arg3); \
2815 _argvec[4] = (unsigned long)(arg4); \
2816 _argvec[5] = (unsigned long)(arg5); \
2817 __asm__ volatile( \
2818 "ldr r0, [%1, #20] \n\t" \
2819 "push {r0} \n\t" \
2820 "ldr r0, [%1, #4] \n\t" \
2821 "ldr r1, [%1, #8] \n\t" \
2822 "ldr r2, [%1, #12] \n\t" \
2823 "ldr r3, [%1, #16] \n\t" \
2824 "ldr r4, [%1] \n\t" /* target->r4 */ \
2825 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2826 "add sp, sp, #4 \n\t" \
2827 "mov %0, r0" \
2828 : /*out*/ "=r" (_res) \
2829 : /*in*/ "0" (&_argvec[0]) \
2830 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2831 ); \
2832 lval = (__typeof__(lval)) _res; \
2833 } while (0)
2834
2835#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2836 do { \
2837 volatile OrigFn _orig = (orig); \
2838 volatile unsigned long _argvec[7]; \
2839 volatile unsigned long _res; \
2840 _argvec[0] = (unsigned long)_orig.nraddr; \
2841 _argvec[1] = (unsigned long)(arg1); \
2842 _argvec[2] = (unsigned long)(arg2); \
2843 _argvec[3] = (unsigned long)(arg3); \
2844 _argvec[4] = (unsigned long)(arg4); \
2845 _argvec[5] = (unsigned long)(arg5); \
2846 _argvec[6] = (unsigned long)(arg6); \
2847 __asm__ volatile( \
2848 "ldr r0, [%1, #20] \n\t" \
2849 "ldr r1, [%1, #24] \n\t" \
2850 "push {r0, r1} \n\t" \
2851 "ldr r0, [%1, #4] \n\t" \
2852 "ldr r1, [%1, #8] \n\t" \
2853 "ldr r2, [%1, #12] \n\t" \
2854 "ldr r3, [%1, #16] \n\t" \
2855 "ldr r4, [%1] \n\t" /* target->r4 */ \
2856 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2857 "add sp, sp, #8 \n\t" \
2858 "mov %0, r0" \
2859 : /*out*/ "=r" (_res) \
2860 : /*in*/ "0" (&_argvec[0]) \
2861 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2862 ); \
2863 lval = (__typeof__(lval)) _res; \
2864 } while (0)
2865
2866#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2867 arg7) \
2868 do { \
2869 volatile OrigFn _orig = (orig); \
2870 volatile unsigned long _argvec[8]; \
2871 volatile unsigned long _res; \
2872 _argvec[0] = (unsigned long)_orig.nraddr; \
2873 _argvec[1] = (unsigned long)(arg1); \
2874 _argvec[2] = (unsigned long)(arg2); \
2875 _argvec[3] = (unsigned long)(arg3); \
2876 _argvec[4] = (unsigned long)(arg4); \
2877 _argvec[5] = (unsigned long)(arg5); \
2878 _argvec[6] = (unsigned long)(arg6); \
2879 _argvec[7] = (unsigned long)(arg7); \
2880 __asm__ volatile( \
2881 "ldr r0, [%1, #20] \n\t" \
2882 "ldr r1, [%1, #24] \n\t" \
2883 "ldr r2, [%1, #28] \n\t" \
2884 "push {r0, r1, r2} \n\t" \
2885 "ldr r0, [%1, #4] \n\t" \
2886 "ldr r1, [%1, #8] \n\t" \
2887 "ldr r2, [%1, #12] \n\t" \
2888 "ldr r3, [%1, #16] \n\t" \
2889 "ldr r4, [%1] \n\t" /* target->r4 */ \
2890 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2891 "add sp, sp, #12 \n\t" \
2892 "mov %0, r0" \
2893 : /*out*/ "=r" (_res) \
2894 : /*in*/ "0" (&_argvec[0]) \
2895 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2896 ); \
2897 lval = (__typeof__(lval)) _res; \
2898 } while (0)
2899
2900#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2901 arg7,arg8) \
2902 do { \
2903 volatile OrigFn _orig = (orig); \
2904 volatile unsigned long _argvec[9]; \
2905 volatile unsigned long _res; \
2906 _argvec[0] = (unsigned long)_orig.nraddr; \
2907 _argvec[1] = (unsigned long)(arg1); \
2908 _argvec[2] = (unsigned long)(arg2); \
2909 _argvec[3] = (unsigned long)(arg3); \
2910 _argvec[4] = (unsigned long)(arg4); \
2911 _argvec[5] = (unsigned long)(arg5); \
2912 _argvec[6] = (unsigned long)(arg6); \
2913 _argvec[7] = (unsigned long)(arg7); \
2914 _argvec[8] = (unsigned long)(arg8); \
2915 __asm__ volatile( \
2916 "ldr r0, [%1, #20] \n\t" \
2917 "ldr r1, [%1, #24] \n\t" \
2918 "ldr r2, [%1, #28] \n\t" \
2919 "ldr r3, [%1, #32] \n\t" \
2920 "push {r0, r1, r2, r3} \n\t" \
2921 "ldr r0, [%1, #4] \n\t" \
2922 "ldr r1, [%1, #8] \n\t" \
2923 "ldr r2, [%1, #12] \n\t" \
2924 "ldr r3, [%1, #16] \n\t" \
2925 "ldr r4, [%1] \n\t" /* target->r4 */ \
2926 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2927 "add sp, sp, #16 \n\t" \
2928 "mov %0, r0" \
2929 : /*out*/ "=r" (_res) \
2930 : /*in*/ "0" (&_argvec[0]) \
2931 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2932 ); \
2933 lval = (__typeof__(lval)) _res; \
2934 } while (0)
2935
2936#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2937 arg7,arg8,arg9) \
2938 do { \
2939 volatile OrigFn _orig = (orig); \
2940 volatile unsigned long _argvec[10]; \
2941 volatile unsigned long _res; \
2942 _argvec[0] = (unsigned long)_orig.nraddr; \
2943 _argvec[1] = (unsigned long)(arg1); \
2944 _argvec[2] = (unsigned long)(arg2); \
2945 _argvec[3] = (unsigned long)(arg3); \
2946 _argvec[4] = (unsigned long)(arg4); \
2947 _argvec[5] = (unsigned long)(arg5); \
2948 _argvec[6] = (unsigned long)(arg6); \
2949 _argvec[7] = (unsigned long)(arg7); \
2950 _argvec[8] = (unsigned long)(arg8); \
2951 _argvec[9] = (unsigned long)(arg9); \
2952 __asm__ volatile( \
2953 "ldr r0, [%1, #20] \n\t" \
2954 "ldr r1, [%1, #24] \n\t" \
2955 "ldr r2, [%1, #28] \n\t" \
2956 "ldr r3, [%1, #32] \n\t" \
2957 "ldr r4, [%1, #36] \n\t" \
2958 "push {r0, r1, r2, r3, r4} \n\t" \
2959 "ldr r0, [%1, #4] \n\t" \
2960 "ldr r1, [%1, #8] \n\t" \
2961 "ldr r2, [%1, #12] \n\t" \
2962 "ldr r3, [%1, #16] \n\t" \
2963 "ldr r4, [%1] \n\t" /* target->r4 */ \
2964 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2965 "add sp, sp, #20 \n\t" \
2966 "mov %0, r0" \
2967 : /*out*/ "=r" (_res) \
2968 : /*in*/ "0" (&_argvec[0]) \
2969 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2970 ); \
2971 lval = (__typeof__(lval)) _res; \
2972 } while (0)
2973
2974#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2975 arg7,arg8,arg9,arg10) \
2976 do { \
2977 volatile OrigFn _orig = (orig); \
2978 volatile unsigned long _argvec[11]; \
2979 volatile unsigned long _res; \
2980 _argvec[0] = (unsigned long)_orig.nraddr; \
2981 _argvec[1] = (unsigned long)(arg1); \
2982 _argvec[2] = (unsigned long)(arg2); \
2983 _argvec[3] = (unsigned long)(arg3); \
2984 _argvec[4] = (unsigned long)(arg4); \
2985 _argvec[5] = (unsigned long)(arg5); \
2986 _argvec[6] = (unsigned long)(arg6); \
2987 _argvec[7] = (unsigned long)(arg7); \
2988 _argvec[8] = (unsigned long)(arg8); \
2989 _argvec[9] = (unsigned long)(arg9); \
2990 _argvec[10] = (unsigned long)(arg10); \
2991 __asm__ volatile( \
2992 "ldr r0, [%1, #40] \n\t" \
2993 "push {r0} \n\t" \
2994 "ldr r0, [%1, #20] \n\t" \
2995 "ldr r1, [%1, #24] \n\t" \
2996 "ldr r2, [%1, #28] \n\t" \
2997 "ldr r3, [%1, #32] \n\t" \
2998 "ldr r4, [%1, #36] \n\t" \
2999 "push {r0, r1, r2, r3, r4} \n\t" \
3000 "ldr r0, [%1, #4] \n\t" \
3001 "ldr r1, [%1, #8] \n\t" \
3002 "ldr r2, [%1, #12] \n\t" \
3003 "ldr r3, [%1, #16] \n\t" \
3004 "ldr r4, [%1] \n\t" /* target->r4 */ \
3005 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3006 "add sp, sp, #24 \n\t" \
3007 "mov %0, r0" \
3008 : /*out*/ "=r" (_res) \
3009 : /*in*/ "0" (&_argvec[0]) \
3010 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3011 ); \
3012 lval = (__typeof__(lval)) _res; \
3013 } while (0)
3014
3015#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3016 arg6,arg7,arg8,arg9,arg10, \
3017 arg11) \
3018 do { \
3019 volatile OrigFn _orig = (orig); \
3020 volatile unsigned long _argvec[12]; \
3021 volatile unsigned long _res; \
3022 _argvec[0] = (unsigned long)_orig.nraddr; \
3023 _argvec[1] = (unsigned long)(arg1); \
3024 _argvec[2] = (unsigned long)(arg2); \
3025 _argvec[3] = (unsigned long)(arg3); \
3026 _argvec[4] = (unsigned long)(arg4); \
3027 _argvec[5] = (unsigned long)(arg5); \
3028 _argvec[6] = (unsigned long)(arg6); \
3029 _argvec[7] = (unsigned long)(arg7); \
3030 _argvec[8] = (unsigned long)(arg8); \
3031 _argvec[9] = (unsigned long)(arg9); \
3032 _argvec[10] = (unsigned long)(arg10); \
3033 _argvec[11] = (unsigned long)(arg11); \
3034 __asm__ volatile( \
3035 "ldr r0, [%1, #40] \n\t" \
3036 "ldr r1, [%1, #44] \n\t" \
3037 "push {r0, r1} \n\t" \
3038 "ldr r0, [%1, #20] \n\t" \
3039 "ldr r1, [%1, #24] \n\t" \
3040 "ldr r2, [%1, #28] \n\t" \
3041 "ldr r3, [%1, #32] \n\t" \
3042 "ldr r4, [%1, #36] \n\t" \
3043 "push {r0, r1, r2, r3, r4} \n\t" \
3044 "ldr r0, [%1, #4] \n\t" \
3045 "ldr r1, [%1, #8] \n\t" \
3046 "ldr r2, [%1, #12] \n\t" \
3047 "ldr r3, [%1, #16] \n\t" \
3048 "ldr r4, [%1] \n\t" /* target->r4 */ \
3049 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3050 "add sp, sp, #28 \n\t" \
3051 "mov %0, r0" \
3052 : /*out*/ "=r" (_res) \
3053 : /*in*/ "0" (&_argvec[0]) \
3054 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3055 ); \
3056 lval = (__typeof__(lval)) _res; \
3057 } while (0)
3058
3059#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3060 arg6,arg7,arg8,arg9,arg10, \
3061 arg11,arg12) \
3062 do { \
3063 volatile OrigFn _orig = (orig); \
3064 volatile unsigned long _argvec[13]; \
3065 volatile unsigned long _res; \
3066 _argvec[0] = (unsigned long)_orig.nraddr; \
3067 _argvec[1] = (unsigned long)(arg1); \
3068 _argvec[2] = (unsigned long)(arg2); \
3069 _argvec[3] = (unsigned long)(arg3); \
3070 _argvec[4] = (unsigned long)(arg4); \
3071 _argvec[5] = (unsigned long)(arg5); \
3072 _argvec[6] = (unsigned long)(arg6); \
3073 _argvec[7] = (unsigned long)(arg7); \
3074 _argvec[8] = (unsigned long)(arg8); \
3075 _argvec[9] = (unsigned long)(arg9); \
3076 _argvec[10] = (unsigned long)(arg10); \
3077 _argvec[11] = (unsigned long)(arg11); \
3078 _argvec[12] = (unsigned long)(arg12); \
3079 __asm__ volatile( \
3080 "ldr r0, [%1, #40] \n\t" \
3081 "ldr r1, [%1, #44] \n\t" \
3082 "ldr r2, [%1, #48] \n\t" \
3083 "push {r0, r1, r2} \n\t" \
3084 "ldr r0, [%1, #20] \n\t" \
3085 "ldr r1, [%1, #24] \n\t" \
3086 "ldr r2, [%1, #28] \n\t" \
3087 "ldr r3, [%1, #32] \n\t" \
3088 "ldr r4, [%1, #36] \n\t" \
3089 "push {r0, r1, r2, r3, r4} \n\t" \
3090 "ldr r0, [%1, #4] \n\t" \
3091 "ldr r1, [%1, #8] \n\t" \
3092 "ldr r2, [%1, #12] \n\t" \
3093 "ldr r3, [%1, #16] \n\t" \
3094 "ldr r4, [%1] \n\t" /* target->r4 */ \
3095 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3096 "add sp, sp, #32 \n\t" \
3097 "mov %0, r0" \
3098 : /*out*/ "=r" (_res) \
3099 : /*in*/ "0" (&_argvec[0]) \
3100 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3101 ); \
3102 lval = (__typeof__(lval)) _res; \
3103 } while (0)
3104
3105#endif /* PLAT_arm_linux */
3106
sewardjf5c1a7f2006-10-17 01:32:48 +00003107/* ------------------------ ppc32-aix5 ------------------------- */
3108
3109#if defined(PLAT_ppc32_aix5)
3110
3111/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3112
3113/* These regs are trashed by the hidden call. */
3114#define __CALLER_SAVED_REGS \
3115 "lr", "ctr", "xer", \
3116 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3117 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3118 "r11", "r12", "r13"
3119
3120/* Expand the stack frame, copying enough info that unwinding
3121 still works. Trashes r3. */
3122
3123#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3124 "addi 1,1,-" #_n_fr "\n\t" \
3125 "lwz 3," #_n_fr "(1)\n\t" \
3126 "stw 3,0(1)\n\t"
3127
3128#define VG_CONTRACT_FRAME_BY(_n_fr) \
3129 "addi 1,1," #_n_fr "\n\t"
3130
3131/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
3132 long) == 4. */
3133
3134#define CALL_FN_W_v(lval, orig) \
3135 do { \
3136 volatile OrigFn _orig = (orig); \
3137 volatile unsigned long _argvec[3+0]; \
3138 volatile unsigned long _res; \
3139 /* _argvec[0] holds current r2 across the call */ \
3140 _argvec[1] = (unsigned long)_orig.r2; \
3141 _argvec[2] = (unsigned long)_orig.nraddr; \
3142 __asm__ volatile( \
3143 "mr 11,%1\n\t" \
3144 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3145 "stw 2,-8(11)\n\t" /* save tocptr */ \
3146 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3147 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3148 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3149 "mr 11,%1\n\t" \
3150 "mr %0,3\n\t" \
3151 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3152 VG_CONTRACT_FRAME_BY(512) \
3153 : /*out*/ "=r" (_res) \
3154 : /*in*/ "r" (&_argvec[2]) \
3155 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3156 ); \
3157 lval = (__typeof__(lval)) _res; \
3158 } while (0)
3159
3160#define CALL_FN_W_W(lval, orig, arg1) \
3161 do { \
3162 volatile OrigFn _orig = (orig); \
3163 volatile unsigned long _argvec[3+1]; \
3164 volatile unsigned long _res; \
3165 /* _argvec[0] holds current r2 across the call */ \
3166 _argvec[1] = (unsigned long)_orig.r2; \
3167 _argvec[2] = (unsigned long)_orig.nraddr; \
3168 _argvec[2+1] = (unsigned long)arg1; \
3169 __asm__ volatile( \
3170 "mr 11,%1\n\t" \
3171 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3172 "stw 2,-8(11)\n\t" /* save tocptr */ \
3173 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3174 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3175 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3176 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3177 "mr 11,%1\n\t" \
3178 "mr %0,3\n\t" \
3179 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3180 VG_CONTRACT_FRAME_BY(512) \
3181 : /*out*/ "=r" (_res) \
3182 : /*in*/ "r" (&_argvec[2]) \
3183 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3184 ); \
3185 lval = (__typeof__(lval)) _res; \
3186 } while (0)
3187
3188#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3189 do { \
3190 volatile OrigFn _orig = (orig); \
3191 volatile unsigned long _argvec[3+2]; \
3192 volatile unsigned long _res; \
3193 /* _argvec[0] holds current r2 across the call */ \
3194 _argvec[1] = (unsigned long)_orig.r2; \
3195 _argvec[2] = (unsigned long)_orig.nraddr; \
3196 _argvec[2+1] = (unsigned long)arg1; \
3197 _argvec[2+2] = (unsigned long)arg2; \
3198 __asm__ volatile( \
3199 "mr 11,%1\n\t" \
3200 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3201 "stw 2,-8(11)\n\t" /* save tocptr */ \
3202 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3203 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3204 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3205 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3206 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3207 "mr 11,%1\n\t" \
3208 "mr %0,3\n\t" \
3209 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3210 VG_CONTRACT_FRAME_BY(512) \
3211 : /*out*/ "=r" (_res) \
3212 : /*in*/ "r" (&_argvec[2]) \
3213 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3214 ); \
3215 lval = (__typeof__(lval)) _res; \
3216 } while (0)
3217
3218#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3219 do { \
3220 volatile OrigFn _orig = (orig); \
3221 volatile unsigned long _argvec[3+3]; \
3222 volatile unsigned long _res; \
3223 /* _argvec[0] holds current r2 across the call */ \
3224 _argvec[1] = (unsigned long)_orig.r2; \
3225 _argvec[2] = (unsigned long)_orig.nraddr; \
3226 _argvec[2+1] = (unsigned long)arg1; \
3227 _argvec[2+2] = (unsigned long)arg2; \
3228 _argvec[2+3] = (unsigned long)arg3; \
3229 __asm__ volatile( \
3230 "mr 11,%1\n\t" \
3231 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3232 "stw 2,-8(11)\n\t" /* save tocptr */ \
3233 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3234 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3235 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3236 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3237 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3238 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3239 "mr 11,%1\n\t" \
3240 "mr %0,3\n\t" \
3241 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3242 VG_CONTRACT_FRAME_BY(512) \
3243 : /*out*/ "=r" (_res) \
3244 : /*in*/ "r" (&_argvec[2]) \
3245 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3246 ); \
3247 lval = (__typeof__(lval)) _res; \
3248 } while (0)
3249
3250#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3251 do { \
3252 volatile OrigFn _orig = (orig); \
3253 volatile unsigned long _argvec[3+4]; \
3254 volatile unsigned long _res; \
3255 /* _argvec[0] holds current r2 across the call */ \
3256 _argvec[1] = (unsigned long)_orig.r2; \
3257 _argvec[2] = (unsigned long)_orig.nraddr; \
3258 _argvec[2+1] = (unsigned long)arg1; \
3259 _argvec[2+2] = (unsigned long)arg2; \
3260 _argvec[2+3] = (unsigned long)arg3; \
3261 _argvec[2+4] = (unsigned long)arg4; \
3262 __asm__ volatile( \
3263 "mr 11,%1\n\t" \
3264 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3265 "stw 2,-8(11)\n\t" /* save tocptr */ \
3266 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3267 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3268 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3269 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3270 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3271 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3272 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3273 "mr 11,%1\n\t" \
3274 "mr %0,3\n\t" \
3275 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3276 VG_CONTRACT_FRAME_BY(512) \
3277 : /*out*/ "=r" (_res) \
3278 : /*in*/ "r" (&_argvec[2]) \
3279 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3280 ); \
3281 lval = (__typeof__(lval)) _res; \
3282 } while (0)
3283
3284#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3285 do { \
3286 volatile OrigFn _orig = (orig); \
3287 volatile unsigned long _argvec[3+5]; \
3288 volatile unsigned long _res; \
3289 /* _argvec[0] holds current r2 across the call */ \
3290 _argvec[1] = (unsigned long)_orig.r2; \
3291 _argvec[2] = (unsigned long)_orig.nraddr; \
3292 _argvec[2+1] = (unsigned long)arg1; \
3293 _argvec[2+2] = (unsigned long)arg2; \
3294 _argvec[2+3] = (unsigned long)arg3; \
3295 _argvec[2+4] = (unsigned long)arg4; \
3296 _argvec[2+5] = (unsigned long)arg5; \
3297 __asm__ volatile( \
3298 "mr 11,%1\n\t" \
3299 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3300 "stw 2,-8(11)\n\t" /* save tocptr */ \
3301 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3302 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3303 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3304 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3305 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3306 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3307 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3308 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3309 "mr 11,%1\n\t" \
3310 "mr %0,3\n\t" \
3311 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3312 VG_CONTRACT_FRAME_BY(512) \
3313 : /*out*/ "=r" (_res) \
3314 : /*in*/ "r" (&_argvec[2]) \
3315 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3316 ); \
3317 lval = (__typeof__(lval)) _res; \
3318 } while (0)
3319
3320#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3321 do { \
3322 volatile OrigFn _orig = (orig); \
3323 volatile unsigned long _argvec[3+6]; \
3324 volatile unsigned long _res; \
3325 /* _argvec[0] holds current r2 across the call */ \
3326 _argvec[1] = (unsigned long)_orig.r2; \
3327 _argvec[2] = (unsigned long)_orig.nraddr; \
3328 _argvec[2+1] = (unsigned long)arg1; \
3329 _argvec[2+2] = (unsigned long)arg2; \
3330 _argvec[2+3] = (unsigned long)arg3; \
3331 _argvec[2+4] = (unsigned long)arg4; \
3332 _argvec[2+5] = (unsigned long)arg5; \
3333 _argvec[2+6] = (unsigned long)arg6; \
3334 __asm__ volatile( \
3335 "mr 11,%1\n\t" \
3336 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3337 "stw 2,-8(11)\n\t" /* save tocptr */ \
3338 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3339 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3340 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3341 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3342 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3343 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3344 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3345 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3346 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3347 "mr 11,%1\n\t" \
3348 "mr %0,3\n\t" \
3349 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3350 VG_CONTRACT_FRAME_BY(512) \
3351 : /*out*/ "=r" (_res) \
3352 : /*in*/ "r" (&_argvec[2]) \
3353 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3354 ); \
3355 lval = (__typeof__(lval)) _res; \
3356 } while (0)
3357
3358#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3359 arg7) \
3360 do { \
3361 volatile OrigFn _orig = (orig); \
3362 volatile unsigned long _argvec[3+7]; \
3363 volatile unsigned long _res; \
3364 /* _argvec[0] holds current r2 across the call */ \
3365 _argvec[1] = (unsigned long)_orig.r2; \
3366 _argvec[2] = (unsigned long)_orig.nraddr; \
3367 _argvec[2+1] = (unsigned long)arg1; \
3368 _argvec[2+2] = (unsigned long)arg2; \
3369 _argvec[2+3] = (unsigned long)arg3; \
3370 _argvec[2+4] = (unsigned long)arg4; \
3371 _argvec[2+5] = (unsigned long)arg5; \
3372 _argvec[2+6] = (unsigned long)arg6; \
3373 _argvec[2+7] = (unsigned long)arg7; \
3374 __asm__ volatile( \
3375 "mr 11,%1\n\t" \
3376 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3377 "stw 2,-8(11)\n\t" /* save tocptr */ \
3378 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3379 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3380 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3381 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3382 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3383 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3384 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3385 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3386 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3387 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3388 "mr 11,%1\n\t" \
3389 "mr %0,3\n\t" \
3390 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3391 VG_CONTRACT_FRAME_BY(512) \
3392 : /*out*/ "=r" (_res) \
3393 : /*in*/ "r" (&_argvec[2]) \
3394 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3395 ); \
3396 lval = (__typeof__(lval)) _res; \
3397 } while (0)
3398
3399#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3400 arg7,arg8) \
3401 do { \
3402 volatile OrigFn _orig = (orig); \
3403 volatile unsigned long _argvec[3+8]; \
3404 volatile unsigned long _res; \
3405 /* _argvec[0] holds current r2 across the call */ \
3406 _argvec[1] = (unsigned long)_orig.r2; \
3407 _argvec[2] = (unsigned long)_orig.nraddr; \
3408 _argvec[2+1] = (unsigned long)arg1; \
3409 _argvec[2+2] = (unsigned long)arg2; \
3410 _argvec[2+3] = (unsigned long)arg3; \
3411 _argvec[2+4] = (unsigned long)arg4; \
3412 _argvec[2+5] = (unsigned long)arg5; \
3413 _argvec[2+6] = (unsigned long)arg6; \
3414 _argvec[2+7] = (unsigned long)arg7; \
3415 _argvec[2+8] = (unsigned long)arg8; \
3416 __asm__ volatile( \
3417 "mr 11,%1\n\t" \
3418 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3419 "stw 2,-8(11)\n\t" /* save tocptr */ \
3420 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3421 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3422 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3423 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3424 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3425 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3426 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3427 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3428 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3429 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3430 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3431 "mr 11,%1\n\t" \
3432 "mr %0,3\n\t" \
3433 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3434 VG_CONTRACT_FRAME_BY(512) \
3435 : /*out*/ "=r" (_res) \
3436 : /*in*/ "r" (&_argvec[2]) \
3437 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3438 ); \
3439 lval = (__typeof__(lval)) _res; \
3440 } while (0)
3441
3442#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3443 arg7,arg8,arg9) \
3444 do { \
3445 volatile OrigFn _orig = (orig); \
3446 volatile unsigned long _argvec[3+9]; \
3447 volatile unsigned long _res; \
3448 /* _argvec[0] holds current r2 across the call */ \
3449 _argvec[1] = (unsigned long)_orig.r2; \
3450 _argvec[2] = (unsigned long)_orig.nraddr; \
3451 _argvec[2+1] = (unsigned long)arg1; \
3452 _argvec[2+2] = (unsigned long)arg2; \
3453 _argvec[2+3] = (unsigned long)arg3; \
3454 _argvec[2+4] = (unsigned long)arg4; \
3455 _argvec[2+5] = (unsigned long)arg5; \
3456 _argvec[2+6] = (unsigned long)arg6; \
3457 _argvec[2+7] = (unsigned long)arg7; \
3458 _argvec[2+8] = (unsigned long)arg8; \
3459 _argvec[2+9] = (unsigned long)arg9; \
3460 __asm__ volatile( \
3461 "mr 11,%1\n\t" \
3462 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3463 "stw 2,-8(11)\n\t" /* save tocptr */ \
3464 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3465 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3466 /* arg9 */ \
3467 "lwz 3,36(11)\n\t" \
3468 "stw 3,56(1)\n\t" \
3469 /* args1-8 */ \
3470 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3471 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3472 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3473 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3474 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3475 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3476 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3477 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3478 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3479 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3480 "mr 11,%1\n\t" \
3481 "mr %0,3\n\t" \
3482 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3483 VG_CONTRACT_FRAME_BY(64) \
3484 VG_CONTRACT_FRAME_BY(512) \
3485 : /*out*/ "=r" (_res) \
3486 : /*in*/ "r" (&_argvec[2]) \
3487 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3488 ); \
3489 lval = (__typeof__(lval)) _res; \
3490 } while (0)
3491
3492#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3493 arg7,arg8,arg9,arg10) \
3494 do { \
3495 volatile OrigFn _orig = (orig); \
3496 volatile unsigned long _argvec[3+10]; \
3497 volatile unsigned long _res; \
3498 /* _argvec[0] holds current r2 across the call */ \
3499 _argvec[1] = (unsigned long)_orig.r2; \
3500 _argvec[2] = (unsigned long)_orig.nraddr; \
3501 _argvec[2+1] = (unsigned long)arg1; \
3502 _argvec[2+2] = (unsigned long)arg2; \
3503 _argvec[2+3] = (unsigned long)arg3; \
3504 _argvec[2+4] = (unsigned long)arg4; \
3505 _argvec[2+5] = (unsigned long)arg5; \
3506 _argvec[2+6] = (unsigned long)arg6; \
3507 _argvec[2+7] = (unsigned long)arg7; \
3508 _argvec[2+8] = (unsigned long)arg8; \
3509 _argvec[2+9] = (unsigned long)arg9; \
3510 _argvec[2+10] = (unsigned long)arg10; \
3511 __asm__ volatile( \
3512 "mr 11,%1\n\t" \
3513 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3514 "stw 2,-8(11)\n\t" /* save tocptr */ \
3515 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3516 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3517 /* arg10 */ \
3518 "lwz 3,40(11)\n\t" \
3519 "stw 3,60(1)\n\t" \
3520 /* arg9 */ \
3521 "lwz 3,36(11)\n\t" \
3522 "stw 3,56(1)\n\t" \
3523 /* args1-8 */ \
3524 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3525 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3526 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3527 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3528 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3529 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3530 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3531 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3532 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3533 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3534 "mr 11,%1\n\t" \
3535 "mr %0,3\n\t" \
3536 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3537 VG_CONTRACT_FRAME_BY(64) \
3538 VG_CONTRACT_FRAME_BY(512) \
3539 : /*out*/ "=r" (_res) \
3540 : /*in*/ "r" (&_argvec[2]) \
3541 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3542 ); \
3543 lval = (__typeof__(lval)) _res; \
3544 } while (0)
3545
3546#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3547 arg7,arg8,arg9,arg10,arg11) \
3548 do { \
3549 volatile OrigFn _orig = (orig); \
3550 volatile unsigned long _argvec[3+11]; \
3551 volatile unsigned long _res; \
3552 /* _argvec[0] holds current r2 across the call */ \
3553 _argvec[1] = (unsigned long)_orig.r2; \
3554 _argvec[2] = (unsigned long)_orig.nraddr; \
3555 _argvec[2+1] = (unsigned long)arg1; \
3556 _argvec[2+2] = (unsigned long)arg2; \
3557 _argvec[2+3] = (unsigned long)arg3; \
3558 _argvec[2+4] = (unsigned long)arg4; \
3559 _argvec[2+5] = (unsigned long)arg5; \
3560 _argvec[2+6] = (unsigned long)arg6; \
3561 _argvec[2+7] = (unsigned long)arg7; \
3562 _argvec[2+8] = (unsigned long)arg8; \
3563 _argvec[2+9] = (unsigned long)arg9; \
3564 _argvec[2+10] = (unsigned long)arg10; \
3565 _argvec[2+11] = (unsigned long)arg11; \
3566 __asm__ volatile( \
3567 "mr 11,%1\n\t" \
3568 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3569 "stw 2,-8(11)\n\t" /* save tocptr */ \
3570 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3571 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3572 /* arg11 */ \
3573 "lwz 3,44(11)\n\t" \
3574 "stw 3,64(1)\n\t" \
3575 /* arg10 */ \
3576 "lwz 3,40(11)\n\t" \
3577 "stw 3,60(1)\n\t" \
3578 /* arg9 */ \
3579 "lwz 3,36(11)\n\t" \
3580 "stw 3,56(1)\n\t" \
3581 /* args1-8 */ \
3582 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3583 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3584 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3585 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3586 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3587 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3588 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3589 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3590 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3591 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3592 "mr 11,%1\n\t" \
3593 "mr %0,3\n\t" \
3594 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3595 VG_CONTRACT_FRAME_BY(72) \
3596 VG_CONTRACT_FRAME_BY(512) \
3597 : /*out*/ "=r" (_res) \
3598 : /*in*/ "r" (&_argvec[2]) \
3599 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3600 ); \
3601 lval = (__typeof__(lval)) _res; \
3602 } while (0)
3603
3604#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3605 arg7,arg8,arg9,arg10,arg11,arg12) \
3606 do { \
3607 volatile OrigFn _orig = (orig); \
3608 volatile unsigned long _argvec[3+12]; \
3609 volatile unsigned long _res; \
3610 /* _argvec[0] holds current r2 across the call */ \
3611 _argvec[1] = (unsigned long)_orig.r2; \
3612 _argvec[2] = (unsigned long)_orig.nraddr; \
3613 _argvec[2+1] = (unsigned long)arg1; \
3614 _argvec[2+2] = (unsigned long)arg2; \
3615 _argvec[2+3] = (unsigned long)arg3; \
3616 _argvec[2+4] = (unsigned long)arg4; \
3617 _argvec[2+5] = (unsigned long)arg5; \
3618 _argvec[2+6] = (unsigned long)arg6; \
3619 _argvec[2+7] = (unsigned long)arg7; \
3620 _argvec[2+8] = (unsigned long)arg8; \
3621 _argvec[2+9] = (unsigned long)arg9; \
3622 _argvec[2+10] = (unsigned long)arg10; \
3623 _argvec[2+11] = (unsigned long)arg11; \
3624 _argvec[2+12] = (unsigned long)arg12; \
3625 __asm__ volatile( \
3626 "mr 11,%1\n\t" \
3627 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3628 "stw 2,-8(11)\n\t" /* save tocptr */ \
3629 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3630 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3631 /* arg12 */ \
3632 "lwz 3,48(11)\n\t" \
3633 "stw 3,68(1)\n\t" \
3634 /* arg11 */ \
3635 "lwz 3,44(11)\n\t" \
3636 "stw 3,64(1)\n\t" \
3637 /* arg10 */ \
3638 "lwz 3,40(11)\n\t" \
3639 "stw 3,60(1)\n\t" \
3640 /* arg9 */ \
3641 "lwz 3,36(11)\n\t" \
3642 "stw 3,56(1)\n\t" \
3643 /* args1-8 */ \
3644 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3645 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3646 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3647 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3648 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3649 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3650 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3651 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3652 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3653 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3654 "mr 11,%1\n\t" \
3655 "mr %0,3\n\t" \
3656 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3657 VG_CONTRACT_FRAME_BY(72) \
3658 VG_CONTRACT_FRAME_BY(512) \
3659 : /*out*/ "=r" (_res) \
3660 : /*in*/ "r" (&_argvec[2]) \
3661 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3662 ); \
3663 lval = (__typeof__(lval)) _res; \
3664 } while (0)
3665
3666#endif /* PLAT_ppc32_aix5 */
3667
3668/* ------------------------ ppc64-aix5 ------------------------- */
3669
3670#if defined(PLAT_ppc64_aix5)
3671
3672/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3673
3674/* These regs are trashed by the hidden call. */
3675#define __CALLER_SAVED_REGS \
3676 "lr", "ctr", "xer", \
3677 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3678 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3679 "r11", "r12", "r13"
3680
3681/* Expand the stack frame, copying enough info that unwinding
3682 still works. Trashes r3. */
3683
3684#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3685 "addi 1,1,-" #_n_fr "\n\t" \
3686 "ld 3," #_n_fr "(1)\n\t" \
3687 "std 3,0(1)\n\t"
3688
3689#define VG_CONTRACT_FRAME_BY(_n_fr) \
3690 "addi 1,1," #_n_fr "\n\t"
3691
3692/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3693 long) == 8. */
3694
3695#define CALL_FN_W_v(lval, orig) \
3696 do { \
3697 volatile OrigFn _orig = (orig); \
3698 volatile unsigned long _argvec[3+0]; \
3699 volatile unsigned long _res; \
3700 /* _argvec[0] holds current r2 across the call */ \
3701 _argvec[1] = (unsigned long)_orig.r2; \
3702 _argvec[2] = (unsigned long)_orig.nraddr; \
3703 __asm__ volatile( \
3704 "mr 11,%1\n\t" \
3705 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3706 "std 2,-16(11)\n\t" /* save tocptr */ \
3707 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3708 "ld 11, 0(11)\n\t" /* target->r11 */ \
3709 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3710 "mr 11,%1\n\t" \
3711 "mr %0,3\n\t" \
3712 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3713 VG_CONTRACT_FRAME_BY(512) \
3714 : /*out*/ "=r" (_res) \
3715 : /*in*/ "r" (&_argvec[2]) \
3716 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3717 ); \
3718 lval = (__typeof__(lval)) _res; \
3719 } while (0)
3720
3721#define CALL_FN_W_W(lval, orig, arg1) \
3722 do { \
3723 volatile OrigFn _orig = (orig); \
3724 volatile unsigned long _argvec[3+1]; \
3725 volatile unsigned long _res; \
3726 /* _argvec[0] holds current r2 across the call */ \
3727 _argvec[1] = (unsigned long)_orig.r2; \
3728 _argvec[2] = (unsigned long)_orig.nraddr; \
3729 _argvec[2+1] = (unsigned long)arg1; \
3730 __asm__ volatile( \
3731 "mr 11,%1\n\t" \
3732 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3733 "std 2,-16(11)\n\t" /* save tocptr */ \
3734 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3735 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3736 "ld 11, 0(11)\n\t" /* target->r11 */ \
3737 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3738 "mr 11,%1\n\t" \
3739 "mr %0,3\n\t" \
3740 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3741 VG_CONTRACT_FRAME_BY(512) \
3742 : /*out*/ "=r" (_res) \
3743 : /*in*/ "r" (&_argvec[2]) \
3744 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3745 ); \
3746 lval = (__typeof__(lval)) _res; \
3747 } while (0)
3748
3749#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3750 do { \
3751 volatile OrigFn _orig = (orig); \
3752 volatile unsigned long _argvec[3+2]; \
3753 volatile unsigned long _res; \
3754 /* _argvec[0] holds current r2 across the call */ \
3755 _argvec[1] = (unsigned long)_orig.r2; \
3756 _argvec[2] = (unsigned long)_orig.nraddr; \
3757 _argvec[2+1] = (unsigned long)arg1; \
3758 _argvec[2+2] = (unsigned long)arg2; \
3759 __asm__ volatile( \
3760 "mr 11,%1\n\t" \
3761 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3762 "std 2,-16(11)\n\t" /* save tocptr */ \
3763 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3764 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3765 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3766 "ld 11, 0(11)\n\t" /* target->r11 */ \
3767 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3768 "mr 11,%1\n\t" \
3769 "mr %0,3\n\t" \
3770 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3771 VG_CONTRACT_FRAME_BY(512) \
3772 : /*out*/ "=r" (_res) \
3773 : /*in*/ "r" (&_argvec[2]) \
3774 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3775 ); \
3776 lval = (__typeof__(lval)) _res; \
3777 } while (0)
3778
3779#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3780 do { \
3781 volatile OrigFn _orig = (orig); \
3782 volatile unsigned long _argvec[3+3]; \
3783 volatile unsigned long _res; \
3784 /* _argvec[0] holds current r2 across the call */ \
3785 _argvec[1] = (unsigned long)_orig.r2; \
3786 _argvec[2] = (unsigned long)_orig.nraddr; \
3787 _argvec[2+1] = (unsigned long)arg1; \
3788 _argvec[2+2] = (unsigned long)arg2; \
3789 _argvec[2+3] = (unsigned long)arg3; \
3790 __asm__ volatile( \
3791 "mr 11,%1\n\t" \
3792 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3793 "std 2,-16(11)\n\t" /* save tocptr */ \
3794 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3795 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3796 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3797 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3798 "ld 11, 0(11)\n\t" /* target->r11 */ \
3799 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3800 "mr 11,%1\n\t" \
3801 "mr %0,3\n\t" \
3802 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3803 VG_CONTRACT_FRAME_BY(512) \
3804 : /*out*/ "=r" (_res) \
3805 : /*in*/ "r" (&_argvec[2]) \
3806 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3807 ); \
3808 lval = (__typeof__(lval)) _res; \
3809 } while (0)
3810
3811#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3812 do { \
3813 volatile OrigFn _orig = (orig); \
3814 volatile unsigned long _argvec[3+4]; \
3815 volatile unsigned long _res; \
3816 /* _argvec[0] holds current r2 across the call */ \
3817 _argvec[1] = (unsigned long)_orig.r2; \
3818 _argvec[2] = (unsigned long)_orig.nraddr; \
3819 _argvec[2+1] = (unsigned long)arg1; \
3820 _argvec[2+2] = (unsigned long)arg2; \
3821 _argvec[2+3] = (unsigned long)arg3; \
3822 _argvec[2+4] = (unsigned long)arg4; \
3823 __asm__ volatile( \
3824 "mr 11,%1\n\t" \
3825 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3826 "std 2,-16(11)\n\t" /* save tocptr */ \
3827 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3828 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3829 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3830 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3831 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3832 "ld 11, 0(11)\n\t" /* target->r11 */ \
3833 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3834 "mr 11,%1\n\t" \
3835 "mr %0,3\n\t" \
3836 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3837 VG_CONTRACT_FRAME_BY(512) \
3838 : /*out*/ "=r" (_res) \
3839 : /*in*/ "r" (&_argvec[2]) \
3840 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3841 ); \
3842 lval = (__typeof__(lval)) _res; \
3843 } while (0)
3844
3845#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3846 do { \
3847 volatile OrigFn _orig = (orig); \
3848 volatile unsigned long _argvec[3+5]; \
3849 volatile unsigned long _res; \
3850 /* _argvec[0] holds current r2 across the call */ \
3851 _argvec[1] = (unsigned long)_orig.r2; \
3852 _argvec[2] = (unsigned long)_orig.nraddr; \
3853 _argvec[2+1] = (unsigned long)arg1; \
3854 _argvec[2+2] = (unsigned long)arg2; \
3855 _argvec[2+3] = (unsigned long)arg3; \
3856 _argvec[2+4] = (unsigned long)arg4; \
3857 _argvec[2+5] = (unsigned long)arg5; \
3858 __asm__ volatile( \
3859 "mr 11,%1\n\t" \
3860 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3861 "std 2,-16(11)\n\t" /* save tocptr */ \
3862 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3863 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3864 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3865 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3866 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3867 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3868 "ld 11, 0(11)\n\t" /* target->r11 */ \
3869 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3870 "mr 11,%1\n\t" \
3871 "mr %0,3\n\t" \
3872 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3873 VG_CONTRACT_FRAME_BY(512) \
3874 : /*out*/ "=r" (_res) \
3875 : /*in*/ "r" (&_argvec[2]) \
3876 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3877 ); \
3878 lval = (__typeof__(lval)) _res; \
3879 } while (0)
3880
3881#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3882 do { \
3883 volatile OrigFn _orig = (orig); \
3884 volatile unsigned long _argvec[3+6]; \
3885 volatile unsigned long _res; \
3886 /* _argvec[0] holds current r2 across the call */ \
3887 _argvec[1] = (unsigned long)_orig.r2; \
3888 _argvec[2] = (unsigned long)_orig.nraddr; \
3889 _argvec[2+1] = (unsigned long)arg1; \
3890 _argvec[2+2] = (unsigned long)arg2; \
3891 _argvec[2+3] = (unsigned long)arg3; \
3892 _argvec[2+4] = (unsigned long)arg4; \
3893 _argvec[2+5] = (unsigned long)arg5; \
3894 _argvec[2+6] = (unsigned long)arg6; \
3895 __asm__ volatile( \
3896 "mr 11,%1\n\t" \
3897 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3898 "std 2,-16(11)\n\t" /* save tocptr */ \
3899 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3900 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3901 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3902 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3903 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3904 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3905 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3906 "ld 11, 0(11)\n\t" /* target->r11 */ \
3907 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3908 "mr 11,%1\n\t" \
3909 "mr %0,3\n\t" \
3910 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3911 VG_CONTRACT_FRAME_BY(512) \
3912 : /*out*/ "=r" (_res) \
3913 : /*in*/ "r" (&_argvec[2]) \
3914 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3915 ); \
3916 lval = (__typeof__(lval)) _res; \
3917 } while (0)
3918
3919#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3920 arg7) \
3921 do { \
3922 volatile OrigFn _orig = (orig); \
3923 volatile unsigned long _argvec[3+7]; \
3924 volatile unsigned long _res; \
3925 /* _argvec[0] holds current r2 across the call */ \
3926 _argvec[1] = (unsigned long)_orig.r2; \
3927 _argvec[2] = (unsigned long)_orig.nraddr; \
3928 _argvec[2+1] = (unsigned long)arg1; \
3929 _argvec[2+2] = (unsigned long)arg2; \
3930 _argvec[2+3] = (unsigned long)arg3; \
3931 _argvec[2+4] = (unsigned long)arg4; \
3932 _argvec[2+5] = (unsigned long)arg5; \
3933 _argvec[2+6] = (unsigned long)arg6; \
3934 _argvec[2+7] = (unsigned long)arg7; \
3935 __asm__ volatile( \
3936 "mr 11,%1\n\t" \
3937 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3938 "std 2,-16(11)\n\t" /* save tocptr */ \
3939 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3940 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3941 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3942 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3943 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3944 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3945 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3946 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3947 "ld 11, 0(11)\n\t" /* target->r11 */ \
3948 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3949 "mr 11,%1\n\t" \
3950 "mr %0,3\n\t" \
3951 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3952 VG_CONTRACT_FRAME_BY(512) \
3953 : /*out*/ "=r" (_res) \
3954 : /*in*/ "r" (&_argvec[2]) \
3955 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3956 ); \
3957 lval = (__typeof__(lval)) _res; \
3958 } while (0)
3959
3960#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3961 arg7,arg8) \
3962 do { \
3963 volatile OrigFn _orig = (orig); \
3964 volatile unsigned long _argvec[3+8]; \
3965 volatile unsigned long _res; \
3966 /* _argvec[0] holds current r2 across the call */ \
3967 _argvec[1] = (unsigned long)_orig.r2; \
3968 _argvec[2] = (unsigned long)_orig.nraddr; \
3969 _argvec[2+1] = (unsigned long)arg1; \
3970 _argvec[2+2] = (unsigned long)arg2; \
3971 _argvec[2+3] = (unsigned long)arg3; \
3972 _argvec[2+4] = (unsigned long)arg4; \
3973 _argvec[2+5] = (unsigned long)arg5; \
3974 _argvec[2+6] = (unsigned long)arg6; \
3975 _argvec[2+7] = (unsigned long)arg7; \
3976 _argvec[2+8] = (unsigned long)arg8; \
3977 __asm__ volatile( \
3978 "mr 11,%1\n\t" \
3979 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3980 "std 2,-16(11)\n\t" /* save tocptr */ \
3981 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3982 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3983 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3984 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3985 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3986 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3987 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3988 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3989 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3990 "ld 11, 0(11)\n\t" /* target->r11 */ \
3991 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3992 "mr 11,%1\n\t" \
3993 "mr %0,3\n\t" \
3994 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3995 VG_CONTRACT_FRAME_BY(512) \
3996 : /*out*/ "=r" (_res) \
3997 : /*in*/ "r" (&_argvec[2]) \
3998 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3999 ); \
4000 lval = (__typeof__(lval)) _res; \
4001 } while (0)
4002
4003#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4004 arg7,arg8,arg9) \
4005 do { \
4006 volatile OrigFn _orig = (orig); \
4007 volatile unsigned long _argvec[3+9]; \
4008 volatile unsigned long _res; \
4009 /* _argvec[0] holds current r2 across the call */ \
4010 _argvec[1] = (unsigned long)_orig.r2; \
4011 _argvec[2] = (unsigned long)_orig.nraddr; \
4012 _argvec[2+1] = (unsigned long)arg1; \
4013 _argvec[2+2] = (unsigned long)arg2; \
4014 _argvec[2+3] = (unsigned long)arg3; \
4015 _argvec[2+4] = (unsigned long)arg4; \
4016 _argvec[2+5] = (unsigned long)arg5; \
4017 _argvec[2+6] = (unsigned long)arg6; \
4018 _argvec[2+7] = (unsigned long)arg7; \
4019 _argvec[2+8] = (unsigned long)arg8; \
4020 _argvec[2+9] = (unsigned long)arg9; \
4021 __asm__ volatile( \
4022 "mr 11,%1\n\t" \
4023 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4024 "std 2,-16(11)\n\t" /* save tocptr */ \
4025 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4026 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4027 /* arg9 */ \
4028 "ld 3,72(11)\n\t" \
4029 "std 3,112(1)\n\t" \
4030 /* args1-8 */ \
4031 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4032 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4033 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4034 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4035 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4036 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4037 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4038 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4039 "ld 11, 0(11)\n\t" /* target->r11 */ \
4040 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4041 "mr 11,%1\n\t" \
4042 "mr %0,3\n\t" \
4043 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4044 VG_CONTRACT_FRAME_BY(128) \
4045 VG_CONTRACT_FRAME_BY(512) \
4046 : /*out*/ "=r" (_res) \
4047 : /*in*/ "r" (&_argvec[2]) \
4048 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4049 ); \
4050 lval = (__typeof__(lval)) _res; \
4051 } while (0)
4052
4053#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4054 arg7,arg8,arg9,arg10) \
4055 do { \
4056 volatile OrigFn _orig = (orig); \
4057 volatile unsigned long _argvec[3+10]; \
4058 volatile unsigned long _res; \
4059 /* _argvec[0] holds current r2 across the call */ \
4060 _argvec[1] = (unsigned long)_orig.r2; \
4061 _argvec[2] = (unsigned long)_orig.nraddr; \
4062 _argvec[2+1] = (unsigned long)arg1; \
4063 _argvec[2+2] = (unsigned long)arg2; \
4064 _argvec[2+3] = (unsigned long)arg3; \
4065 _argvec[2+4] = (unsigned long)arg4; \
4066 _argvec[2+5] = (unsigned long)arg5; \
4067 _argvec[2+6] = (unsigned long)arg6; \
4068 _argvec[2+7] = (unsigned long)arg7; \
4069 _argvec[2+8] = (unsigned long)arg8; \
4070 _argvec[2+9] = (unsigned long)arg9; \
4071 _argvec[2+10] = (unsigned long)arg10; \
4072 __asm__ volatile( \
4073 "mr 11,%1\n\t" \
4074 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4075 "std 2,-16(11)\n\t" /* save tocptr */ \
4076 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4077 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4078 /* arg10 */ \
4079 "ld 3,80(11)\n\t" \
4080 "std 3,120(1)\n\t" \
4081 /* arg9 */ \
4082 "ld 3,72(11)\n\t" \
4083 "std 3,112(1)\n\t" \
4084 /* args1-8 */ \
4085 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4086 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4087 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4088 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4089 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4090 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4091 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4092 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4093 "ld 11, 0(11)\n\t" /* target->r11 */ \
4094 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4095 "mr 11,%1\n\t" \
4096 "mr %0,3\n\t" \
4097 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4098 VG_CONTRACT_FRAME_BY(128) \
4099 VG_CONTRACT_FRAME_BY(512) \
4100 : /*out*/ "=r" (_res) \
4101 : /*in*/ "r" (&_argvec[2]) \
4102 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4103 ); \
4104 lval = (__typeof__(lval)) _res; \
4105 } while (0)
4106
4107#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4108 arg7,arg8,arg9,arg10,arg11) \
4109 do { \
4110 volatile OrigFn _orig = (orig); \
4111 volatile unsigned long _argvec[3+11]; \
4112 volatile unsigned long _res; \
4113 /* _argvec[0] holds current r2 across the call */ \
4114 _argvec[1] = (unsigned long)_orig.r2; \
4115 _argvec[2] = (unsigned long)_orig.nraddr; \
4116 _argvec[2+1] = (unsigned long)arg1; \
4117 _argvec[2+2] = (unsigned long)arg2; \
4118 _argvec[2+3] = (unsigned long)arg3; \
4119 _argvec[2+4] = (unsigned long)arg4; \
4120 _argvec[2+5] = (unsigned long)arg5; \
4121 _argvec[2+6] = (unsigned long)arg6; \
4122 _argvec[2+7] = (unsigned long)arg7; \
4123 _argvec[2+8] = (unsigned long)arg8; \
4124 _argvec[2+9] = (unsigned long)arg9; \
4125 _argvec[2+10] = (unsigned long)arg10; \
4126 _argvec[2+11] = (unsigned long)arg11; \
4127 __asm__ volatile( \
4128 "mr 11,%1\n\t" \
4129 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4130 "std 2,-16(11)\n\t" /* save tocptr */ \
4131 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4132 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4133 /* arg11 */ \
4134 "ld 3,88(11)\n\t" \
4135 "std 3,128(1)\n\t" \
4136 /* arg10 */ \
4137 "ld 3,80(11)\n\t" \
4138 "std 3,120(1)\n\t" \
4139 /* arg9 */ \
4140 "ld 3,72(11)\n\t" \
4141 "std 3,112(1)\n\t" \
4142 /* args1-8 */ \
4143 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4144 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4145 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4146 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4147 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4148 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4149 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4150 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4151 "ld 11, 0(11)\n\t" /* target->r11 */ \
4152 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4153 "mr 11,%1\n\t" \
4154 "mr %0,3\n\t" \
4155 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4156 VG_CONTRACT_FRAME_BY(144) \
4157 VG_CONTRACT_FRAME_BY(512) \
4158 : /*out*/ "=r" (_res) \
4159 : /*in*/ "r" (&_argvec[2]) \
4160 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4161 ); \
4162 lval = (__typeof__(lval)) _res; \
4163 } while (0)
4164
4165#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4166 arg7,arg8,arg9,arg10,arg11,arg12) \
4167 do { \
4168 volatile OrigFn _orig = (orig); \
4169 volatile unsigned long _argvec[3+12]; \
4170 volatile unsigned long _res; \
4171 /* _argvec[0] holds current r2 across the call */ \
4172 _argvec[1] = (unsigned long)_orig.r2; \
4173 _argvec[2] = (unsigned long)_orig.nraddr; \
4174 _argvec[2+1] = (unsigned long)arg1; \
4175 _argvec[2+2] = (unsigned long)arg2; \
4176 _argvec[2+3] = (unsigned long)arg3; \
4177 _argvec[2+4] = (unsigned long)arg4; \
4178 _argvec[2+5] = (unsigned long)arg5; \
4179 _argvec[2+6] = (unsigned long)arg6; \
4180 _argvec[2+7] = (unsigned long)arg7; \
4181 _argvec[2+8] = (unsigned long)arg8; \
4182 _argvec[2+9] = (unsigned long)arg9; \
4183 _argvec[2+10] = (unsigned long)arg10; \
4184 _argvec[2+11] = (unsigned long)arg11; \
4185 _argvec[2+12] = (unsigned long)arg12; \
4186 __asm__ volatile( \
4187 "mr 11,%1\n\t" \
4188 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4189 "std 2,-16(11)\n\t" /* save tocptr */ \
4190 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4191 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4192 /* arg12 */ \
4193 "ld 3,96(11)\n\t" \
4194 "std 3,136(1)\n\t" \
4195 /* arg11 */ \
4196 "ld 3,88(11)\n\t" \
4197 "std 3,128(1)\n\t" \
4198 /* arg10 */ \
4199 "ld 3,80(11)\n\t" \
4200 "std 3,120(1)\n\t" \
4201 /* arg9 */ \
4202 "ld 3,72(11)\n\t" \
4203 "std 3,112(1)\n\t" \
4204 /* args1-8 */ \
4205 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4206 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4207 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4208 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4209 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4210 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4211 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4212 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4213 "ld 11, 0(11)\n\t" /* target->r11 */ \
4214 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4215 "mr 11,%1\n\t" \
4216 "mr %0,3\n\t" \
4217 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4218 VG_CONTRACT_FRAME_BY(144) \
4219 VG_CONTRACT_FRAME_BY(512) \
4220 : /*out*/ "=r" (_res) \
4221 : /*in*/ "r" (&_argvec[2]) \
4222 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4223 ); \
4224 lval = (__typeof__(lval)) _res; \
4225 } while (0)
4226
4227#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00004228
sewardj0ec07f32006-01-12 12:32:32 +00004229
4230/* ------------------------------------------------------------------ */
4231/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4232/* */
njn30d76c62005-06-18 15:07:39 +00004233/* ------------------------------------------------------------------ */
4234
sewardj2e93c502002-04-12 11:12:52 +00004235/* Some request codes. There are many more of these, but most are not
4236 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004237 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004238
sewardj0ec07f32006-01-12 12:32:32 +00004239 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4240 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004241*/
4242
sewardj0ec07f32006-01-12 12:32:32 +00004243/* These macros are used by tools -- they must be public, but don't
4244 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004245#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004246 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004247#define VG_IS_TOOL_USERREQ(a, b, v) \
4248 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004249
sewardj5ce4b152006-03-11 12:57:41 +00004250/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4251 This enum comprises an ABI exported by Valgrind to programs
4252 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4253 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004254typedef
njn4c791212003-05-02 17:53:54 +00004255 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4256 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004257
sewardj0ec07f32006-01-12 12:32:32 +00004258 /* These allow any function to be called from the simulated
4259 CPU but run on the real CPU. Nb: the first arg passed to
4260 the function is always the ThreadId of the running
4261 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004262 function, etc. */
njn4c791212003-05-02 17:53:54 +00004263 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4264 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4265 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4266 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004267
sewardj0ec07f32006-01-12 12:32:32 +00004268 /* Can be useful in regression testing suites -- eg. can
4269 send Valgrind's output to /dev/null and still count
4270 errors. */
njn4c791212003-05-02 17:53:54 +00004271 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004272
sewardj0ec07f32006-01-12 12:32:32 +00004273 /* These are useful and can be interpreted by any tool that
4274 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004275 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4276 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004277 /* Memory pool support. */
4278 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4279 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4280 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4281 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004282 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004283 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4284 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4285 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004286
fitzhardinge39de4b42003-10-31 07:12:21 +00004287 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00004288 /* The first two pass the va_list argument by value, which
4289 assumes it is the same size as or smaller than a UWord,
4290 which generally isn't the case. Hence are deprecated.
4291 The second two pass the vargs by reference and so are
4292 immune to this problem. */
4293 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00004294 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004295 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00004296 /* both :: char* fmt, va_list* vargs */
4297 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4298 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00004299
4300 /* Stack support. */
4301 VG_USERREQ__STACK_REGISTER = 0x1501,
4302 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004303 VG_USERREQ__STACK_CHANGE = 0x1503,
4304
4305 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00004306 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
4307
4308 /* Querying of debug info. */
4309 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701
njn25e49d8e72002-09-23 09:36:25 +00004310 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004311
sewardj0ec07f32006-01-12 12:32:32 +00004312#if !defined(__GNUC__)
4313# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004314#endif
sewardj2e93c502002-04-12 11:12:52 +00004315
bartfa5115a2010-09-02 09:33:02 +00004316
4317/*
4318 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
4319 * client request and whose value equals the client request result.
4320 */
4321
4322#if defined(NVALGRIND)
4323
4324#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4325 _zzq_default, _zzq_request, \
4326 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4327 (_zzq_default)
4328
4329#else /*defined(NVALGRIND)*/
4330
4331#if defined(_MSC_VER)
4332
4333#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4334 _zzq_default, _zzq_request, \
4335 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4336 (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \
4337 (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \
4338 (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \
4339 (uintptr_t)(_zzq_arg5)))
4340
4341static __inline unsigned
4342vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default,
4343 unsigned _zzq_request, uintptr_t _zzq_arg1,
4344 uintptr_t _zzq_arg2, uintptr_t _zzq_arg3,
4345 uintptr_t _zzq_arg4, uintptr_t _zzq_arg5)
4346{
4347 unsigned _zzq_rlval;
4348 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request,
4349 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5);
4350 return _zzq_rlval;
4351}
4352
4353#else /*defined(_MSC_VER)*/
4354
4355#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4356 _zzq_default, _zzq_request, \
4357 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4358 (__extension__({unsigned int _zzq_rlval; \
4359 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \
4360 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4361 _zzq_rlval; \
4362 }))
4363
4364#endif /*defined(_MSC_VER)*/
4365
4366#endif /*defined(NVALGRIND)*/
4367
4368
sewardj0ec07f32006-01-12 12:32:32 +00004369/* Returns the number of Valgrinds this code is running under. That
4370 is, 0 if running natively, 1 if running under Valgrind, 2 if
4371 running under Valgrind which is running under another Valgrind,
4372 etc. */
bartfa5115a2010-09-02 09:33:02 +00004373#define RUNNING_ON_VALGRIND \
4374 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
4375 VG_USERREQ__RUNNING_ON_VALGRIND, \
4376 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00004377
4378
sewardj18d75132002-05-16 11:06:21 +00004379/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4380 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4381 since it provides a way to make sure valgrind will retranslate the
4382 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00004383#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4384 {unsigned int _qzz_res; \
4385 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4386 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00004387 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00004388 }
4389
njn26aba4d2005-05-16 13:31:23 +00004390
sewardj0ec07f32006-01-12 12:32:32 +00004391/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004392 Possibly with a backtrace. This is a really ugly hack. The return value
4393 is the number of characters printed, excluding the "**<pid>** " part at the
4394 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004395
4396#if defined(NVALGRIND)
4397
4398# define VALGRIND_PRINTF(...)
4399# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00004400
4401#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004402
bart7f489812010-08-27 10:05:27 +00004403#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004404/* Modern GCC will optimize the static routine out if unused,
4405 and unused attribute will shut down warnings about it. */
4406static int VALGRIND_PRINTF(const char *format, ...)
4407 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004408#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004409static int
bart0da2c772010-09-01 10:18:36 +00004410#if defined(_MSC_VER)
4411__inline
4412#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004413VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004414{
njnc6168192004-11-29 13:54:10 +00004415 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004416 va_list vargs;
4417 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004418#if defined(_MSC_VER)
4419 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4420 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004421 (uintptr_t)format,
4422 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004423 0, 0, 0);
4424#else
sewardjc560fb32010-01-28 15:23:54 +00004425 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4426 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004427 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004428 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004429 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004430#endif
sewardjc560fb32010-01-28 15:23:54 +00004431 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004432 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004433}
4434
bart7f489812010-08-27 10:05:27 +00004435#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004436static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4437 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004438#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004439static int
bart0da2c772010-09-01 10:18:36 +00004440#if defined(_MSC_VER)
4441__inline
4442#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004443VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004444{
njnc6168192004-11-29 13:54:10 +00004445 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004446 va_list vargs;
4447 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004448#if defined(_MSC_VER)
4449 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4450 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004451 (uintptr_t)format,
4452 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004453 0, 0, 0);
4454#else
sewardjc560fb32010-01-28 15:23:54 +00004455 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4456 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004457 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004458 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004459 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004460#endif
sewardjc560fb32010-01-28 15:23:54 +00004461 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004462 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004463}
4464
fitzhardinge39de4b42003-10-31 07:12:21 +00004465#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00004466
sewardj0ec07f32006-01-12 12:32:32 +00004467
njn3e884182003-04-15 13:03:23 +00004468/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004469 real CPU, calling an arbitary function.
4470
4471 Note that the current ThreadId is inserted as the first argument.
4472 So this call:
4473
4474 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4475
4476 requires f to have this signature:
4477
4478 Word f(Word tid, Word arg1, Word arg2)
4479
4480 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004481
4482 Note that these client requests are not entirely reliable. For example,
4483 if you call a function with them that subsequently calls printf(),
4484 there's a high chance Valgrind will crash. Generally, your prospects of
4485 these working are made higher if the called function does not refer to
4486 any global variables, and does not refer to any libc or other functions
4487 (printf et al). Any kind of entanglement with libc or dynamic linking is
4488 likely to have a bad outcome, for tricky reasons which we've grappled
4489 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004490*/
sewardj0ec07f32006-01-12 12:32:32 +00004491#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00004492 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004493 ({unsigned long _qyy_res; \
4494 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4495 VG_USERREQ__CLIENT_CALL0, \
4496 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004497 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004498 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004499 })
4500
sewardj0ec07f32006-01-12 12:32:32 +00004501#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00004502 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004503 ({unsigned long _qyy_res; \
4504 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4505 VG_USERREQ__CLIENT_CALL1, \
4506 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004507 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004508 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004509 })
4510
sewardj0ec07f32006-01-12 12:32:32 +00004511#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00004512 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004513 ({unsigned long _qyy_res; \
4514 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4515 VG_USERREQ__CLIENT_CALL2, \
4516 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004517 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004518 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004519 })
4520
sewardj0ec07f32006-01-12 12:32:32 +00004521#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00004522 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004523 ({unsigned long _qyy_res; \
4524 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4525 VG_USERREQ__CLIENT_CALL3, \
4526 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004527 _qyy_arg1, _qyy_arg2, \
4528 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004529 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004530 })
4531
4532
nethercote7cc9c232004-01-21 15:08:04 +00004533/* Counts the number of errors that have been recorded by a tool. Nb:
4534 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004535 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004536#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00004537 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004538 ({unsigned int _qyy_res; \
4539 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4540 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00004541 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004542 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00004543 })
4544
njn3ac96952009-07-09 23:35:44 +00004545/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4546 when heap blocks are allocated in order to give accurate results. This
4547 happens automatically for the standard allocator functions such as
4548 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4549 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004550
njn3ac96952009-07-09 23:35:44 +00004551 But if your program uses a custom allocator, this doesn't automatically
4552 happen, and Valgrind will not do as well. For example, if you allocate
4553 superblocks with mmap() and then allocates chunks of the superblocks, all
4554 Valgrind's observations will be at the mmap() level and it won't know that
4555 the chunks should be considered separate entities. In Memcheck's case,
4556 that means you probably won't get heap block overrun detection (because
4557 there won't be redzones marked as unaddressable) and you definitely won't
4558 get any leak detection.
4559
4560 The following client requests allow a custom allocator to be annotated so
4561 that it can be handled accurately by Valgrind.
4562
4563 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4564 by a malloc()-like function. For Memcheck (an illustrative case), this
4565 does two things:
4566
4567 - It records that the block has been allocated. This means any addresses
4568 within the block mentioned in error messages will be
4569 identified as belonging to the block. It also means that if the block
4570 isn't freed it will be detected by the leak checker.
4571
4572 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4573 not set), or addressable and defined (if 'is_zeroed' is set). This
4574 controls how accesses to the block by the program are handled.
4575
4576 'addr' is the start of the usable block (ie. after any
4577 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4578 can apply redzones -- these are blocks of padding at the start and end of
4579 each block. Adding redzones is recommended as it makes it much more likely
4580 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4581 zeroed (or filled with another predictable value), as is the case for
4582 calloc().
4583
4584 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4585 heap block -- that will be used by the client program -- is allocated.
4586 It's best to put it at the outermost level of the allocator if possible;
4587 for example, if you have a function my_alloc() which calls
4588 internal_alloc(), and the client request is put inside internal_alloc(),
4589 stack traces relating to the heap block will contain entries for both
4590 my_alloc() and internal_alloc(), which is probably not what you want.
4591
njnb965efb2009-08-10 07:36:54 +00004592 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4593 custom blocks from within a heap block, B, that has been allocated with
4594 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4595 -- the custom blocks will take precedence.
4596
njn3ac96952009-07-09 23:35:44 +00004597 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4598 Memcheck, it does two things:
4599
4600 - It records that the block has been deallocated. This assumes that the
4601 block was annotated as having been allocated via
4602 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4603
4604 - It marks the block as being unaddressable.
4605
4606 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4607 heap block is deallocated.
4608
4609 In many cases, these two client requests will not be enough to get your
4610 allocator working well with Memcheck. More specifically, if your allocator
4611 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4612 will be necessary to mark the memory as addressable just before the zeroing
4613 occurs, otherwise you'll get a lot of invalid write errors. For example,
4614 you'll need to do this if your allocator recycles freed blocks, but it
4615 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4616 Alternatively, if your allocator reuses freed blocks for allocator-internal
4617 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4618
4619 Really, what's happening is a blurring of the lines between the client
4620 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4621 memory should be considered unaddressable to the client program, but the
4622 allocator knows more than the rest of the client program and so may be able
4623 to safely access it. Extra client requests are necessary for Valgrind to
4624 understand the distinction between the allocator and the rest of the
4625 program.
4626
4627 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4628 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4629
njn32f8d8c2009-07-15 02:31:45 +00004630 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004631*/
sewardj0ec07f32006-01-12 12:32:32 +00004632#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4633 {unsigned int _qzz_res; \
4634 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4635 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004636 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00004637 }
4638
njn32f8d8c2009-07-15 02:31:45 +00004639/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4640 Ignored if addr == 0.
4641*/
sewardj0ec07f32006-01-12 12:32:32 +00004642#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4643 {unsigned int _qzz_res; \
4644 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4645 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004646 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00004647 }
4648
rjwalshbc0bb832004-06-19 18:12:36 +00004649/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004650#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4651 {unsigned int _qzz_res; \
4652 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4653 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004654 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004655 }
4656
4657/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004658#define VALGRIND_DESTROY_MEMPOOL(pool) \
4659 {unsigned int _qzz_res; \
4660 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4661 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004662 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004663 }
4664
4665/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004666#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4667 {unsigned int _qzz_res; \
4668 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4669 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00004670 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004671 }
4672
4673/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004674#define VALGRIND_MEMPOOL_FREE(pool, addr) \
4675 {unsigned int _qzz_res; \
4676 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4677 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00004678 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004679 }
4680
sewardj2c1c9df2006-07-28 00:06:37 +00004681/* Disassociate any pieces outside a particular range. */
4682#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4683 {unsigned int _qzz_res; \
4684 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4685 VG_USERREQ__MEMPOOL_TRIM, \
4686 pool, addr, size, 0, 0); \
4687 }
4688
sewardjc740d762006-10-05 17:59:23 +00004689/* Resize and/or move a piece associated with a memory pool. */
4690#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4691 {unsigned int _qzz_res; \
4692 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4693 VG_USERREQ__MOVE_MEMPOOL, \
4694 poolA, poolB, 0, 0, 0); \
4695 }
4696
4697/* Resize and/or move a piece associated with a memory pool. */
4698#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4699 {unsigned int _qzz_res; \
4700 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4701 VG_USERREQ__MEMPOOL_CHANGE, \
4702 pool, addrA, addrB, size, 0); \
4703 }
4704
4705/* Return 1 if a mempool exists, else 0. */
4706#define VALGRIND_MEMPOOL_EXISTS(pool) \
njn44862972009-02-23 02:08:24 +00004707 __extension__ \
sewardjc740d762006-10-05 17:59:23 +00004708 ({unsigned int _qzz_res; \
4709 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4710 VG_USERREQ__MEMPOOL_EXISTS, \
4711 pool, 0, 0, 0, 0); \
4712 _qzz_res; \
4713 })
4714
rjwalsh0140af52005-06-04 20:42:33 +00004715/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004716#define VALGRIND_STACK_REGISTER(start, end) \
njn44862972009-02-23 02:08:24 +00004717 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004718 ({unsigned int _qzz_res; \
4719 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4720 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004721 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004722 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00004723 })
4724
4725/* Unmark the piece of memory associated with a stack id as being a
4726 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004727#define VALGRIND_STACK_DEREGISTER(id) \
4728 {unsigned int _qzz_res; \
4729 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4730 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004731 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004732 }
4733
4734/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004735#define VALGRIND_STACK_CHANGE(id, start, end) \
4736 {unsigned int _qzz_res; \
4737 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4738 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00004739 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004740 }
4741
sewardjc8259b82009-04-22 22:42:10 +00004742/* Load PDB debug info for Wine PE image_map. */
4743#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4744 {unsigned int _qzz_res; \
4745 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4746 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4747 fd, ptr, total_size, delta, 0); \
4748 }
4749
sewardj5c659622010-08-20 18:22:07 +00004750/* Map a code address to a source file name and line number. buf64
4751 must point to a 64-byte buffer in the caller's address space. The
4752 result will be dumped in there and is guaranteed to be zero
4753 terminated. If no info is found, the first byte is set to zero. */
4754#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
4755 {unsigned int _qzz_res; \
4756 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4757 VG_USERREQ__MAP_IP_TO_SRCLOC, \
4758 addr, buf64, 0, 0, 0); \
4759 }
4760
sewardj0ec07f32006-01-12 12:32:32 +00004761
sewardjf5c1a7f2006-10-17 01:32:48 +00004762#undef PLAT_x86_linux
4763#undef PLAT_amd64_linux
4764#undef PLAT_ppc32_linux
4765#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004766#undef PLAT_arm_linux
sewardjf5c1a7f2006-10-17 01:32:48 +00004767#undef PLAT_ppc32_aix5
4768#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00004769
njn3e884182003-04-15 13:03:23 +00004770#endif /* __VALGRIND_H */