blob: 4896018ea8000a97b41235c23d098087a53c369f [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
bartdea799c2010-10-08 15:54:57 +00001224 that don't support __builtin_frame_address.
sewardjdfa55cf2010-10-06 22:07:06 +00001225*/
bartdea799c2010-10-08 15:54:57 +00001226#if defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001227# define __FRAME_POINTER \
1228 ,"r"(__builtin_frame_address(0))
1229# define VALGRIND_CFI_PROLOGUE \
1230 ".cfi_remember_state\n\t" \
1231 "movq %%rbp, %%r15\n\t" \
1232 "movq %0, %%rbp\n\t" \
1233 ".cfi_def_cfa rbp, 0\n\t"
1234# define VALGRIND_CFI_EPILOGUE \
1235 "movq %%r15, %%rbp\n\t" \
1236 ".cfi_restore_state\n\t"
1237#else
1238# define __FRAME_POINTER
1239# define VALGRIND_CFI_PROLOGUE
1240# define VALGRIND_CFI_EPILOGUE
1241#endif
1242
1243
sewardj0ec07f32006-01-12 12:32:32 +00001244/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1245 long) == 8. */
1246
sewardja07c2e12007-11-09 23:09:50 +00001247/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1248 macros. In order not to trash the stack redzone, we need to drop
1249 %rsp by 128 before the hidden call, and restore afterwards. The
1250 nastyness is that it is only by luck that the stack still appears
1251 to be unwindable during the hidden call - since then the behaviour
1252 of any routine using this macro does not match what the CFI data
1253 says. Sigh.
1254
1255 Why is this important? Imagine that a wrapper has a stack
1256 allocated local, and passes to the hidden call, a pointer to it.
1257 Because gcc does not know about the hidden call, it may allocate
1258 that local in the redzone. Unfortunately the hidden call may then
1259 trash it before it comes to use it. So we must step clear of the
1260 redzone, for the duration of the hidden call, to make it safe.
1261
1262 Probably the same problem afflicts the other redzone-style ABIs too
1263 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1264 self describing (none of this CFI nonsense) so at least messing
1265 with the stack pointer doesn't give a danger of non-unwindable
1266 stack. */
1267
sewardjc8858442006-01-20 15:17:20 +00001268#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001269 do { \
sewardjc8858442006-01-20 15:17:20 +00001270 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001271 volatile unsigned long _argvec[1]; \
1272 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001273 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001274 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001275 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001276 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001277 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1278 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001279 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001280 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001281 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001282 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1283 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001284 ); \
1285 lval = (__typeof__(lval)) _res; \
1286 } while (0)
1287
sewardjc8858442006-01-20 15:17:20 +00001288#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001289 do { \
sewardjc8858442006-01-20 15:17:20 +00001290 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001291 volatile unsigned long _argvec[2]; \
1292 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001293 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001294 _argvec[1] = (unsigned long)(arg1); \
1295 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001296 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001297 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001298 "movq 8(%%rax), %%rdi\n\t" \
1299 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1300 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001301 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001302 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001303 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001304 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1305 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001306 ); \
1307 lval = (__typeof__(lval)) _res; \
1308 } while (0)
1309
sewardjc8858442006-01-20 15:17:20 +00001310#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001311 do { \
sewardjc8858442006-01-20 15:17:20 +00001312 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001313 volatile unsigned long _argvec[3]; \
1314 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001315 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001316 _argvec[1] = (unsigned long)(arg1); \
1317 _argvec[2] = (unsigned long)(arg2); \
1318 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001319 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001320 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001321 "movq 16(%%rax), %%rsi\n\t" \
1322 "movq 8(%%rax), %%rdi\n\t" \
1323 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1324 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001325 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001326 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001327 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001328 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1329 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001330 ); \
1331 lval = (__typeof__(lval)) _res; \
1332 } while (0)
1333
sewardja50f9dc2006-03-11 16:19:14 +00001334#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1335 do { \
1336 volatile OrigFn _orig = (orig); \
1337 volatile unsigned long _argvec[4]; \
1338 volatile unsigned long _res; \
1339 _argvec[0] = (unsigned long)_orig.nraddr; \
1340 _argvec[1] = (unsigned long)(arg1); \
1341 _argvec[2] = (unsigned long)(arg2); \
1342 _argvec[3] = (unsigned long)(arg3); \
1343 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001344 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001345 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001346 "movq 24(%%rax), %%rdx\n\t" \
1347 "movq 16(%%rax), %%rsi\n\t" \
1348 "movq 8(%%rax), %%rdi\n\t" \
1349 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1350 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001351 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001352 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001353 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001354 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1355 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001356 ); \
1357 lval = (__typeof__(lval)) _res; \
1358 } while (0)
1359
1360#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1361 do { \
1362 volatile OrigFn _orig = (orig); \
1363 volatile unsigned long _argvec[5]; \
1364 volatile unsigned long _res; \
1365 _argvec[0] = (unsigned long)_orig.nraddr; \
1366 _argvec[1] = (unsigned long)(arg1); \
1367 _argvec[2] = (unsigned long)(arg2); \
1368 _argvec[3] = (unsigned long)(arg3); \
1369 _argvec[4] = (unsigned long)(arg4); \
1370 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001371 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001372 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001373 "movq 32(%%rax), %%rcx\n\t" \
1374 "movq 24(%%rax), %%rdx\n\t" \
1375 "movq 16(%%rax), %%rsi\n\t" \
1376 "movq 8(%%rax), %%rdi\n\t" \
1377 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1378 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001379 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001380 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001381 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001382 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1383 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001384 ); \
1385 lval = (__typeof__(lval)) _res; \
1386 } while (0)
1387
1388#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1389 do { \
1390 volatile OrigFn _orig = (orig); \
1391 volatile unsigned long _argvec[6]; \
1392 volatile unsigned long _res; \
1393 _argvec[0] = (unsigned long)_orig.nraddr; \
1394 _argvec[1] = (unsigned long)(arg1); \
1395 _argvec[2] = (unsigned long)(arg2); \
1396 _argvec[3] = (unsigned long)(arg3); \
1397 _argvec[4] = (unsigned long)(arg4); \
1398 _argvec[5] = (unsigned long)(arg5); \
1399 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001400 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001401 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001402 "movq 40(%%rax), %%r8\n\t" \
1403 "movq 32(%%rax), %%rcx\n\t" \
1404 "movq 24(%%rax), %%rdx\n\t" \
1405 "movq 16(%%rax), %%rsi\n\t" \
1406 "movq 8(%%rax), %%rdi\n\t" \
1407 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1408 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001409 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001410 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001411 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001412 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1413 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001414 ); \
1415 lval = (__typeof__(lval)) _res; \
1416 } while (0)
1417
1418#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1419 do { \
1420 volatile OrigFn _orig = (orig); \
1421 volatile unsigned long _argvec[7]; \
1422 volatile unsigned long _res; \
1423 _argvec[0] = (unsigned long)_orig.nraddr; \
1424 _argvec[1] = (unsigned long)(arg1); \
1425 _argvec[2] = (unsigned long)(arg2); \
1426 _argvec[3] = (unsigned long)(arg3); \
1427 _argvec[4] = (unsigned long)(arg4); \
1428 _argvec[5] = (unsigned long)(arg5); \
1429 _argvec[6] = (unsigned long)(arg6); \
1430 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001431 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001432 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001433 "movq 48(%%rax), %%r9\n\t" \
1434 "movq 40(%%rax), %%r8\n\t" \
1435 "movq 32(%%rax), %%rcx\n\t" \
1436 "movq 24(%%rax), %%rdx\n\t" \
1437 "movq 16(%%rax), %%rsi\n\t" \
1438 "movq 8(%%rax), %%rdi\n\t" \
1439 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1440 VALGRIND_CALL_NOREDIR_RAX \
bart2823aac2010-09-05 12:10:25 +00001441 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001442 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001443 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001444 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1445 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001446 ); \
1447 lval = (__typeof__(lval)) _res; \
1448 } while (0)
1449
1450#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1451 arg7) \
1452 do { \
1453 volatile OrigFn _orig = (orig); \
1454 volatile unsigned long _argvec[8]; \
1455 volatile unsigned long _res; \
1456 _argvec[0] = (unsigned long)_orig.nraddr; \
1457 _argvec[1] = (unsigned long)(arg1); \
1458 _argvec[2] = (unsigned long)(arg2); \
1459 _argvec[3] = (unsigned long)(arg3); \
1460 _argvec[4] = (unsigned long)(arg4); \
1461 _argvec[5] = (unsigned long)(arg5); \
1462 _argvec[6] = (unsigned long)(arg6); \
1463 _argvec[7] = (unsigned long)(arg7); \
1464 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001465 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001466 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001467 "pushq 56(%%rax)\n\t" \
1468 "movq 48(%%rax), %%r9\n\t" \
1469 "movq 40(%%rax), %%r8\n\t" \
1470 "movq 32(%%rax), %%rcx\n\t" \
1471 "movq 24(%%rax), %%rdx\n\t" \
1472 "movq 16(%%rax), %%rsi\n\t" \
1473 "movq 8(%%rax), %%rdi\n\t" \
1474 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1475 VALGRIND_CALL_NOREDIR_RAX \
1476 "addq $8, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001477 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001478 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001479 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001480 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1481 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001482 ); \
1483 lval = (__typeof__(lval)) _res; \
1484 } while (0)
1485
1486#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1487 arg7,arg8) \
1488 do { \
1489 volatile OrigFn _orig = (orig); \
1490 volatile unsigned long _argvec[9]; \
1491 volatile unsigned long _res; \
1492 _argvec[0] = (unsigned long)_orig.nraddr; \
1493 _argvec[1] = (unsigned long)(arg1); \
1494 _argvec[2] = (unsigned long)(arg2); \
1495 _argvec[3] = (unsigned long)(arg3); \
1496 _argvec[4] = (unsigned long)(arg4); \
1497 _argvec[5] = (unsigned long)(arg5); \
1498 _argvec[6] = (unsigned long)(arg6); \
1499 _argvec[7] = (unsigned long)(arg7); \
1500 _argvec[8] = (unsigned long)(arg8); \
1501 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001502 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001503 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001504 "pushq 64(%%rax)\n\t" \
1505 "pushq 56(%%rax)\n\t" \
1506 "movq 48(%%rax), %%r9\n\t" \
1507 "movq 40(%%rax), %%r8\n\t" \
1508 "movq 32(%%rax), %%rcx\n\t" \
1509 "movq 24(%%rax), %%rdx\n\t" \
1510 "movq 16(%%rax), %%rsi\n\t" \
1511 "movq 8(%%rax), %%rdi\n\t" \
1512 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1513 VALGRIND_CALL_NOREDIR_RAX \
1514 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001515 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001516 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001517 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001518 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1519 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001520 ); \
1521 lval = (__typeof__(lval)) _res; \
1522 } while (0)
1523
1524#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1525 arg7,arg8,arg9) \
1526 do { \
1527 volatile OrigFn _orig = (orig); \
1528 volatile unsigned long _argvec[10]; \
1529 volatile unsigned long _res; \
1530 _argvec[0] = (unsigned long)_orig.nraddr; \
1531 _argvec[1] = (unsigned long)(arg1); \
1532 _argvec[2] = (unsigned long)(arg2); \
1533 _argvec[3] = (unsigned long)(arg3); \
1534 _argvec[4] = (unsigned long)(arg4); \
1535 _argvec[5] = (unsigned long)(arg5); \
1536 _argvec[6] = (unsigned long)(arg6); \
1537 _argvec[7] = (unsigned long)(arg7); \
1538 _argvec[8] = (unsigned long)(arg8); \
1539 _argvec[9] = (unsigned long)(arg9); \
1540 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001541 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001542 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001543 "pushq 72(%%rax)\n\t" \
1544 "pushq 64(%%rax)\n\t" \
1545 "pushq 56(%%rax)\n\t" \
1546 "movq 48(%%rax), %%r9\n\t" \
1547 "movq 40(%%rax), %%r8\n\t" \
1548 "movq 32(%%rax), %%rcx\n\t" \
1549 "movq 24(%%rax), %%rdx\n\t" \
1550 "movq 16(%%rax), %%rsi\n\t" \
1551 "movq 8(%%rax), %%rdi\n\t" \
1552 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1553 VALGRIND_CALL_NOREDIR_RAX \
1554 "addq $24, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001555 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001556 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001557 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001558 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1559 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001560 ); \
1561 lval = (__typeof__(lval)) _res; \
1562 } while (0)
1563
1564#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1565 arg7,arg8,arg9,arg10) \
1566 do { \
1567 volatile OrigFn _orig = (orig); \
1568 volatile unsigned long _argvec[11]; \
1569 volatile unsigned long _res; \
1570 _argvec[0] = (unsigned long)_orig.nraddr; \
1571 _argvec[1] = (unsigned long)(arg1); \
1572 _argvec[2] = (unsigned long)(arg2); \
1573 _argvec[3] = (unsigned long)(arg3); \
1574 _argvec[4] = (unsigned long)(arg4); \
1575 _argvec[5] = (unsigned long)(arg5); \
1576 _argvec[6] = (unsigned long)(arg6); \
1577 _argvec[7] = (unsigned long)(arg7); \
1578 _argvec[8] = (unsigned long)(arg8); \
1579 _argvec[9] = (unsigned long)(arg9); \
1580 _argvec[10] = (unsigned long)(arg10); \
1581 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001582 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001583 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001584 "pushq 80(%%rax)\n\t" \
1585 "pushq 72(%%rax)\n\t" \
1586 "pushq 64(%%rax)\n\t" \
1587 "pushq 56(%%rax)\n\t" \
1588 "movq 48(%%rax), %%r9\n\t" \
1589 "movq 40(%%rax), %%r8\n\t" \
1590 "movq 32(%%rax), %%rcx\n\t" \
1591 "movq 24(%%rax), %%rdx\n\t" \
1592 "movq 16(%%rax), %%rsi\n\t" \
1593 "movq 8(%%rax), %%rdi\n\t" \
1594 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1595 VALGRIND_CALL_NOREDIR_RAX \
1596 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001597 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001598 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001599 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001600 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1601 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001602 ); \
1603 lval = (__typeof__(lval)) _res; \
1604 } while (0)
1605
1606#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1607 arg7,arg8,arg9,arg10,arg11) \
1608 do { \
1609 volatile OrigFn _orig = (orig); \
1610 volatile unsigned long _argvec[12]; \
1611 volatile unsigned long _res; \
1612 _argvec[0] = (unsigned long)_orig.nraddr; \
1613 _argvec[1] = (unsigned long)(arg1); \
1614 _argvec[2] = (unsigned long)(arg2); \
1615 _argvec[3] = (unsigned long)(arg3); \
1616 _argvec[4] = (unsigned long)(arg4); \
1617 _argvec[5] = (unsigned long)(arg5); \
1618 _argvec[6] = (unsigned long)(arg6); \
1619 _argvec[7] = (unsigned long)(arg7); \
1620 _argvec[8] = (unsigned long)(arg8); \
1621 _argvec[9] = (unsigned long)(arg9); \
1622 _argvec[10] = (unsigned long)(arg10); \
1623 _argvec[11] = (unsigned long)(arg11); \
1624 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001625 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001626 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001627 "pushq 88(%%rax)\n\t" \
1628 "pushq 80(%%rax)\n\t" \
1629 "pushq 72(%%rax)\n\t" \
1630 "pushq 64(%%rax)\n\t" \
1631 "pushq 56(%%rax)\n\t" \
1632 "movq 48(%%rax), %%r9\n\t" \
1633 "movq 40(%%rax), %%r8\n\t" \
1634 "movq 32(%%rax), %%rcx\n\t" \
1635 "movq 24(%%rax), %%rdx\n\t" \
1636 "movq 16(%%rax), %%rsi\n\t" \
1637 "movq 8(%%rax), %%rdi\n\t" \
1638 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1639 VALGRIND_CALL_NOREDIR_RAX \
1640 "addq $40, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001641 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001642 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001643 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001644 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1645 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001646 ); \
1647 lval = (__typeof__(lval)) _res; \
1648 } while (0)
1649
1650#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1651 arg7,arg8,arg9,arg10,arg11,arg12) \
1652 do { \
1653 volatile OrigFn _orig = (orig); \
1654 volatile unsigned long _argvec[13]; \
1655 volatile unsigned long _res; \
1656 _argvec[0] = (unsigned long)_orig.nraddr; \
1657 _argvec[1] = (unsigned long)(arg1); \
1658 _argvec[2] = (unsigned long)(arg2); \
1659 _argvec[3] = (unsigned long)(arg3); \
1660 _argvec[4] = (unsigned long)(arg4); \
1661 _argvec[5] = (unsigned long)(arg5); \
1662 _argvec[6] = (unsigned long)(arg6); \
1663 _argvec[7] = (unsigned long)(arg7); \
1664 _argvec[8] = (unsigned long)(arg8); \
1665 _argvec[9] = (unsigned long)(arg9); \
1666 _argvec[10] = (unsigned long)(arg10); \
1667 _argvec[11] = (unsigned long)(arg11); \
1668 _argvec[12] = (unsigned long)(arg12); \
1669 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001670 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001671 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001672 "pushq 96(%%rax)\n\t" \
1673 "pushq 88(%%rax)\n\t" \
1674 "pushq 80(%%rax)\n\t" \
1675 "pushq 72(%%rax)\n\t" \
1676 "pushq 64(%%rax)\n\t" \
1677 "pushq 56(%%rax)\n\t" \
1678 "movq 48(%%rax), %%r9\n\t" \
1679 "movq 40(%%rax), %%r8\n\t" \
1680 "movq 32(%%rax), %%rcx\n\t" \
1681 "movq 24(%%rax), %%rdx\n\t" \
1682 "movq 16(%%rax), %%rsi\n\t" \
1683 "movq 8(%%rax), %%rdi\n\t" \
1684 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1685 VALGRIND_CALL_NOREDIR_RAX \
1686 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001687 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001688 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001689 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001690 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1691 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001692 ); \
1693 lval = (__typeof__(lval)) _res; \
1694 } while (0)
1695
njnf76d27a2009-05-28 01:53:07 +00001696#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001697
sewardjf5c1a7f2006-10-17 01:32:48 +00001698/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001699
sewardjf5c1a7f2006-10-17 01:32:48 +00001700#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001701
sewardjead61df2006-03-12 13:39:15 +00001702/* This is useful for finding out about the on-stack stuff:
1703
1704 extern int f9 ( int,int,int,int,int,int,int,int,int );
1705 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1706 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1707 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1708
1709 int g9 ( void ) {
1710 return f9(11,22,33,44,55,66,77,88,99);
1711 }
1712 int g10 ( void ) {
1713 return f10(11,22,33,44,55,66,77,88,99,110);
1714 }
1715 int g11 ( void ) {
1716 return f11(11,22,33,44,55,66,77,88,99,110,121);
1717 }
1718 int g12 ( void ) {
1719 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1720 }
1721*/
1722
sewardj0ec07f32006-01-12 12:32:32 +00001723/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1724
1725/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001726#define __CALLER_SAVED_REGS \
1727 "lr", "ctr", "xer", \
1728 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1729 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1730 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001731
sewardjead61df2006-03-12 13:39:15 +00001732/* These CALL_FN_ macros assume that on ppc32-linux,
1733 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001734
sewardj38de0992006-01-20 16:46:34 +00001735#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001736 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001737 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001738 volatile unsigned long _argvec[1]; \
1739 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001740 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001741 __asm__ volatile( \
1742 "mr 11,%1\n\t" \
1743 "lwz 11,0(11)\n\t" /* target->r11 */ \
1744 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1745 "mr %0,3" \
1746 : /*out*/ "=r" (_res) \
1747 : /*in*/ "r" (&_argvec[0]) \
1748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1749 ); \
1750 lval = (__typeof__(lval)) _res; \
1751 } while (0)
1752
sewardj38de0992006-01-20 16:46:34 +00001753#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001754 do { \
sewardj38de0992006-01-20 16:46:34 +00001755 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001756 volatile unsigned long _argvec[2]; \
1757 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001758 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001759 _argvec[1] = (unsigned long)arg1; \
1760 __asm__ volatile( \
1761 "mr 11,%1\n\t" \
1762 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1763 "lwz 11,0(11)\n\t" /* target->r11 */ \
1764 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1765 "mr %0,3" \
1766 : /*out*/ "=r" (_res) \
1767 : /*in*/ "r" (&_argvec[0]) \
1768 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1769 ); \
1770 lval = (__typeof__(lval)) _res; \
1771 } while (0)
1772
sewardj38de0992006-01-20 16:46:34 +00001773#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001774 do { \
sewardj38de0992006-01-20 16:46:34 +00001775 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001776 volatile unsigned long _argvec[3]; \
1777 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001778 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001779 _argvec[1] = (unsigned long)arg1; \
1780 _argvec[2] = (unsigned long)arg2; \
1781 __asm__ volatile( \
1782 "mr 11,%1\n\t" \
1783 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1784 "lwz 4,8(11)\n\t" \
1785 "lwz 11,0(11)\n\t" /* target->r11 */ \
1786 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1787 "mr %0,3" \
1788 : /*out*/ "=r" (_res) \
1789 : /*in*/ "r" (&_argvec[0]) \
1790 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1791 ); \
1792 lval = (__typeof__(lval)) _res; \
1793 } while (0)
1794
sewardjead61df2006-03-12 13:39:15 +00001795#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1796 do { \
1797 volatile OrigFn _orig = (orig); \
1798 volatile unsigned long _argvec[4]; \
1799 volatile unsigned long _res; \
1800 _argvec[0] = (unsigned long)_orig.nraddr; \
1801 _argvec[1] = (unsigned long)arg1; \
1802 _argvec[2] = (unsigned long)arg2; \
1803 _argvec[3] = (unsigned long)arg3; \
1804 __asm__ volatile( \
1805 "mr 11,%1\n\t" \
1806 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1807 "lwz 4,8(11)\n\t" \
1808 "lwz 5,12(11)\n\t" \
1809 "lwz 11,0(11)\n\t" /* target->r11 */ \
1810 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1811 "mr %0,3" \
1812 : /*out*/ "=r" (_res) \
1813 : /*in*/ "r" (&_argvec[0]) \
1814 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1815 ); \
1816 lval = (__typeof__(lval)) _res; \
1817 } while (0)
1818
1819#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1820 do { \
1821 volatile OrigFn _orig = (orig); \
1822 volatile unsigned long _argvec[5]; \
1823 volatile unsigned long _res; \
1824 _argvec[0] = (unsigned long)_orig.nraddr; \
1825 _argvec[1] = (unsigned long)arg1; \
1826 _argvec[2] = (unsigned long)arg2; \
1827 _argvec[3] = (unsigned long)arg3; \
1828 _argvec[4] = (unsigned long)arg4; \
1829 __asm__ volatile( \
1830 "mr 11,%1\n\t" \
1831 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1832 "lwz 4,8(11)\n\t" \
1833 "lwz 5,12(11)\n\t" \
1834 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1835 "lwz 11,0(11)\n\t" /* target->r11 */ \
1836 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1837 "mr %0,3" \
1838 : /*out*/ "=r" (_res) \
1839 : /*in*/ "r" (&_argvec[0]) \
1840 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1841 ); \
1842 lval = (__typeof__(lval)) _res; \
1843 } while (0)
1844
1845#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1846 do { \
1847 volatile OrigFn _orig = (orig); \
1848 volatile unsigned long _argvec[6]; \
1849 volatile unsigned long _res; \
1850 _argvec[0] = (unsigned long)_orig.nraddr; \
1851 _argvec[1] = (unsigned long)arg1; \
1852 _argvec[2] = (unsigned long)arg2; \
1853 _argvec[3] = (unsigned long)arg3; \
1854 _argvec[4] = (unsigned long)arg4; \
1855 _argvec[5] = (unsigned long)arg5; \
1856 __asm__ volatile( \
1857 "mr 11,%1\n\t" \
1858 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1859 "lwz 4,8(11)\n\t" \
1860 "lwz 5,12(11)\n\t" \
1861 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1862 "lwz 7,20(11)\n\t" \
1863 "lwz 11,0(11)\n\t" /* target->r11 */ \
1864 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1865 "mr %0,3" \
1866 : /*out*/ "=r" (_res) \
1867 : /*in*/ "r" (&_argvec[0]) \
1868 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1869 ); \
1870 lval = (__typeof__(lval)) _res; \
1871 } while (0)
1872
1873#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1874 do { \
1875 volatile OrigFn _orig = (orig); \
1876 volatile unsigned long _argvec[7]; \
1877 volatile unsigned long _res; \
1878 _argvec[0] = (unsigned long)_orig.nraddr; \
1879 _argvec[1] = (unsigned long)arg1; \
1880 _argvec[2] = (unsigned long)arg2; \
1881 _argvec[3] = (unsigned long)arg3; \
1882 _argvec[4] = (unsigned long)arg4; \
1883 _argvec[5] = (unsigned long)arg5; \
1884 _argvec[6] = (unsigned long)arg6; \
1885 __asm__ volatile( \
1886 "mr 11,%1\n\t" \
1887 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1888 "lwz 4,8(11)\n\t" \
1889 "lwz 5,12(11)\n\t" \
1890 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1891 "lwz 7,20(11)\n\t" \
1892 "lwz 8,24(11)\n\t" \
1893 "lwz 11,0(11)\n\t" /* target->r11 */ \
1894 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1895 "mr %0,3" \
1896 : /*out*/ "=r" (_res) \
1897 : /*in*/ "r" (&_argvec[0]) \
1898 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1899 ); \
1900 lval = (__typeof__(lval)) _res; \
1901 } while (0)
1902
1903#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1904 arg7) \
1905 do { \
1906 volatile OrigFn _orig = (orig); \
1907 volatile unsigned long _argvec[8]; \
1908 volatile unsigned long _res; \
1909 _argvec[0] = (unsigned long)_orig.nraddr; \
1910 _argvec[1] = (unsigned long)arg1; \
1911 _argvec[2] = (unsigned long)arg2; \
1912 _argvec[3] = (unsigned long)arg3; \
1913 _argvec[4] = (unsigned long)arg4; \
1914 _argvec[5] = (unsigned long)arg5; \
1915 _argvec[6] = (unsigned long)arg6; \
1916 _argvec[7] = (unsigned long)arg7; \
1917 __asm__ volatile( \
1918 "mr 11,%1\n\t" \
1919 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1920 "lwz 4,8(11)\n\t" \
1921 "lwz 5,12(11)\n\t" \
1922 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1923 "lwz 7,20(11)\n\t" \
1924 "lwz 8,24(11)\n\t" \
1925 "lwz 9,28(11)\n\t" \
1926 "lwz 11,0(11)\n\t" /* target->r11 */ \
1927 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1928 "mr %0,3" \
1929 : /*out*/ "=r" (_res) \
1930 : /*in*/ "r" (&_argvec[0]) \
1931 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1932 ); \
1933 lval = (__typeof__(lval)) _res; \
1934 } while (0)
1935
1936#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1937 arg7,arg8) \
1938 do { \
1939 volatile OrigFn _orig = (orig); \
1940 volatile unsigned long _argvec[9]; \
1941 volatile unsigned long _res; \
1942 _argvec[0] = (unsigned long)_orig.nraddr; \
1943 _argvec[1] = (unsigned long)arg1; \
1944 _argvec[2] = (unsigned long)arg2; \
1945 _argvec[3] = (unsigned long)arg3; \
1946 _argvec[4] = (unsigned long)arg4; \
1947 _argvec[5] = (unsigned long)arg5; \
1948 _argvec[6] = (unsigned long)arg6; \
1949 _argvec[7] = (unsigned long)arg7; \
1950 _argvec[8] = (unsigned long)arg8; \
1951 __asm__ volatile( \
1952 "mr 11,%1\n\t" \
1953 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1954 "lwz 4,8(11)\n\t" \
1955 "lwz 5,12(11)\n\t" \
1956 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1957 "lwz 7,20(11)\n\t" \
1958 "lwz 8,24(11)\n\t" \
1959 "lwz 9,28(11)\n\t" \
1960 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1961 "lwz 11,0(11)\n\t" /* target->r11 */ \
1962 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1963 "mr %0,3" \
1964 : /*out*/ "=r" (_res) \
1965 : /*in*/ "r" (&_argvec[0]) \
1966 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1967 ); \
1968 lval = (__typeof__(lval)) _res; \
1969 } while (0)
1970
1971#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1972 arg7,arg8,arg9) \
1973 do { \
1974 volatile OrigFn _orig = (orig); \
1975 volatile unsigned long _argvec[10]; \
1976 volatile unsigned long _res; \
1977 _argvec[0] = (unsigned long)_orig.nraddr; \
1978 _argvec[1] = (unsigned long)arg1; \
1979 _argvec[2] = (unsigned long)arg2; \
1980 _argvec[3] = (unsigned long)arg3; \
1981 _argvec[4] = (unsigned long)arg4; \
1982 _argvec[5] = (unsigned long)arg5; \
1983 _argvec[6] = (unsigned long)arg6; \
1984 _argvec[7] = (unsigned long)arg7; \
1985 _argvec[8] = (unsigned long)arg8; \
1986 _argvec[9] = (unsigned long)arg9; \
1987 __asm__ volatile( \
1988 "mr 11,%1\n\t" \
1989 "addi 1,1,-16\n\t" \
1990 /* arg9 */ \
1991 "lwz 3,36(11)\n\t" \
1992 "stw 3,8(1)\n\t" \
1993 /* args1-8 */ \
1994 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1995 "lwz 4,8(11)\n\t" \
1996 "lwz 5,12(11)\n\t" \
1997 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1998 "lwz 7,20(11)\n\t" \
1999 "lwz 8,24(11)\n\t" \
2000 "lwz 9,28(11)\n\t" \
2001 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2002 "lwz 11,0(11)\n\t" /* target->r11 */ \
2003 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2004 "addi 1,1,16\n\t" \
2005 "mr %0,3" \
2006 : /*out*/ "=r" (_res) \
2007 : /*in*/ "r" (&_argvec[0]) \
2008 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2009 ); \
2010 lval = (__typeof__(lval)) _res; \
2011 } while (0)
2012
2013#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2014 arg7,arg8,arg9,arg10) \
2015 do { \
2016 volatile OrigFn _orig = (orig); \
2017 volatile unsigned long _argvec[11]; \
2018 volatile unsigned long _res; \
2019 _argvec[0] = (unsigned long)_orig.nraddr; \
2020 _argvec[1] = (unsigned long)arg1; \
2021 _argvec[2] = (unsigned long)arg2; \
2022 _argvec[3] = (unsigned long)arg3; \
2023 _argvec[4] = (unsigned long)arg4; \
2024 _argvec[5] = (unsigned long)arg5; \
2025 _argvec[6] = (unsigned long)arg6; \
2026 _argvec[7] = (unsigned long)arg7; \
2027 _argvec[8] = (unsigned long)arg8; \
2028 _argvec[9] = (unsigned long)arg9; \
2029 _argvec[10] = (unsigned long)arg10; \
2030 __asm__ volatile( \
2031 "mr 11,%1\n\t" \
2032 "addi 1,1,-16\n\t" \
2033 /* arg10 */ \
2034 "lwz 3,40(11)\n\t" \
2035 "stw 3,12(1)\n\t" \
2036 /* arg9 */ \
2037 "lwz 3,36(11)\n\t" \
2038 "stw 3,8(1)\n\t" \
2039 /* args1-8 */ \
2040 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2041 "lwz 4,8(11)\n\t" \
2042 "lwz 5,12(11)\n\t" \
2043 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2044 "lwz 7,20(11)\n\t" \
2045 "lwz 8,24(11)\n\t" \
2046 "lwz 9,28(11)\n\t" \
2047 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2048 "lwz 11,0(11)\n\t" /* target->r11 */ \
2049 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2050 "addi 1,1,16\n\t" \
2051 "mr %0,3" \
2052 : /*out*/ "=r" (_res) \
2053 : /*in*/ "r" (&_argvec[0]) \
2054 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2055 ); \
2056 lval = (__typeof__(lval)) _res; \
2057 } while (0)
2058
2059#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2060 arg7,arg8,arg9,arg10,arg11) \
2061 do { \
2062 volatile OrigFn _orig = (orig); \
2063 volatile unsigned long _argvec[12]; \
2064 volatile unsigned long _res; \
2065 _argvec[0] = (unsigned long)_orig.nraddr; \
2066 _argvec[1] = (unsigned long)arg1; \
2067 _argvec[2] = (unsigned long)arg2; \
2068 _argvec[3] = (unsigned long)arg3; \
2069 _argvec[4] = (unsigned long)arg4; \
2070 _argvec[5] = (unsigned long)arg5; \
2071 _argvec[6] = (unsigned long)arg6; \
2072 _argvec[7] = (unsigned long)arg7; \
2073 _argvec[8] = (unsigned long)arg8; \
2074 _argvec[9] = (unsigned long)arg9; \
2075 _argvec[10] = (unsigned long)arg10; \
2076 _argvec[11] = (unsigned long)arg11; \
2077 __asm__ volatile( \
2078 "mr 11,%1\n\t" \
2079 "addi 1,1,-32\n\t" \
2080 /* arg11 */ \
2081 "lwz 3,44(11)\n\t" \
2082 "stw 3,16(1)\n\t" \
2083 /* arg10 */ \
2084 "lwz 3,40(11)\n\t" \
2085 "stw 3,12(1)\n\t" \
2086 /* arg9 */ \
2087 "lwz 3,36(11)\n\t" \
2088 "stw 3,8(1)\n\t" \
2089 /* args1-8 */ \
2090 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2091 "lwz 4,8(11)\n\t" \
2092 "lwz 5,12(11)\n\t" \
2093 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2094 "lwz 7,20(11)\n\t" \
2095 "lwz 8,24(11)\n\t" \
2096 "lwz 9,28(11)\n\t" \
2097 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2098 "lwz 11,0(11)\n\t" /* target->r11 */ \
2099 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2100 "addi 1,1,32\n\t" \
2101 "mr %0,3" \
2102 : /*out*/ "=r" (_res) \
2103 : /*in*/ "r" (&_argvec[0]) \
2104 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2105 ); \
2106 lval = (__typeof__(lval)) _res; \
2107 } while (0)
2108
2109#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2110 arg7,arg8,arg9,arg10,arg11,arg12) \
2111 do { \
2112 volatile OrigFn _orig = (orig); \
2113 volatile unsigned long _argvec[13]; \
2114 volatile unsigned long _res; \
2115 _argvec[0] = (unsigned long)_orig.nraddr; \
2116 _argvec[1] = (unsigned long)arg1; \
2117 _argvec[2] = (unsigned long)arg2; \
2118 _argvec[3] = (unsigned long)arg3; \
2119 _argvec[4] = (unsigned long)arg4; \
2120 _argvec[5] = (unsigned long)arg5; \
2121 _argvec[6] = (unsigned long)arg6; \
2122 _argvec[7] = (unsigned long)arg7; \
2123 _argvec[8] = (unsigned long)arg8; \
2124 _argvec[9] = (unsigned long)arg9; \
2125 _argvec[10] = (unsigned long)arg10; \
2126 _argvec[11] = (unsigned long)arg11; \
2127 _argvec[12] = (unsigned long)arg12; \
2128 __asm__ volatile( \
2129 "mr 11,%1\n\t" \
2130 "addi 1,1,-32\n\t" \
2131 /* arg12 */ \
2132 "lwz 3,48(11)\n\t" \
2133 "stw 3,20(1)\n\t" \
2134 /* arg11 */ \
2135 "lwz 3,44(11)\n\t" \
2136 "stw 3,16(1)\n\t" \
2137 /* arg10 */ \
2138 "lwz 3,40(11)\n\t" \
2139 "stw 3,12(1)\n\t" \
2140 /* arg9 */ \
2141 "lwz 3,36(11)\n\t" \
2142 "stw 3,8(1)\n\t" \
2143 /* args1-8 */ \
2144 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2145 "lwz 4,8(11)\n\t" \
2146 "lwz 5,12(11)\n\t" \
2147 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2148 "lwz 7,20(11)\n\t" \
2149 "lwz 8,24(11)\n\t" \
2150 "lwz 9,28(11)\n\t" \
2151 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2152 "lwz 11,0(11)\n\t" /* target->r11 */ \
2153 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2154 "addi 1,1,32\n\t" \
2155 "mr %0,3" \
2156 : /*out*/ "=r" (_res) \
2157 : /*in*/ "r" (&_argvec[0]) \
2158 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2159 ); \
2160 lval = (__typeof__(lval)) _res; \
2161 } while (0)
2162
sewardjf5c1a7f2006-10-17 01:32:48 +00002163#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002164
sewardjf5c1a7f2006-10-17 01:32:48 +00002165/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002166
sewardjf5c1a7f2006-10-17 01:32:48 +00002167#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002168
2169/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2170
2171/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002172#define __CALLER_SAVED_REGS \
2173 "lr", "ctr", "xer", \
2174 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2175 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2176 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002177
2178/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2179 long) == 8. */
2180
sewardjd68ac3e2006-01-20 14:31:57 +00002181#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002182 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002183 volatile OrigFn _orig = (orig); \
2184 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002185 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002186 /* _argvec[0] holds current r2 across the call */ \
2187 _argvec[1] = (unsigned long)_orig.r2; \
2188 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002189 __asm__ volatile( \
2190 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002191 "std 2,-16(11)\n\t" /* save tocptr */ \
2192 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2193 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002194 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2195 "mr 11,%1\n\t" \
2196 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002197 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002198 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002199 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002200 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2201 ); \
2202 lval = (__typeof__(lval)) _res; \
2203 } while (0)
2204
sewardjd68ac3e2006-01-20 14:31:57 +00002205#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002206 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002207 volatile OrigFn _orig = (orig); \
2208 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002209 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002210 /* _argvec[0] holds current r2 across the call */ \
2211 _argvec[1] = (unsigned long)_orig.r2; \
2212 _argvec[2] = (unsigned long)_orig.nraddr; \
2213 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002214 __asm__ volatile( \
2215 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002216 "std 2,-16(11)\n\t" /* save tocptr */ \
2217 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2218 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2219 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002220 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2221 "mr 11,%1\n\t" \
2222 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002223 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002224 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002225 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002226 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2227 ); \
2228 lval = (__typeof__(lval)) _res; \
2229 } while (0)
2230
sewardjd68ac3e2006-01-20 14:31:57 +00002231#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002232 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002233 volatile OrigFn _orig = (orig); \
2234 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002235 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002236 /* _argvec[0] holds current r2 across the call */ \
2237 _argvec[1] = (unsigned long)_orig.r2; \
2238 _argvec[2] = (unsigned long)_orig.nraddr; \
2239 _argvec[2+1] = (unsigned long)arg1; \
2240 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002241 __asm__ volatile( \
2242 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002243 "std 2,-16(11)\n\t" /* save tocptr */ \
2244 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2245 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002246 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002247 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002248 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2249 "mr 11,%1\n\t" \
2250 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002251 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002252 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002253 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002254 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2255 ); \
2256 lval = (__typeof__(lval)) _res; \
2257 } while (0)
2258
sewardjcd636392006-03-12 16:48:14 +00002259#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2260 do { \
2261 volatile OrigFn _orig = (orig); \
2262 volatile unsigned long _argvec[3+3]; \
2263 volatile unsigned long _res; \
2264 /* _argvec[0] holds current r2 across the call */ \
2265 _argvec[1] = (unsigned long)_orig.r2; \
2266 _argvec[2] = (unsigned long)_orig.nraddr; \
2267 _argvec[2+1] = (unsigned long)arg1; \
2268 _argvec[2+2] = (unsigned long)arg2; \
2269 _argvec[2+3] = (unsigned long)arg3; \
2270 __asm__ volatile( \
2271 "mr 11,%1\n\t" \
2272 "std 2,-16(11)\n\t" /* save tocptr */ \
2273 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2274 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2275 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2276 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2277 "ld 11, 0(11)\n\t" /* target->r11 */ \
2278 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2279 "mr 11,%1\n\t" \
2280 "mr %0,3\n\t" \
2281 "ld 2,-16(11)" /* restore tocptr */ \
2282 : /*out*/ "=r" (_res) \
2283 : /*in*/ "r" (&_argvec[2]) \
2284 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2285 ); \
2286 lval = (__typeof__(lval)) _res; \
2287 } while (0)
2288
2289#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2290 do { \
2291 volatile OrigFn _orig = (orig); \
2292 volatile unsigned long _argvec[3+4]; \
2293 volatile unsigned long _res; \
2294 /* _argvec[0] holds current r2 across the call */ \
2295 _argvec[1] = (unsigned long)_orig.r2; \
2296 _argvec[2] = (unsigned long)_orig.nraddr; \
2297 _argvec[2+1] = (unsigned long)arg1; \
2298 _argvec[2+2] = (unsigned long)arg2; \
2299 _argvec[2+3] = (unsigned long)arg3; \
2300 _argvec[2+4] = (unsigned long)arg4; \
2301 __asm__ volatile( \
2302 "mr 11,%1\n\t" \
2303 "std 2,-16(11)\n\t" /* save tocptr */ \
2304 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2305 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2306 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2307 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2308 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2309 "ld 11, 0(11)\n\t" /* target->r11 */ \
2310 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2311 "mr 11,%1\n\t" \
2312 "mr %0,3\n\t" \
2313 "ld 2,-16(11)" /* restore tocptr */ \
2314 : /*out*/ "=r" (_res) \
2315 : /*in*/ "r" (&_argvec[2]) \
2316 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2317 ); \
2318 lval = (__typeof__(lval)) _res; \
2319 } while (0)
2320
2321#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2322 do { \
2323 volatile OrigFn _orig = (orig); \
2324 volatile unsigned long _argvec[3+5]; \
2325 volatile unsigned long _res; \
2326 /* _argvec[0] holds current r2 across the call */ \
2327 _argvec[1] = (unsigned long)_orig.r2; \
2328 _argvec[2] = (unsigned long)_orig.nraddr; \
2329 _argvec[2+1] = (unsigned long)arg1; \
2330 _argvec[2+2] = (unsigned long)arg2; \
2331 _argvec[2+3] = (unsigned long)arg3; \
2332 _argvec[2+4] = (unsigned long)arg4; \
2333 _argvec[2+5] = (unsigned long)arg5; \
2334 __asm__ volatile( \
2335 "mr 11,%1\n\t" \
2336 "std 2,-16(11)\n\t" /* save tocptr */ \
2337 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2338 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2339 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2340 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2341 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2342 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2343 "ld 11, 0(11)\n\t" /* target->r11 */ \
2344 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2345 "mr 11,%1\n\t" \
2346 "mr %0,3\n\t" \
2347 "ld 2,-16(11)" /* restore tocptr */ \
2348 : /*out*/ "=r" (_res) \
2349 : /*in*/ "r" (&_argvec[2]) \
2350 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2351 ); \
2352 lval = (__typeof__(lval)) _res; \
2353 } while (0)
2354
2355#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2356 do { \
2357 volatile OrigFn _orig = (orig); \
2358 volatile unsigned long _argvec[3+6]; \
2359 volatile unsigned long _res; \
2360 /* _argvec[0] holds current r2 across the call */ \
2361 _argvec[1] = (unsigned long)_orig.r2; \
2362 _argvec[2] = (unsigned long)_orig.nraddr; \
2363 _argvec[2+1] = (unsigned long)arg1; \
2364 _argvec[2+2] = (unsigned long)arg2; \
2365 _argvec[2+3] = (unsigned long)arg3; \
2366 _argvec[2+4] = (unsigned long)arg4; \
2367 _argvec[2+5] = (unsigned long)arg5; \
2368 _argvec[2+6] = (unsigned long)arg6; \
2369 __asm__ volatile( \
2370 "mr 11,%1\n\t" \
2371 "std 2,-16(11)\n\t" /* save tocptr */ \
2372 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2373 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2374 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2375 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2376 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2377 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2378 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2379 "ld 11, 0(11)\n\t" /* target->r11 */ \
2380 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2381 "mr 11,%1\n\t" \
2382 "mr %0,3\n\t" \
2383 "ld 2,-16(11)" /* restore tocptr */ \
2384 : /*out*/ "=r" (_res) \
2385 : /*in*/ "r" (&_argvec[2]) \
2386 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2387 ); \
2388 lval = (__typeof__(lval)) _res; \
2389 } while (0)
2390
2391#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2392 arg7) \
2393 do { \
2394 volatile OrigFn _orig = (orig); \
2395 volatile unsigned long _argvec[3+7]; \
2396 volatile unsigned long _res; \
2397 /* _argvec[0] holds current r2 across the call */ \
2398 _argvec[1] = (unsigned long)_orig.r2; \
2399 _argvec[2] = (unsigned long)_orig.nraddr; \
2400 _argvec[2+1] = (unsigned long)arg1; \
2401 _argvec[2+2] = (unsigned long)arg2; \
2402 _argvec[2+3] = (unsigned long)arg3; \
2403 _argvec[2+4] = (unsigned long)arg4; \
2404 _argvec[2+5] = (unsigned long)arg5; \
2405 _argvec[2+6] = (unsigned long)arg6; \
2406 _argvec[2+7] = (unsigned long)arg7; \
2407 __asm__ volatile( \
2408 "mr 11,%1\n\t" \
2409 "std 2,-16(11)\n\t" /* save tocptr */ \
2410 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2411 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2412 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2413 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2414 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2415 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2416 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2417 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2418 "ld 11, 0(11)\n\t" /* target->r11 */ \
2419 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2420 "mr 11,%1\n\t" \
2421 "mr %0,3\n\t" \
2422 "ld 2,-16(11)" /* restore tocptr */ \
2423 : /*out*/ "=r" (_res) \
2424 : /*in*/ "r" (&_argvec[2]) \
2425 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2426 ); \
2427 lval = (__typeof__(lval)) _res; \
2428 } while (0)
2429
2430#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2431 arg7,arg8) \
2432 do { \
2433 volatile OrigFn _orig = (orig); \
2434 volatile unsigned long _argvec[3+8]; \
2435 volatile unsigned long _res; \
2436 /* _argvec[0] holds current r2 across the call */ \
2437 _argvec[1] = (unsigned long)_orig.r2; \
2438 _argvec[2] = (unsigned long)_orig.nraddr; \
2439 _argvec[2+1] = (unsigned long)arg1; \
2440 _argvec[2+2] = (unsigned long)arg2; \
2441 _argvec[2+3] = (unsigned long)arg3; \
2442 _argvec[2+4] = (unsigned long)arg4; \
2443 _argvec[2+5] = (unsigned long)arg5; \
2444 _argvec[2+6] = (unsigned long)arg6; \
2445 _argvec[2+7] = (unsigned long)arg7; \
2446 _argvec[2+8] = (unsigned long)arg8; \
2447 __asm__ volatile( \
2448 "mr 11,%1\n\t" \
2449 "std 2,-16(11)\n\t" /* save tocptr */ \
2450 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2451 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2452 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2453 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2454 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2455 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2456 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2457 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2458 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2459 "ld 11, 0(11)\n\t" /* target->r11 */ \
2460 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2461 "mr 11,%1\n\t" \
2462 "mr %0,3\n\t" \
2463 "ld 2,-16(11)" /* restore tocptr */ \
2464 : /*out*/ "=r" (_res) \
2465 : /*in*/ "r" (&_argvec[2]) \
2466 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2467 ); \
2468 lval = (__typeof__(lval)) _res; \
2469 } while (0)
2470
2471#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2472 arg7,arg8,arg9) \
2473 do { \
2474 volatile OrigFn _orig = (orig); \
2475 volatile unsigned long _argvec[3+9]; \
2476 volatile unsigned long _res; \
2477 /* _argvec[0] holds current r2 across the call */ \
2478 _argvec[1] = (unsigned long)_orig.r2; \
2479 _argvec[2] = (unsigned long)_orig.nraddr; \
2480 _argvec[2+1] = (unsigned long)arg1; \
2481 _argvec[2+2] = (unsigned long)arg2; \
2482 _argvec[2+3] = (unsigned long)arg3; \
2483 _argvec[2+4] = (unsigned long)arg4; \
2484 _argvec[2+5] = (unsigned long)arg5; \
2485 _argvec[2+6] = (unsigned long)arg6; \
2486 _argvec[2+7] = (unsigned long)arg7; \
2487 _argvec[2+8] = (unsigned long)arg8; \
2488 _argvec[2+9] = (unsigned long)arg9; \
2489 __asm__ volatile( \
2490 "mr 11,%1\n\t" \
2491 "std 2,-16(11)\n\t" /* save tocptr */ \
2492 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2493 "addi 1,1,-128\n\t" /* expand stack frame */ \
2494 /* arg9 */ \
2495 "ld 3,72(11)\n\t" \
2496 "std 3,112(1)\n\t" \
2497 /* args1-8 */ \
2498 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2499 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2500 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2501 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2502 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2503 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2504 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2505 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2506 "ld 11, 0(11)\n\t" /* target->r11 */ \
2507 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2508 "mr 11,%1\n\t" \
2509 "mr %0,3\n\t" \
2510 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2511 "addi 1,1,128" /* restore frame */ \
2512 : /*out*/ "=r" (_res) \
2513 : /*in*/ "r" (&_argvec[2]) \
2514 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2515 ); \
2516 lval = (__typeof__(lval)) _res; \
2517 } while (0)
2518
2519#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2520 arg7,arg8,arg9,arg10) \
2521 do { \
2522 volatile OrigFn _orig = (orig); \
2523 volatile unsigned long _argvec[3+10]; \
2524 volatile unsigned long _res; \
2525 /* _argvec[0] holds current r2 across the call */ \
2526 _argvec[1] = (unsigned long)_orig.r2; \
2527 _argvec[2] = (unsigned long)_orig.nraddr; \
2528 _argvec[2+1] = (unsigned long)arg1; \
2529 _argvec[2+2] = (unsigned long)arg2; \
2530 _argvec[2+3] = (unsigned long)arg3; \
2531 _argvec[2+4] = (unsigned long)arg4; \
2532 _argvec[2+5] = (unsigned long)arg5; \
2533 _argvec[2+6] = (unsigned long)arg6; \
2534 _argvec[2+7] = (unsigned long)arg7; \
2535 _argvec[2+8] = (unsigned long)arg8; \
2536 _argvec[2+9] = (unsigned long)arg9; \
2537 _argvec[2+10] = (unsigned long)arg10; \
2538 __asm__ volatile( \
2539 "mr 11,%1\n\t" \
2540 "std 2,-16(11)\n\t" /* save tocptr */ \
2541 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2542 "addi 1,1,-128\n\t" /* expand stack frame */ \
2543 /* arg10 */ \
2544 "ld 3,80(11)\n\t" \
2545 "std 3,120(1)\n\t" \
2546 /* arg9 */ \
2547 "ld 3,72(11)\n\t" \
2548 "std 3,112(1)\n\t" \
2549 /* args1-8 */ \
2550 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2551 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2552 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2553 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2554 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2555 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2556 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2557 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2558 "ld 11, 0(11)\n\t" /* target->r11 */ \
2559 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2560 "mr 11,%1\n\t" \
2561 "mr %0,3\n\t" \
2562 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2563 "addi 1,1,128" /* restore frame */ \
2564 : /*out*/ "=r" (_res) \
2565 : /*in*/ "r" (&_argvec[2]) \
2566 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2567 ); \
2568 lval = (__typeof__(lval)) _res; \
2569 } while (0)
2570
2571#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2572 arg7,arg8,arg9,arg10,arg11) \
2573 do { \
2574 volatile OrigFn _orig = (orig); \
2575 volatile unsigned long _argvec[3+11]; \
2576 volatile unsigned long _res; \
2577 /* _argvec[0] holds current r2 across the call */ \
2578 _argvec[1] = (unsigned long)_orig.r2; \
2579 _argvec[2] = (unsigned long)_orig.nraddr; \
2580 _argvec[2+1] = (unsigned long)arg1; \
2581 _argvec[2+2] = (unsigned long)arg2; \
2582 _argvec[2+3] = (unsigned long)arg3; \
2583 _argvec[2+4] = (unsigned long)arg4; \
2584 _argvec[2+5] = (unsigned long)arg5; \
2585 _argvec[2+6] = (unsigned long)arg6; \
2586 _argvec[2+7] = (unsigned long)arg7; \
2587 _argvec[2+8] = (unsigned long)arg8; \
2588 _argvec[2+9] = (unsigned long)arg9; \
2589 _argvec[2+10] = (unsigned long)arg10; \
2590 _argvec[2+11] = (unsigned long)arg11; \
2591 __asm__ volatile( \
2592 "mr 11,%1\n\t" \
2593 "std 2,-16(11)\n\t" /* save tocptr */ \
2594 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2595 "addi 1,1,-144\n\t" /* expand stack frame */ \
2596 /* arg11 */ \
2597 "ld 3,88(11)\n\t" \
2598 "std 3,128(1)\n\t" \
2599 /* arg10 */ \
2600 "ld 3,80(11)\n\t" \
2601 "std 3,120(1)\n\t" \
2602 /* arg9 */ \
2603 "ld 3,72(11)\n\t" \
2604 "std 3,112(1)\n\t" \
2605 /* args1-8 */ \
2606 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2607 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2608 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2609 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2610 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2611 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2612 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2613 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2614 "ld 11, 0(11)\n\t" /* target->r11 */ \
2615 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2616 "mr 11,%1\n\t" \
2617 "mr %0,3\n\t" \
2618 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2619 "addi 1,1,144" /* restore frame */ \
2620 : /*out*/ "=r" (_res) \
2621 : /*in*/ "r" (&_argvec[2]) \
2622 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2623 ); \
2624 lval = (__typeof__(lval)) _res; \
2625 } while (0)
2626
2627#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2628 arg7,arg8,arg9,arg10,arg11,arg12) \
2629 do { \
2630 volatile OrigFn _orig = (orig); \
2631 volatile unsigned long _argvec[3+12]; \
2632 volatile unsigned long _res; \
2633 /* _argvec[0] holds current r2 across the call */ \
2634 _argvec[1] = (unsigned long)_orig.r2; \
2635 _argvec[2] = (unsigned long)_orig.nraddr; \
2636 _argvec[2+1] = (unsigned long)arg1; \
2637 _argvec[2+2] = (unsigned long)arg2; \
2638 _argvec[2+3] = (unsigned long)arg3; \
2639 _argvec[2+4] = (unsigned long)arg4; \
2640 _argvec[2+5] = (unsigned long)arg5; \
2641 _argvec[2+6] = (unsigned long)arg6; \
2642 _argvec[2+7] = (unsigned long)arg7; \
2643 _argvec[2+8] = (unsigned long)arg8; \
2644 _argvec[2+9] = (unsigned long)arg9; \
2645 _argvec[2+10] = (unsigned long)arg10; \
2646 _argvec[2+11] = (unsigned long)arg11; \
2647 _argvec[2+12] = (unsigned long)arg12; \
2648 __asm__ volatile( \
2649 "mr 11,%1\n\t" \
2650 "std 2,-16(11)\n\t" /* save tocptr */ \
2651 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2652 "addi 1,1,-144\n\t" /* expand stack frame */ \
2653 /* arg12 */ \
2654 "ld 3,96(11)\n\t" \
2655 "std 3,136(1)\n\t" \
2656 /* arg11 */ \
2657 "ld 3,88(11)\n\t" \
2658 "std 3,128(1)\n\t" \
2659 /* arg10 */ \
2660 "ld 3,80(11)\n\t" \
2661 "std 3,120(1)\n\t" \
2662 /* arg9 */ \
2663 "ld 3,72(11)\n\t" \
2664 "std 3,112(1)\n\t" \
2665 /* args1-8 */ \
2666 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2667 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2668 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2669 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2670 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2671 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2672 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2673 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2674 "ld 11, 0(11)\n\t" /* target->r11 */ \
2675 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2676 "mr 11,%1\n\t" \
2677 "mr %0,3\n\t" \
2678 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2679 "addi 1,1,144" /* restore frame */ \
2680 : /*out*/ "=r" (_res) \
2681 : /*in*/ "r" (&_argvec[2]) \
2682 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2683 ); \
2684 lval = (__typeof__(lval)) _res; \
2685 } while (0)
2686
sewardjf5c1a7f2006-10-17 01:32:48 +00002687#endif /* PLAT_ppc64_linux */
2688
sewardj59570ff2010-01-01 11:59:33 +00002689/* ------------------------- arm-linux ------------------------- */
2690
2691#if defined(PLAT_arm_linux)
2692
2693/* These regs are trashed by the hidden call. */
2694#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2695
2696/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2697 long) == 4. */
2698
2699#define CALL_FN_W_v(lval, orig) \
2700 do { \
2701 volatile OrigFn _orig = (orig); \
2702 volatile unsigned long _argvec[1]; \
2703 volatile unsigned long _res; \
2704 _argvec[0] = (unsigned long)_orig.nraddr; \
2705 __asm__ volatile( \
2706 "ldr r4, [%1] \n\t" /* target->r4 */ \
2707 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2708 "mov %0, r0\n" \
2709 : /*out*/ "=r" (_res) \
2710 : /*in*/ "0" (&_argvec[0]) \
2711 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2712 ); \
2713 lval = (__typeof__(lval)) _res; \
2714 } while (0)
2715
2716#define CALL_FN_W_W(lval, orig, arg1) \
2717 do { \
2718 volatile OrigFn _orig = (orig); \
2719 volatile unsigned long _argvec[2]; \
2720 volatile unsigned long _res; \
2721 _argvec[0] = (unsigned long)_orig.nraddr; \
2722 _argvec[1] = (unsigned long)(arg1); \
2723 __asm__ volatile( \
2724 "ldr r0, [%1, #4] \n\t" \
2725 "ldr r4, [%1] \n\t" /* target->r4 */ \
2726 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2727 "mov %0, r0\n" \
2728 : /*out*/ "=r" (_res) \
2729 : /*in*/ "0" (&_argvec[0]) \
2730 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2731 ); \
2732 lval = (__typeof__(lval)) _res; \
2733 } while (0)
2734
2735#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2736 do { \
2737 volatile OrigFn _orig = (orig); \
2738 volatile unsigned long _argvec[3]; \
2739 volatile unsigned long _res; \
2740 _argvec[0] = (unsigned long)_orig.nraddr; \
2741 _argvec[1] = (unsigned long)(arg1); \
2742 _argvec[2] = (unsigned long)(arg2); \
2743 __asm__ volatile( \
2744 "ldr r0, [%1, #4] \n\t" \
2745 "ldr r1, [%1, #8] \n\t" \
2746 "ldr r4, [%1] \n\t" /* target->r4 */ \
2747 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2748 "mov %0, r0\n" \
2749 : /*out*/ "=r" (_res) \
2750 : /*in*/ "0" (&_argvec[0]) \
2751 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2752 ); \
2753 lval = (__typeof__(lval)) _res; \
2754 } while (0)
2755
2756#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2757 do { \
2758 volatile OrigFn _orig = (orig); \
2759 volatile unsigned long _argvec[4]; \
2760 volatile unsigned long _res; \
2761 _argvec[0] = (unsigned long)_orig.nraddr; \
2762 _argvec[1] = (unsigned long)(arg1); \
2763 _argvec[2] = (unsigned long)(arg2); \
2764 _argvec[3] = (unsigned long)(arg3); \
2765 __asm__ volatile( \
2766 "ldr r0, [%1, #4] \n\t" \
2767 "ldr r1, [%1, #8] \n\t" \
2768 "ldr r2, [%1, #12] \n\t" \
2769 "ldr r4, [%1] \n\t" /* target->r4 */ \
2770 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2771 "mov %0, r0\n" \
2772 : /*out*/ "=r" (_res) \
2773 : /*in*/ "0" (&_argvec[0]) \
2774 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2775 ); \
2776 lval = (__typeof__(lval)) _res; \
2777 } while (0)
2778
2779#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2780 do { \
2781 volatile OrigFn _orig = (orig); \
2782 volatile unsigned long _argvec[5]; \
2783 volatile unsigned long _res; \
2784 _argvec[0] = (unsigned long)_orig.nraddr; \
2785 _argvec[1] = (unsigned long)(arg1); \
2786 _argvec[2] = (unsigned long)(arg2); \
2787 _argvec[3] = (unsigned long)(arg3); \
2788 _argvec[4] = (unsigned long)(arg4); \
2789 __asm__ volatile( \
2790 "ldr r0, [%1, #4] \n\t" \
2791 "ldr r1, [%1, #8] \n\t" \
2792 "ldr r2, [%1, #12] \n\t" \
2793 "ldr r3, [%1, #16] \n\t" \
2794 "ldr r4, [%1] \n\t" /* target->r4 */ \
2795 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2796 "mov %0, r0" \
2797 : /*out*/ "=r" (_res) \
2798 : /*in*/ "0" (&_argvec[0]) \
2799 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2800 ); \
2801 lval = (__typeof__(lval)) _res; \
2802 } while (0)
2803
2804#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2805 do { \
2806 volatile OrigFn _orig = (orig); \
2807 volatile unsigned long _argvec[6]; \
2808 volatile unsigned long _res; \
2809 _argvec[0] = (unsigned long)_orig.nraddr; \
2810 _argvec[1] = (unsigned long)(arg1); \
2811 _argvec[2] = (unsigned long)(arg2); \
2812 _argvec[3] = (unsigned long)(arg3); \
2813 _argvec[4] = (unsigned long)(arg4); \
2814 _argvec[5] = (unsigned long)(arg5); \
2815 __asm__ volatile( \
2816 "ldr r0, [%1, #20] \n\t" \
2817 "push {r0} \n\t" \
2818 "ldr r0, [%1, #4] \n\t" \
2819 "ldr r1, [%1, #8] \n\t" \
2820 "ldr r2, [%1, #12] \n\t" \
2821 "ldr r3, [%1, #16] \n\t" \
2822 "ldr r4, [%1] \n\t" /* target->r4 */ \
2823 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2824 "add sp, sp, #4 \n\t" \
2825 "mov %0, r0" \
2826 : /*out*/ "=r" (_res) \
2827 : /*in*/ "0" (&_argvec[0]) \
2828 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2829 ); \
2830 lval = (__typeof__(lval)) _res; \
2831 } while (0)
2832
2833#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2834 do { \
2835 volatile OrigFn _orig = (orig); \
2836 volatile unsigned long _argvec[7]; \
2837 volatile unsigned long _res; \
2838 _argvec[0] = (unsigned long)_orig.nraddr; \
2839 _argvec[1] = (unsigned long)(arg1); \
2840 _argvec[2] = (unsigned long)(arg2); \
2841 _argvec[3] = (unsigned long)(arg3); \
2842 _argvec[4] = (unsigned long)(arg4); \
2843 _argvec[5] = (unsigned long)(arg5); \
2844 _argvec[6] = (unsigned long)(arg6); \
2845 __asm__ volatile( \
2846 "ldr r0, [%1, #20] \n\t" \
2847 "ldr r1, [%1, #24] \n\t" \
2848 "push {r0, r1} \n\t" \
2849 "ldr r0, [%1, #4] \n\t" \
2850 "ldr r1, [%1, #8] \n\t" \
2851 "ldr r2, [%1, #12] \n\t" \
2852 "ldr r3, [%1, #16] \n\t" \
2853 "ldr r4, [%1] \n\t" /* target->r4 */ \
2854 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2855 "add sp, sp, #8 \n\t" \
2856 "mov %0, r0" \
2857 : /*out*/ "=r" (_res) \
2858 : /*in*/ "0" (&_argvec[0]) \
2859 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2860 ); \
2861 lval = (__typeof__(lval)) _res; \
2862 } while (0)
2863
2864#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2865 arg7) \
2866 do { \
2867 volatile OrigFn _orig = (orig); \
2868 volatile unsigned long _argvec[8]; \
2869 volatile unsigned long _res; \
2870 _argvec[0] = (unsigned long)_orig.nraddr; \
2871 _argvec[1] = (unsigned long)(arg1); \
2872 _argvec[2] = (unsigned long)(arg2); \
2873 _argvec[3] = (unsigned long)(arg3); \
2874 _argvec[4] = (unsigned long)(arg4); \
2875 _argvec[5] = (unsigned long)(arg5); \
2876 _argvec[6] = (unsigned long)(arg6); \
2877 _argvec[7] = (unsigned long)(arg7); \
2878 __asm__ volatile( \
2879 "ldr r0, [%1, #20] \n\t" \
2880 "ldr r1, [%1, #24] \n\t" \
2881 "ldr r2, [%1, #28] \n\t" \
2882 "push {r0, r1, r2} \n\t" \
2883 "ldr r0, [%1, #4] \n\t" \
2884 "ldr r1, [%1, #8] \n\t" \
2885 "ldr r2, [%1, #12] \n\t" \
2886 "ldr r3, [%1, #16] \n\t" \
2887 "ldr r4, [%1] \n\t" /* target->r4 */ \
2888 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2889 "add sp, sp, #12 \n\t" \
2890 "mov %0, r0" \
2891 : /*out*/ "=r" (_res) \
2892 : /*in*/ "0" (&_argvec[0]) \
2893 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2894 ); \
2895 lval = (__typeof__(lval)) _res; \
2896 } while (0)
2897
2898#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2899 arg7,arg8) \
2900 do { \
2901 volatile OrigFn _orig = (orig); \
2902 volatile unsigned long _argvec[9]; \
2903 volatile unsigned long _res; \
2904 _argvec[0] = (unsigned long)_orig.nraddr; \
2905 _argvec[1] = (unsigned long)(arg1); \
2906 _argvec[2] = (unsigned long)(arg2); \
2907 _argvec[3] = (unsigned long)(arg3); \
2908 _argvec[4] = (unsigned long)(arg4); \
2909 _argvec[5] = (unsigned long)(arg5); \
2910 _argvec[6] = (unsigned long)(arg6); \
2911 _argvec[7] = (unsigned long)(arg7); \
2912 _argvec[8] = (unsigned long)(arg8); \
2913 __asm__ volatile( \
2914 "ldr r0, [%1, #20] \n\t" \
2915 "ldr r1, [%1, #24] \n\t" \
2916 "ldr r2, [%1, #28] \n\t" \
2917 "ldr r3, [%1, #32] \n\t" \
2918 "push {r0, r1, r2, r3} \n\t" \
2919 "ldr r0, [%1, #4] \n\t" \
2920 "ldr r1, [%1, #8] \n\t" \
2921 "ldr r2, [%1, #12] \n\t" \
2922 "ldr r3, [%1, #16] \n\t" \
2923 "ldr r4, [%1] \n\t" /* target->r4 */ \
2924 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2925 "add sp, sp, #16 \n\t" \
2926 "mov %0, r0" \
2927 : /*out*/ "=r" (_res) \
2928 : /*in*/ "0" (&_argvec[0]) \
2929 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2930 ); \
2931 lval = (__typeof__(lval)) _res; \
2932 } while (0)
2933
2934#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2935 arg7,arg8,arg9) \
2936 do { \
2937 volatile OrigFn _orig = (orig); \
2938 volatile unsigned long _argvec[10]; \
2939 volatile unsigned long _res; \
2940 _argvec[0] = (unsigned long)_orig.nraddr; \
2941 _argvec[1] = (unsigned long)(arg1); \
2942 _argvec[2] = (unsigned long)(arg2); \
2943 _argvec[3] = (unsigned long)(arg3); \
2944 _argvec[4] = (unsigned long)(arg4); \
2945 _argvec[5] = (unsigned long)(arg5); \
2946 _argvec[6] = (unsigned long)(arg6); \
2947 _argvec[7] = (unsigned long)(arg7); \
2948 _argvec[8] = (unsigned long)(arg8); \
2949 _argvec[9] = (unsigned long)(arg9); \
2950 __asm__ volatile( \
2951 "ldr r0, [%1, #20] \n\t" \
2952 "ldr r1, [%1, #24] \n\t" \
2953 "ldr r2, [%1, #28] \n\t" \
2954 "ldr r3, [%1, #32] \n\t" \
2955 "ldr r4, [%1, #36] \n\t" \
2956 "push {r0, r1, r2, r3, r4} \n\t" \
2957 "ldr r0, [%1, #4] \n\t" \
2958 "ldr r1, [%1, #8] \n\t" \
2959 "ldr r2, [%1, #12] \n\t" \
2960 "ldr r3, [%1, #16] \n\t" \
2961 "ldr r4, [%1] \n\t" /* target->r4 */ \
2962 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2963 "add sp, sp, #20 \n\t" \
2964 "mov %0, r0" \
2965 : /*out*/ "=r" (_res) \
2966 : /*in*/ "0" (&_argvec[0]) \
2967 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2968 ); \
2969 lval = (__typeof__(lval)) _res; \
2970 } while (0)
2971
2972#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2973 arg7,arg8,arg9,arg10) \
2974 do { \
2975 volatile OrigFn _orig = (orig); \
2976 volatile unsigned long _argvec[11]; \
2977 volatile unsigned long _res; \
2978 _argvec[0] = (unsigned long)_orig.nraddr; \
2979 _argvec[1] = (unsigned long)(arg1); \
2980 _argvec[2] = (unsigned long)(arg2); \
2981 _argvec[3] = (unsigned long)(arg3); \
2982 _argvec[4] = (unsigned long)(arg4); \
2983 _argvec[5] = (unsigned long)(arg5); \
2984 _argvec[6] = (unsigned long)(arg6); \
2985 _argvec[7] = (unsigned long)(arg7); \
2986 _argvec[8] = (unsigned long)(arg8); \
2987 _argvec[9] = (unsigned long)(arg9); \
2988 _argvec[10] = (unsigned long)(arg10); \
2989 __asm__ volatile( \
2990 "ldr r0, [%1, #40] \n\t" \
2991 "push {r0} \n\t" \
2992 "ldr r0, [%1, #20] \n\t" \
2993 "ldr r1, [%1, #24] \n\t" \
2994 "ldr r2, [%1, #28] \n\t" \
2995 "ldr r3, [%1, #32] \n\t" \
2996 "ldr r4, [%1, #36] \n\t" \
2997 "push {r0, r1, r2, r3, r4} \n\t" \
2998 "ldr r0, [%1, #4] \n\t" \
2999 "ldr r1, [%1, #8] \n\t" \
3000 "ldr r2, [%1, #12] \n\t" \
3001 "ldr r3, [%1, #16] \n\t" \
3002 "ldr r4, [%1] \n\t" /* target->r4 */ \
3003 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3004 "add sp, sp, #24 \n\t" \
3005 "mov %0, r0" \
3006 : /*out*/ "=r" (_res) \
3007 : /*in*/ "0" (&_argvec[0]) \
3008 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3009 ); \
3010 lval = (__typeof__(lval)) _res; \
3011 } while (0)
3012
3013#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3014 arg6,arg7,arg8,arg9,arg10, \
3015 arg11) \
3016 do { \
3017 volatile OrigFn _orig = (orig); \
3018 volatile unsigned long _argvec[12]; \
3019 volatile unsigned long _res; \
3020 _argvec[0] = (unsigned long)_orig.nraddr; \
3021 _argvec[1] = (unsigned long)(arg1); \
3022 _argvec[2] = (unsigned long)(arg2); \
3023 _argvec[3] = (unsigned long)(arg3); \
3024 _argvec[4] = (unsigned long)(arg4); \
3025 _argvec[5] = (unsigned long)(arg5); \
3026 _argvec[6] = (unsigned long)(arg6); \
3027 _argvec[7] = (unsigned long)(arg7); \
3028 _argvec[8] = (unsigned long)(arg8); \
3029 _argvec[9] = (unsigned long)(arg9); \
3030 _argvec[10] = (unsigned long)(arg10); \
3031 _argvec[11] = (unsigned long)(arg11); \
3032 __asm__ volatile( \
3033 "ldr r0, [%1, #40] \n\t" \
3034 "ldr r1, [%1, #44] \n\t" \
3035 "push {r0, r1} \n\t" \
3036 "ldr r0, [%1, #20] \n\t" \
3037 "ldr r1, [%1, #24] \n\t" \
3038 "ldr r2, [%1, #28] \n\t" \
3039 "ldr r3, [%1, #32] \n\t" \
3040 "ldr r4, [%1, #36] \n\t" \
3041 "push {r0, r1, r2, r3, r4} \n\t" \
3042 "ldr r0, [%1, #4] \n\t" \
3043 "ldr r1, [%1, #8] \n\t" \
3044 "ldr r2, [%1, #12] \n\t" \
3045 "ldr r3, [%1, #16] \n\t" \
3046 "ldr r4, [%1] \n\t" /* target->r4 */ \
3047 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3048 "add sp, sp, #28 \n\t" \
3049 "mov %0, r0" \
3050 : /*out*/ "=r" (_res) \
3051 : /*in*/ "0" (&_argvec[0]) \
3052 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3053 ); \
3054 lval = (__typeof__(lval)) _res; \
3055 } while (0)
3056
3057#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3058 arg6,arg7,arg8,arg9,arg10, \
3059 arg11,arg12) \
3060 do { \
3061 volatile OrigFn _orig = (orig); \
3062 volatile unsigned long _argvec[13]; \
3063 volatile unsigned long _res; \
3064 _argvec[0] = (unsigned long)_orig.nraddr; \
3065 _argvec[1] = (unsigned long)(arg1); \
3066 _argvec[2] = (unsigned long)(arg2); \
3067 _argvec[3] = (unsigned long)(arg3); \
3068 _argvec[4] = (unsigned long)(arg4); \
3069 _argvec[5] = (unsigned long)(arg5); \
3070 _argvec[6] = (unsigned long)(arg6); \
3071 _argvec[7] = (unsigned long)(arg7); \
3072 _argvec[8] = (unsigned long)(arg8); \
3073 _argvec[9] = (unsigned long)(arg9); \
3074 _argvec[10] = (unsigned long)(arg10); \
3075 _argvec[11] = (unsigned long)(arg11); \
3076 _argvec[12] = (unsigned long)(arg12); \
3077 __asm__ volatile( \
3078 "ldr r0, [%1, #40] \n\t" \
3079 "ldr r1, [%1, #44] \n\t" \
3080 "ldr r2, [%1, #48] \n\t" \
3081 "push {r0, r1, r2} \n\t" \
3082 "ldr r0, [%1, #20] \n\t" \
3083 "ldr r1, [%1, #24] \n\t" \
3084 "ldr r2, [%1, #28] \n\t" \
3085 "ldr r3, [%1, #32] \n\t" \
3086 "ldr r4, [%1, #36] \n\t" \
3087 "push {r0, r1, r2, r3, r4} \n\t" \
3088 "ldr r0, [%1, #4] \n\t" \
3089 "ldr r1, [%1, #8] \n\t" \
3090 "ldr r2, [%1, #12] \n\t" \
3091 "ldr r3, [%1, #16] \n\t" \
3092 "ldr r4, [%1] \n\t" /* target->r4 */ \
3093 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3094 "add sp, sp, #32 \n\t" \
3095 "mov %0, r0" \
3096 : /*out*/ "=r" (_res) \
3097 : /*in*/ "0" (&_argvec[0]) \
3098 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3099 ); \
3100 lval = (__typeof__(lval)) _res; \
3101 } while (0)
3102
3103#endif /* PLAT_arm_linux */
3104
sewardjf5c1a7f2006-10-17 01:32:48 +00003105/* ------------------------ ppc32-aix5 ------------------------- */
3106
3107#if defined(PLAT_ppc32_aix5)
3108
3109/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3110
3111/* These regs are trashed by the hidden call. */
3112#define __CALLER_SAVED_REGS \
3113 "lr", "ctr", "xer", \
3114 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3115 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3116 "r11", "r12", "r13"
3117
3118/* Expand the stack frame, copying enough info that unwinding
3119 still works. Trashes r3. */
3120
3121#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3122 "addi 1,1,-" #_n_fr "\n\t" \
3123 "lwz 3," #_n_fr "(1)\n\t" \
3124 "stw 3,0(1)\n\t"
3125
3126#define VG_CONTRACT_FRAME_BY(_n_fr) \
3127 "addi 1,1," #_n_fr "\n\t"
3128
3129/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
3130 long) == 4. */
3131
3132#define CALL_FN_W_v(lval, orig) \
3133 do { \
3134 volatile OrigFn _orig = (orig); \
3135 volatile unsigned long _argvec[3+0]; \
3136 volatile unsigned long _res; \
3137 /* _argvec[0] holds current r2 across the call */ \
3138 _argvec[1] = (unsigned long)_orig.r2; \
3139 _argvec[2] = (unsigned long)_orig.nraddr; \
3140 __asm__ volatile( \
3141 "mr 11,%1\n\t" \
3142 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3143 "stw 2,-8(11)\n\t" /* save tocptr */ \
3144 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3145 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3146 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3147 "mr 11,%1\n\t" \
3148 "mr %0,3\n\t" \
3149 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3150 VG_CONTRACT_FRAME_BY(512) \
3151 : /*out*/ "=r" (_res) \
3152 : /*in*/ "r" (&_argvec[2]) \
3153 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3154 ); \
3155 lval = (__typeof__(lval)) _res; \
3156 } while (0)
3157
3158#define CALL_FN_W_W(lval, orig, arg1) \
3159 do { \
3160 volatile OrigFn _orig = (orig); \
3161 volatile unsigned long _argvec[3+1]; \
3162 volatile unsigned long _res; \
3163 /* _argvec[0] holds current r2 across the call */ \
3164 _argvec[1] = (unsigned long)_orig.r2; \
3165 _argvec[2] = (unsigned long)_orig.nraddr; \
3166 _argvec[2+1] = (unsigned long)arg1; \
3167 __asm__ volatile( \
3168 "mr 11,%1\n\t" \
3169 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3170 "stw 2,-8(11)\n\t" /* save tocptr */ \
3171 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3172 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3173 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3174 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3175 "mr 11,%1\n\t" \
3176 "mr %0,3\n\t" \
3177 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3178 VG_CONTRACT_FRAME_BY(512) \
3179 : /*out*/ "=r" (_res) \
3180 : /*in*/ "r" (&_argvec[2]) \
3181 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3182 ); \
3183 lval = (__typeof__(lval)) _res; \
3184 } while (0)
3185
3186#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3187 do { \
3188 volatile OrigFn _orig = (orig); \
3189 volatile unsigned long _argvec[3+2]; \
3190 volatile unsigned long _res; \
3191 /* _argvec[0] holds current r2 across the call */ \
3192 _argvec[1] = (unsigned long)_orig.r2; \
3193 _argvec[2] = (unsigned long)_orig.nraddr; \
3194 _argvec[2+1] = (unsigned long)arg1; \
3195 _argvec[2+2] = (unsigned long)arg2; \
3196 __asm__ volatile( \
3197 "mr 11,%1\n\t" \
3198 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3199 "stw 2,-8(11)\n\t" /* save tocptr */ \
3200 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3201 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3202 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3203 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3204 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3205 "mr 11,%1\n\t" \
3206 "mr %0,3\n\t" \
3207 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3208 VG_CONTRACT_FRAME_BY(512) \
3209 : /*out*/ "=r" (_res) \
3210 : /*in*/ "r" (&_argvec[2]) \
3211 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3212 ); \
3213 lval = (__typeof__(lval)) _res; \
3214 } while (0)
3215
3216#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3217 do { \
3218 volatile OrigFn _orig = (orig); \
3219 volatile unsigned long _argvec[3+3]; \
3220 volatile unsigned long _res; \
3221 /* _argvec[0] holds current r2 across the call */ \
3222 _argvec[1] = (unsigned long)_orig.r2; \
3223 _argvec[2] = (unsigned long)_orig.nraddr; \
3224 _argvec[2+1] = (unsigned long)arg1; \
3225 _argvec[2+2] = (unsigned long)arg2; \
3226 _argvec[2+3] = (unsigned long)arg3; \
3227 __asm__ volatile( \
3228 "mr 11,%1\n\t" \
3229 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3230 "stw 2,-8(11)\n\t" /* save tocptr */ \
3231 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3232 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3233 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3234 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3235 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3236 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3237 "mr 11,%1\n\t" \
3238 "mr %0,3\n\t" \
3239 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3240 VG_CONTRACT_FRAME_BY(512) \
3241 : /*out*/ "=r" (_res) \
3242 : /*in*/ "r" (&_argvec[2]) \
3243 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3244 ); \
3245 lval = (__typeof__(lval)) _res; \
3246 } while (0)
3247
3248#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3249 do { \
3250 volatile OrigFn _orig = (orig); \
3251 volatile unsigned long _argvec[3+4]; \
3252 volatile unsigned long _res; \
3253 /* _argvec[0] holds current r2 across the call */ \
3254 _argvec[1] = (unsigned long)_orig.r2; \
3255 _argvec[2] = (unsigned long)_orig.nraddr; \
3256 _argvec[2+1] = (unsigned long)arg1; \
3257 _argvec[2+2] = (unsigned long)arg2; \
3258 _argvec[2+3] = (unsigned long)arg3; \
3259 _argvec[2+4] = (unsigned long)arg4; \
3260 __asm__ volatile( \
3261 "mr 11,%1\n\t" \
3262 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3263 "stw 2,-8(11)\n\t" /* save tocptr */ \
3264 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3265 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3266 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3267 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3268 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3269 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3270 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3271 "mr 11,%1\n\t" \
3272 "mr %0,3\n\t" \
3273 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3274 VG_CONTRACT_FRAME_BY(512) \
3275 : /*out*/ "=r" (_res) \
3276 : /*in*/ "r" (&_argvec[2]) \
3277 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3278 ); \
3279 lval = (__typeof__(lval)) _res; \
3280 } while (0)
3281
3282#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3283 do { \
3284 volatile OrigFn _orig = (orig); \
3285 volatile unsigned long _argvec[3+5]; \
3286 volatile unsigned long _res; \
3287 /* _argvec[0] holds current r2 across the call */ \
3288 _argvec[1] = (unsigned long)_orig.r2; \
3289 _argvec[2] = (unsigned long)_orig.nraddr; \
3290 _argvec[2+1] = (unsigned long)arg1; \
3291 _argvec[2+2] = (unsigned long)arg2; \
3292 _argvec[2+3] = (unsigned long)arg3; \
3293 _argvec[2+4] = (unsigned long)arg4; \
3294 _argvec[2+5] = (unsigned long)arg5; \
3295 __asm__ volatile( \
3296 "mr 11,%1\n\t" \
3297 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3298 "stw 2,-8(11)\n\t" /* save tocptr */ \
3299 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3300 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3301 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3302 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3303 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3304 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3305 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3306 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3307 "mr 11,%1\n\t" \
3308 "mr %0,3\n\t" \
3309 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3310 VG_CONTRACT_FRAME_BY(512) \
3311 : /*out*/ "=r" (_res) \
3312 : /*in*/ "r" (&_argvec[2]) \
3313 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3314 ); \
3315 lval = (__typeof__(lval)) _res; \
3316 } while (0)
3317
3318#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3319 do { \
3320 volatile OrigFn _orig = (orig); \
3321 volatile unsigned long _argvec[3+6]; \
3322 volatile unsigned long _res; \
3323 /* _argvec[0] holds current r2 across the call */ \
3324 _argvec[1] = (unsigned long)_orig.r2; \
3325 _argvec[2] = (unsigned long)_orig.nraddr; \
3326 _argvec[2+1] = (unsigned long)arg1; \
3327 _argvec[2+2] = (unsigned long)arg2; \
3328 _argvec[2+3] = (unsigned long)arg3; \
3329 _argvec[2+4] = (unsigned long)arg4; \
3330 _argvec[2+5] = (unsigned long)arg5; \
3331 _argvec[2+6] = (unsigned long)arg6; \
3332 __asm__ volatile( \
3333 "mr 11,%1\n\t" \
3334 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3335 "stw 2,-8(11)\n\t" /* save tocptr */ \
3336 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3337 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3338 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3339 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3340 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3341 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3342 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3343 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3344 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3345 "mr 11,%1\n\t" \
3346 "mr %0,3\n\t" \
3347 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3348 VG_CONTRACT_FRAME_BY(512) \
3349 : /*out*/ "=r" (_res) \
3350 : /*in*/ "r" (&_argvec[2]) \
3351 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3352 ); \
3353 lval = (__typeof__(lval)) _res; \
3354 } while (0)
3355
3356#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3357 arg7) \
3358 do { \
3359 volatile OrigFn _orig = (orig); \
3360 volatile unsigned long _argvec[3+7]; \
3361 volatile unsigned long _res; \
3362 /* _argvec[0] holds current r2 across the call */ \
3363 _argvec[1] = (unsigned long)_orig.r2; \
3364 _argvec[2] = (unsigned long)_orig.nraddr; \
3365 _argvec[2+1] = (unsigned long)arg1; \
3366 _argvec[2+2] = (unsigned long)arg2; \
3367 _argvec[2+3] = (unsigned long)arg3; \
3368 _argvec[2+4] = (unsigned long)arg4; \
3369 _argvec[2+5] = (unsigned long)arg5; \
3370 _argvec[2+6] = (unsigned long)arg6; \
3371 _argvec[2+7] = (unsigned long)arg7; \
3372 __asm__ volatile( \
3373 "mr 11,%1\n\t" \
3374 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3375 "stw 2,-8(11)\n\t" /* save tocptr */ \
3376 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3377 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3378 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3379 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3380 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3381 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3382 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3383 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3384 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3385 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3386 "mr 11,%1\n\t" \
3387 "mr %0,3\n\t" \
3388 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3389 VG_CONTRACT_FRAME_BY(512) \
3390 : /*out*/ "=r" (_res) \
3391 : /*in*/ "r" (&_argvec[2]) \
3392 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3393 ); \
3394 lval = (__typeof__(lval)) _res; \
3395 } while (0)
3396
3397#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3398 arg7,arg8) \
3399 do { \
3400 volatile OrigFn _orig = (orig); \
3401 volatile unsigned long _argvec[3+8]; \
3402 volatile unsigned long _res; \
3403 /* _argvec[0] holds current r2 across the call */ \
3404 _argvec[1] = (unsigned long)_orig.r2; \
3405 _argvec[2] = (unsigned long)_orig.nraddr; \
3406 _argvec[2+1] = (unsigned long)arg1; \
3407 _argvec[2+2] = (unsigned long)arg2; \
3408 _argvec[2+3] = (unsigned long)arg3; \
3409 _argvec[2+4] = (unsigned long)arg4; \
3410 _argvec[2+5] = (unsigned long)arg5; \
3411 _argvec[2+6] = (unsigned long)arg6; \
3412 _argvec[2+7] = (unsigned long)arg7; \
3413 _argvec[2+8] = (unsigned long)arg8; \
3414 __asm__ volatile( \
3415 "mr 11,%1\n\t" \
3416 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3417 "stw 2,-8(11)\n\t" /* save tocptr */ \
3418 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3419 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3420 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3421 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3422 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3423 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3424 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3425 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3426 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3427 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3428 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3429 "mr 11,%1\n\t" \
3430 "mr %0,3\n\t" \
3431 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3432 VG_CONTRACT_FRAME_BY(512) \
3433 : /*out*/ "=r" (_res) \
3434 : /*in*/ "r" (&_argvec[2]) \
3435 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3436 ); \
3437 lval = (__typeof__(lval)) _res; \
3438 } while (0)
3439
3440#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3441 arg7,arg8,arg9) \
3442 do { \
3443 volatile OrigFn _orig = (orig); \
3444 volatile unsigned long _argvec[3+9]; \
3445 volatile unsigned long _res; \
3446 /* _argvec[0] holds current r2 across the call */ \
3447 _argvec[1] = (unsigned long)_orig.r2; \
3448 _argvec[2] = (unsigned long)_orig.nraddr; \
3449 _argvec[2+1] = (unsigned long)arg1; \
3450 _argvec[2+2] = (unsigned long)arg2; \
3451 _argvec[2+3] = (unsigned long)arg3; \
3452 _argvec[2+4] = (unsigned long)arg4; \
3453 _argvec[2+5] = (unsigned long)arg5; \
3454 _argvec[2+6] = (unsigned long)arg6; \
3455 _argvec[2+7] = (unsigned long)arg7; \
3456 _argvec[2+8] = (unsigned long)arg8; \
3457 _argvec[2+9] = (unsigned long)arg9; \
3458 __asm__ volatile( \
3459 "mr 11,%1\n\t" \
3460 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3461 "stw 2,-8(11)\n\t" /* save tocptr */ \
3462 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3463 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3464 /* arg9 */ \
3465 "lwz 3,36(11)\n\t" \
3466 "stw 3,56(1)\n\t" \
3467 /* args1-8 */ \
3468 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3469 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3470 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3471 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3472 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3473 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3474 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3475 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3476 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3477 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3478 "mr 11,%1\n\t" \
3479 "mr %0,3\n\t" \
3480 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3481 VG_CONTRACT_FRAME_BY(64) \
3482 VG_CONTRACT_FRAME_BY(512) \
3483 : /*out*/ "=r" (_res) \
3484 : /*in*/ "r" (&_argvec[2]) \
3485 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3486 ); \
3487 lval = (__typeof__(lval)) _res; \
3488 } while (0)
3489
3490#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3491 arg7,arg8,arg9,arg10) \
3492 do { \
3493 volatile OrigFn _orig = (orig); \
3494 volatile unsigned long _argvec[3+10]; \
3495 volatile unsigned long _res; \
3496 /* _argvec[0] holds current r2 across the call */ \
3497 _argvec[1] = (unsigned long)_orig.r2; \
3498 _argvec[2] = (unsigned long)_orig.nraddr; \
3499 _argvec[2+1] = (unsigned long)arg1; \
3500 _argvec[2+2] = (unsigned long)arg2; \
3501 _argvec[2+3] = (unsigned long)arg3; \
3502 _argvec[2+4] = (unsigned long)arg4; \
3503 _argvec[2+5] = (unsigned long)arg5; \
3504 _argvec[2+6] = (unsigned long)arg6; \
3505 _argvec[2+7] = (unsigned long)arg7; \
3506 _argvec[2+8] = (unsigned long)arg8; \
3507 _argvec[2+9] = (unsigned long)arg9; \
3508 _argvec[2+10] = (unsigned long)arg10; \
3509 __asm__ volatile( \
3510 "mr 11,%1\n\t" \
3511 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3512 "stw 2,-8(11)\n\t" /* save tocptr */ \
3513 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3514 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3515 /* arg10 */ \
3516 "lwz 3,40(11)\n\t" \
3517 "stw 3,60(1)\n\t" \
3518 /* arg9 */ \
3519 "lwz 3,36(11)\n\t" \
3520 "stw 3,56(1)\n\t" \
3521 /* args1-8 */ \
3522 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3523 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3524 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3525 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3526 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3527 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3528 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3529 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3530 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3531 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3532 "mr 11,%1\n\t" \
3533 "mr %0,3\n\t" \
3534 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3535 VG_CONTRACT_FRAME_BY(64) \
3536 VG_CONTRACT_FRAME_BY(512) \
3537 : /*out*/ "=r" (_res) \
3538 : /*in*/ "r" (&_argvec[2]) \
3539 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3540 ); \
3541 lval = (__typeof__(lval)) _res; \
3542 } while (0)
3543
3544#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3545 arg7,arg8,arg9,arg10,arg11) \
3546 do { \
3547 volatile OrigFn _orig = (orig); \
3548 volatile unsigned long _argvec[3+11]; \
3549 volatile unsigned long _res; \
3550 /* _argvec[0] holds current r2 across the call */ \
3551 _argvec[1] = (unsigned long)_orig.r2; \
3552 _argvec[2] = (unsigned long)_orig.nraddr; \
3553 _argvec[2+1] = (unsigned long)arg1; \
3554 _argvec[2+2] = (unsigned long)arg2; \
3555 _argvec[2+3] = (unsigned long)arg3; \
3556 _argvec[2+4] = (unsigned long)arg4; \
3557 _argvec[2+5] = (unsigned long)arg5; \
3558 _argvec[2+6] = (unsigned long)arg6; \
3559 _argvec[2+7] = (unsigned long)arg7; \
3560 _argvec[2+8] = (unsigned long)arg8; \
3561 _argvec[2+9] = (unsigned long)arg9; \
3562 _argvec[2+10] = (unsigned long)arg10; \
3563 _argvec[2+11] = (unsigned long)arg11; \
3564 __asm__ volatile( \
3565 "mr 11,%1\n\t" \
3566 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3567 "stw 2,-8(11)\n\t" /* save tocptr */ \
3568 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3569 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3570 /* arg11 */ \
3571 "lwz 3,44(11)\n\t" \
3572 "stw 3,64(1)\n\t" \
3573 /* arg10 */ \
3574 "lwz 3,40(11)\n\t" \
3575 "stw 3,60(1)\n\t" \
3576 /* arg9 */ \
3577 "lwz 3,36(11)\n\t" \
3578 "stw 3,56(1)\n\t" \
3579 /* args1-8 */ \
3580 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3581 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3582 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3583 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3584 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3585 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3586 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3587 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3588 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3589 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3590 "mr 11,%1\n\t" \
3591 "mr %0,3\n\t" \
3592 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3593 VG_CONTRACT_FRAME_BY(72) \
3594 VG_CONTRACT_FRAME_BY(512) \
3595 : /*out*/ "=r" (_res) \
3596 : /*in*/ "r" (&_argvec[2]) \
3597 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3598 ); \
3599 lval = (__typeof__(lval)) _res; \
3600 } while (0)
3601
3602#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3603 arg7,arg8,arg9,arg10,arg11,arg12) \
3604 do { \
3605 volatile OrigFn _orig = (orig); \
3606 volatile unsigned long _argvec[3+12]; \
3607 volatile unsigned long _res; \
3608 /* _argvec[0] holds current r2 across the call */ \
3609 _argvec[1] = (unsigned long)_orig.r2; \
3610 _argvec[2] = (unsigned long)_orig.nraddr; \
3611 _argvec[2+1] = (unsigned long)arg1; \
3612 _argvec[2+2] = (unsigned long)arg2; \
3613 _argvec[2+3] = (unsigned long)arg3; \
3614 _argvec[2+4] = (unsigned long)arg4; \
3615 _argvec[2+5] = (unsigned long)arg5; \
3616 _argvec[2+6] = (unsigned long)arg6; \
3617 _argvec[2+7] = (unsigned long)arg7; \
3618 _argvec[2+8] = (unsigned long)arg8; \
3619 _argvec[2+9] = (unsigned long)arg9; \
3620 _argvec[2+10] = (unsigned long)arg10; \
3621 _argvec[2+11] = (unsigned long)arg11; \
3622 _argvec[2+12] = (unsigned long)arg12; \
3623 __asm__ volatile( \
3624 "mr 11,%1\n\t" \
3625 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3626 "stw 2,-8(11)\n\t" /* save tocptr */ \
3627 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3628 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3629 /* arg12 */ \
3630 "lwz 3,48(11)\n\t" \
3631 "stw 3,68(1)\n\t" \
3632 /* arg11 */ \
3633 "lwz 3,44(11)\n\t" \
3634 "stw 3,64(1)\n\t" \
3635 /* arg10 */ \
3636 "lwz 3,40(11)\n\t" \
3637 "stw 3,60(1)\n\t" \
3638 /* arg9 */ \
3639 "lwz 3,36(11)\n\t" \
3640 "stw 3,56(1)\n\t" \
3641 /* args1-8 */ \
3642 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3643 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3644 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3645 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3646 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3647 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3648 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3649 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3650 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3651 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3652 "mr 11,%1\n\t" \
3653 "mr %0,3\n\t" \
3654 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3655 VG_CONTRACT_FRAME_BY(72) \
3656 VG_CONTRACT_FRAME_BY(512) \
3657 : /*out*/ "=r" (_res) \
3658 : /*in*/ "r" (&_argvec[2]) \
3659 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3660 ); \
3661 lval = (__typeof__(lval)) _res; \
3662 } while (0)
3663
3664#endif /* PLAT_ppc32_aix5 */
3665
3666/* ------------------------ ppc64-aix5 ------------------------- */
3667
3668#if defined(PLAT_ppc64_aix5)
3669
3670/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3671
3672/* These regs are trashed by the hidden call. */
3673#define __CALLER_SAVED_REGS \
3674 "lr", "ctr", "xer", \
3675 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3676 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3677 "r11", "r12", "r13"
3678
3679/* Expand the stack frame, copying enough info that unwinding
3680 still works. Trashes r3. */
3681
3682#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3683 "addi 1,1,-" #_n_fr "\n\t" \
3684 "ld 3," #_n_fr "(1)\n\t" \
3685 "std 3,0(1)\n\t"
3686
3687#define VG_CONTRACT_FRAME_BY(_n_fr) \
3688 "addi 1,1," #_n_fr "\n\t"
3689
3690/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3691 long) == 8. */
3692
3693#define CALL_FN_W_v(lval, orig) \
3694 do { \
3695 volatile OrigFn _orig = (orig); \
3696 volatile unsigned long _argvec[3+0]; \
3697 volatile unsigned long _res; \
3698 /* _argvec[0] holds current r2 across the call */ \
3699 _argvec[1] = (unsigned long)_orig.r2; \
3700 _argvec[2] = (unsigned long)_orig.nraddr; \
3701 __asm__ volatile( \
3702 "mr 11,%1\n\t" \
3703 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3704 "std 2,-16(11)\n\t" /* save tocptr */ \
3705 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3706 "ld 11, 0(11)\n\t" /* target->r11 */ \
3707 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3708 "mr 11,%1\n\t" \
3709 "mr %0,3\n\t" \
3710 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3711 VG_CONTRACT_FRAME_BY(512) \
3712 : /*out*/ "=r" (_res) \
3713 : /*in*/ "r" (&_argvec[2]) \
3714 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3715 ); \
3716 lval = (__typeof__(lval)) _res; \
3717 } while (0)
3718
3719#define CALL_FN_W_W(lval, orig, arg1) \
3720 do { \
3721 volatile OrigFn _orig = (orig); \
3722 volatile unsigned long _argvec[3+1]; \
3723 volatile unsigned long _res; \
3724 /* _argvec[0] holds current r2 across the call */ \
3725 _argvec[1] = (unsigned long)_orig.r2; \
3726 _argvec[2] = (unsigned long)_orig.nraddr; \
3727 _argvec[2+1] = (unsigned long)arg1; \
3728 __asm__ volatile( \
3729 "mr 11,%1\n\t" \
3730 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3731 "std 2,-16(11)\n\t" /* save tocptr */ \
3732 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3733 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3734 "ld 11, 0(11)\n\t" /* target->r11 */ \
3735 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3736 "mr 11,%1\n\t" \
3737 "mr %0,3\n\t" \
3738 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3739 VG_CONTRACT_FRAME_BY(512) \
3740 : /*out*/ "=r" (_res) \
3741 : /*in*/ "r" (&_argvec[2]) \
3742 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3743 ); \
3744 lval = (__typeof__(lval)) _res; \
3745 } while (0)
3746
3747#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3748 do { \
3749 volatile OrigFn _orig = (orig); \
3750 volatile unsigned long _argvec[3+2]; \
3751 volatile unsigned long _res; \
3752 /* _argvec[0] holds current r2 across the call */ \
3753 _argvec[1] = (unsigned long)_orig.r2; \
3754 _argvec[2] = (unsigned long)_orig.nraddr; \
3755 _argvec[2+1] = (unsigned long)arg1; \
3756 _argvec[2+2] = (unsigned long)arg2; \
3757 __asm__ volatile( \
3758 "mr 11,%1\n\t" \
3759 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3760 "std 2,-16(11)\n\t" /* save tocptr */ \
3761 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3762 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3763 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3764 "ld 11, 0(11)\n\t" /* target->r11 */ \
3765 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3766 "mr 11,%1\n\t" \
3767 "mr %0,3\n\t" \
3768 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3769 VG_CONTRACT_FRAME_BY(512) \
3770 : /*out*/ "=r" (_res) \
3771 : /*in*/ "r" (&_argvec[2]) \
3772 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3773 ); \
3774 lval = (__typeof__(lval)) _res; \
3775 } while (0)
3776
3777#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3778 do { \
3779 volatile OrigFn _orig = (orig); \
3780 volatile unsigned long _argvec[3+3]; \
3781 volatile unsigned long _res; \
3782 /* _argvec[0] holds current r2 across the call */ \
3783 _argvec[1] = (unsigned long)_orig.r2; \
3784 _argvec[2] = (unsigned long)_orig.nraddr; \
3785 _argvec[2+1] = (unsigned long)arg1; \
3786 _argvec[2+2] = (unsigned long)arg2; \
3787 _argvec[2+3] = (unsigned long)arg3; \
3788 __asm__ volatile( \
3789 "mr 11,%1\n\t" \
3790 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3791 "std 2,-16(11)\n\t" /* save tocptr */ \
3792 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3793 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3794 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3795 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3796 "ld 11, 0(11)\n\t" /* target->r11 */ \
3797 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3798 "mr 11,%1\n\t" \
3799 "mr %0,3\n\t" \
3800 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3801 VG_CONTRACT_FRAME_BY(512) \
3802 : /*out*/ "=r" (_res) \
3803 : /*in*/ "r" (&_argvec[2]) \
3804 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3805 ); \
3806 lval = (__typeof__(lval)) _res; \
3807 } while (0)
3808
3809#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3810 do { \
3811 volatile OrigFn _orig = (orig); \
3812 volatile unsigned long _argvec[3+4]; \
3813 volatile unsigned long _res; \
3814 /* _argvec[0] holds current r2 across the call */ \
3815 _argvec[1] = (unsigned long)_orig.r2; \
3816 _argvec[2] = (unsigned long)_orig.nraddr; \
3817 _argvec[2+1] = (unsigned long)arg1; \
3818 _argvec[2+2] = (unsigned long)arg2; \
3819 _argvec[2+3] = (unsigned long)arg3; \
3820 _argvec[2+4] = (unsigned long)arg4; \
3821 __asm__ volatile( \
3822 "mr 11,%1\n\t" \
3823 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3824 "std 2,-16(11)\n\t" /* save tocptr */ \
3825 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3826 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3827 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3828 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3829 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3830 "ld 11, 0(11)\n\t" /* target->r11 */ \
3831 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3832 "mr 11,%1\n\t" \
3833 "mr %0,3\n\t" \
3834 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3835 VG_CONTRACT_FRAME_BY(512) \
3836 : /*out*/ "=r" (_res) \
3837 : /*in*/ "r" (&_argvec[2]) \
3838 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3839 ); \
3840 lval = (__typeof__(lval)) _res; \
3841 } while (0)
3842
3843#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3844 do { \
3845 volatile OrigFn _orig = (orig); \
3846 volatile unsigned long _argvec[3+5]; \
3847 volatile unsigned long _res; \
3848 /* _argvec[0] holds current r2 across the call */ \
3849 _argvec[1] = (unsigned long)_orig.r2; \
3850 _argvec[2] = (unsigned long)_orig.nraddr; \
3851 _argvec[2+1] = (unsigned long)arg1; \
3852 _argvec[2+2] = (unsigned long)arg2; \
3853 _argvec[2+3] = (unsigned long)arg3; \
3854 _argvec[2+4] = (unsigned long)arg4; \
3855 _argvec[2+5] = (unsigned long)arg5; \
3856 __asm__ volatile( \
3857 "mr 11,%1\n\t" \
3858 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3859 "std 2,-16(11)\n\t" /* save tocptr */ \
3860 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3861 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3862 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3863 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3864 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3865 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3866 "ld 11, 0(11)\n\t" /* target->r11 */ \
3867 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3868 "mr 11,%1\n\t" \
3869 "mr %0,3\n\t" \
3870 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3871 VG_CONTRACT_FRAME_BY(512) \
3872 : /*out*/ "=r" (_res) \
3873 : /*in*/ "r" (&_argvec[2]) \
3874 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3875 ); \
3876 lval = (__typeof__(lval)) _res; \
3877 } while (0)
3878
3879#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3880 do { \
3881 volatile OrigFn _orig = (orig); \
3882 volatile unsigned long _argvec[3+6]; \
3883 volatile unsigned long _res; \
3884 /* _argvec[0] holds current r2 across the call */ \
3885 _argvec[1] = (unsigned long)_orig.r2; \
3886 _argvec[2] = (unsigned long)_orig.nraddr; \
3887 _argvec[2+1] = (unsigned long)arg1; \
3888 _argvec[2+2] = (unsigned long)arg2; \
3889 _argvec[2+3] = (unsigned long)arg3; \
3890 _argvec[2+4] = (unsigned long)arg4; \
3891 _argvec[2+5] = (unsigned long)arg5; \
3892 _argvec[2+6] = (unsigned long)arg6; \
3893 __asm__ volatile( \
3894 "mr 11,%1\n\t" \
3895 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3896 "std 2,-16(11)\n\t" /* save tocptr */ \
3897 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3898 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3899 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3900 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3901 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3902 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3903 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3904 "ld 11, 0(11)\n\t" /* target->r11 */ \
3905 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3906 "mr 11,%1\n\t" \
3907 "mr %0,3\n\t" \
3908 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3909 VG_CONTRACT_FRAME_BY(512) \
3910 : /*out*/ "=r" (_res) \
3911 : /*in*/ "r" (&_argvec[2]) \
3912 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3913 ); \
3914 lval = (__typeof__(lval)) _res; \
3915 } while (0)
3916
3917#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3918 arg7) \
3919 do { \
3920 volatile OrigFn _orig = (orig); \
3921 volatile unsigned long _argvec[3+7]; \
3922 volatile unsigned long _res; \
3923 /* _argvec[0] holds current r2 across the call */ \
3924 _argvec[1] = (unsigned long)_orig.r2; \
3925 _argvec[2] = (unsigned long)_orig.nraddr; \
3926 _argvec[2+1] = (unsigned long)arg1; \
3927 _argvec[2+2] = (unsigned long)arg2; \
3928 _argvec[2+3] = (unsigned long)arg3; \
3929 _argvec[2+4] = (unsigned long)arg4; \
3930 _argvec[2+5] = (unsigned long)arg5; \
3931 _argvec[2+6] = (unsigned long)arg6; \
3932 _argvec[2+7] = (unsigned long)arg7; \
3933 __asm__ volatile( \
3934 "mr 11,%1\n\t" \
3935 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3936 "std 2,-16(11)\n\t" /* save tocptr */ \
3937 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3938 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3939 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3940 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3941 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3942 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3943 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3944 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3945 "ld 11, 0(11)\n\t" /* target->r11 */ \
3946 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3947 "mr 11,%1\n\t" \
3948 "mr %0,3\n\t" \
3949 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3950 VG_CONTRACT_FRAME_BY(512) \
3951 : /*out*/ "=r" (_res) \
3952 : /*in*/ "r" (&_argvec[2]) \
3953 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3954 ); \
3955 lval = (__typeof__(lval)) _res; \
3956 } while (0)
3957
3958#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3959 arg7,arg8) \
3960 do { \
3961 volatile OrigFn _orig = (orig); \
3962 volatile unsigned long _argvec[3+8]; \
3963 volatile unsigned long _res; \
3964 /* _argvec[0] holds current r2 across the call */ \
3965 _argvec[1] = (unsigned long)_orig.r2; \
3966 _argvec[2] = (unsigned long)_orig.nraddr; \
3967 _argvec[2+1] = (unsigned long)arg1; \
3968 _argvec[2+2] = (unsigned long)arg2; \
3969 _argvec[2+3] = (unsigned long)arg3; \
3970 _argvec[2+4] = (unsigned long)arg4; \
3971 _argvec[2+5] = (unsigned long)arg5; \
3972 _argvec[2+6] = (unsigned long)arg6; \
3973 _argvec[2+7] = (unsigned long)arg7; \
3974 _argvec[2+8] = (unsigned long)arg8; \
3975 __asm__ volatile( \
3976 "mr 11,%1\n\t" \
3977 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3978 "std 2,-16(11)\n\t" /* save tocptr */ \
3979 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3980 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3981 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3982 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3983 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3984 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3985 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3986 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3987 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3988 "ld 11, 0(11)\n\t" /* target->r11 */ \
3989 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3990 "mr 11,%1\n\t" \
3991 "mr %0,3\n\t" \
3992 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3993 VG_CONTRACT_FRAME_BY(512) \
3994 : /*out*/ "=r" (_res) \
3995 : /*in*/ "r" (&_argvec[2]) \
3996 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3997 ); \
3998 lval = (__typeof__(lval)) _res; \
3999 } while (0)
4000
4001#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4002 arg7,arg8,arg9) \
4003 do { \
4004 volatile OrigFn _orig = (orig); \
4005 volatile unsigned long _argvec[3+9]; \
4006 volatile unsigned long _res; \
4007 /* _argvec[0] holds current r2 across the call */ \
4008 _argvec[1] = (unsigned long)_orig.r2; \
4009 _argvec[2] = (unsigned long)_orig.nraddr; \
4010 _argvec[2+1] = (unsigned long)arg1; \
4011 _argvec[2+2] = (unsigned long)arg2; \
4012 _argvec[2+3] = (unsigned long)arg3; \
4013 _argvec[2+4] = (unsigned long)arg4; \
4014 _argvec[2+5] = (unsigned long)arg5; \
4015 _argvec[2+6] = (unsigned long)arg6; \
4016 _argvec[2+7] = (unsigned long)arg7; \
4017 _argvec[2+8] = (unsigned long)arg8; \
4018 _argvec[2+9] = (unsigned long)arg9; \
4019 __asm__ volatile( \
4020 "mr 11,%1\n\t" \
4021 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4022 "std 2,-16(11)\n\t" /* save tocptr */ \
4023 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4024 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4025 /* arg9 */ \
4026 "ld 3,72(11)\n\t" \
4027 "std 3,112(1)\n\t" \
4028 /* args1-8 */ \
4029 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4030 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4031 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4032 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4033 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4034 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4035 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4036 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4037 "ld 11, 0(11)\n\t" /* target->r11 */ \
4038 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4039 "mr 11,%1\n\t" \
4040 "mr %0,3\n\t" \
4041 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4042 VG_CONTRACT_FRAME_BY(128) \
4043 VG_CONTRACT_FRAME_BY(512) \
4044 : /*out*/ "=r" (_res) \
4045 : /*in*/ "r" (&_argvec[2]) \
4046 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4047 ); \
4048 lval = (__typeof__(lval)) _res; \
4049 } while (0)
4050
4051#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4052 arg7,arg8,arg9,arg10) \
4053 do { \
4054 volatile OrigFn _orig = (orig); \
4055 volatile unsigned long _argvec[3+10]; \
4056 volatile unsigned long _res; \
4057 /* _argvec[0] holds current r2 across the call */ \
4058 _argvec[1] = (unsigned long)_orig.r2; \
4059 _argvec[2] = (unsigned long)_orig.nraddr; \
4060 _argvec[2+1] = (unsigned long)arg1; \
4061 _argvec[2+2] = (unsigned long)arg2; \
4062 _argvec[2+3] = (unsigned long)arg3; \
4063 _argvec[2+4] = (unsigned long)arg4; \
4064 _argvec[2+5] = (unsigned long)arg5; \
4065 _argvec[2+6] = (unsigned long)arg6; \
4066 _argvec[2+7] = (unsigned long)arg7; \
4067 _argvec[2+8] = (unsigned long)arg8; \
4068 _argvec[2+9] = (unsigned long)arg9; \
4069 _argvec[2+10] = (unsigned long)arg10; \
4070 __asm__ volatile( \
4071 "mr 11,%1\n\t" \
4072 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4073 "std 2,-16(11)\n\t" /* save tocptr */ \
4074 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4075 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4076 /* arg10 */ \
4077 "ld 3,80(11)\n\t" \
4078 "std 3,120(1)\n\t" \
4079 /* arg9 */ \
4080 "ld 3,72(11)\n\t" \
4081 "std 3,112(1)\n\t" \
4082 /* args1-8 */ \
4083 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4084 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4085 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4086 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4087 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4088 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4089 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4090 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4091 "ld 11, 0(11)\n\t" /* target->r11 */ \
4092 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4093 "mr 11,%1\n\t" \
4094 "mr %0,3\n\t" \
4095 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4096 VG_CONTRACT_FRAME_BY(128) \
4097 VG_CONTRACT_FRAME_BY(512) \
4098 : /*out*/ "=r" (_res) \
4099 : /*in*/ "r" (&_argvec[2]) \
4100 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4101 ); \
4102 lval = (__typeof__(lval)) _res; \
4103 } while (0)
4104
4105#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4106 arg7,arg8,arg9,arg10,arg11) \
4107 do { \
4108 volatile OrigFn _orig = (orig); \
4109 volatile unsigned long _argvec[3+11]; \
4110 volatile unsigned long _res; \
4111 /* _argvec[0] holds current r2 across the call */ \
4112 _argvec[1] = (unsigned long)_orig.r2; \
4113 _argvec[2] = (unsigned long)_orig.nraddr; \
4114 _argvec[2+1] = (unsigned long)arg1; \
4115 _argvec[2+2] = (unsigned long)arg2; \
4116 _argvec[2+3] = (unsigned long)arg3; \
4117 _argvec[2+4] = (unsigned long)arg4; \
4118 _argvec[2+5] = (unsigned long)arg5; \
4119 _argvec[2+6] = (unsigned long)arg6; \
4120 _argvec[2+7] = (unsigned long)arg7; \
4121 _argvec[2+8] = (unsigned long)arg8; \
4122 _argvec[2+9] = (unsigned long)arg9; \
4123 _argvec[2+10] = (unsigned long)arg10; \
4124 _argvec[2+11] = (unsigned long)arg11; \
4125 __asm__ volatile( \
4126 "mr 11,%1\n\t" \
4127 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4128 "std 2,-16(11)\n\t" /* save tocptr */ \
4129 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4130 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4131 /* arg11 */ \
4132 "ld 3,88(11)\n\t" \
4133 "std 3,128(1)\n\t" \
4134 /* arg10 */ \
4135 "ld 3,80(11)\n\t" \
4136 "std 3,120(1)\n\t" \
4137 /* arg9 */ \
4138 "ld 3,72(11)\n\t" \
4139 "std 3,112(1)\n\t" \
4140 /* args1-8 */ \
4141 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4142 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4143 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4144 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4145 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4146 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4147 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4148 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4149 "ld 11, 0(11)\n\t" /* target->r11 */ \
4150 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4151 "mr 11,%1\n\t" \
4152 "mr %0,3\n\t" \
4153 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4154 VG_CONTRACT_FRAME_BY(144) \
4155 VG_CONTRACT_FRAME_BY(512) \
4156 : /*out*/ "=r" (_res) \
4157 : /*in*/ "r" (&_argvec[2]) \
4158 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4159 ); \
4160 lval = (__typeof__(lval)) _res; \
4161 } while (0)
4162
4163#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4164 arg7,arg8,arg9,arg10,arg11,arg12) \
4165 do { \
4166 volatile OrigFn _orig = (orig); \
4167 volatile unsigned long _argvec[3+12]; \
4168 volatile unsigned long _res; \
4169 /* _argvec[0] holds current r2 across the call */ \
4170 _argvec[1] = (unsigned long)_orig.r2; \
4171 _argvec[2] = (unsigned long)_orig.nraddr; \
4172 _argvec[2+1] = (unsigned long)arg1; \
4173 _argvec[2+2] = (unsigned long)arg2; \
4174 _argvec[2+3] = (unsigned long)arg3; \
4175 _argvec[2+4] = (unsigned long)arg4; \
4176 _argvec[2+5] = (unsigned long)arg5; \
4177 _argvec[2+6] = (unsigned long)arg6; \
4178 _argvec[2+7] = (unsigned long)arg7; \
4179 _argvec[2+8] = (unsigned long)arg8; \
4180 _argvec[2+9] = (unsigned long)arg9; \
4181 _argvec[2+10] = (unsigned long)arg10; \
4182 _argvec[2+11] = (unsigned long)arg11; \
4183 _argvec[2+12] = (unsigned long)arg12; \
4184 __asm__ volatile( \
4185 "mr 11,%1\n\t" \
4186 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4187 "std 2,-16(11)\n\t" /* save tocptr */ \
4188 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4189 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4190 /* arg12 */ \
4191 "ld 3,96(11)\n\t" \
4192 "std 3,136(1)\n\t" \
4193 /* arg11 */ \
4194 "ld 3,88(11)\n\t" \
4195 "std 3,128(1)\n\t" \
4196 /* arg10 */ \
4197 "ld 3,80(11)\n\t" \
4198 "std 3,120(1)\n\t" \
4199 /* arg9 */ \
4200 "ld 3,72(11)\n\t" \
4201 "std 3,112(1)\n\t" \
4202 /* args1-8 */ \
4203 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4204 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4205 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4206 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4207 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4208 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4209 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4210 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4211 "ld 11, 0(11)\n\t" /* target->r11 */ \
4212 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4213 "mr 11,%1\n\t" \
4214 "mr %0,3\n\t" \
4215 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4216 VG_CONTRACT_FRAME_BY(144) \
4217 VG_CONTRACT_FRAME_BY(512) \
4218 : /*out*/ "=r" (_res) \
4219 : /*in*/ "r" (&_argvec[2]) \
4220 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4221 ); \
4222 lval = (__typeof__(lval)) _res; \
4223 } while (0)
4224
4225#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00004226
sewardj0ec07f32006-01-12 12:32:32 +00004227
4228/* ------------------------------------------------------------------ */
4229/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4230/* */
njn30d76c62005-06-18 15:07:39 +00004231/* ------------------------------------------------------------------ */
4232
sewardj2e93c502002-04-12 11:12:52 +00004233/* Some request codes. There are many more of these, but most are not
4234 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004235 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004236
sewardj0ec07f32006-01-12 12:32:32 +00004237 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4238 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004239*/
4240
sewardj0ec07f32006-01-12 12:32:32 +00004241/* These macros are used by tools -- they must be public, but don't
4242 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004243#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004244 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004245#define VG_IS_TOOL_USERREQ(a, b, v) \
4246 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004247
sewardj5ce4b152006-03-11 12:57:41 +00004248/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4249 This enum comprises an ABI exported by Valgrind to programs
4250 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4251 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004252typedef
njn4c791212003-05-02 17:53:54 +00004253 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4254 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004255
sewardj0ec07f32006-01-12 12:32:32 +00004256 /* These allow any function to be called from the simulated
4257 CPU but run on the real CPU. Nb: the first arg passed to
4258 the function is always the ThreadId of the running
4259 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004260 function, etc. */
njn4c791212003-05-02 17:53:54 +00004261 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4262 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4263 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4264 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004265
sewardj0ec07f32006-01-12 12:32:32 +00004266 /* Can be useful in regression testing suites -- eg. can
4267 send Valgrind's output to /dev/null and still count
4268 errors. */
njn4c791212003-05-02 17:53:54 +00004269 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004270
sewardj0ec07f32006-01-12 12:32:32 +00004271 /* These are useful and can be interpreted by any tool that
4272 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004273 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4274 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004275 /* Memory pool support. */
4276 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4277 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4278 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4279 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004280 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004281 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4282 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4283 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004284
fitzhardinge39de4b42003-10-31 07:12:21 +00004285 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00004286 /* The first two pass the va_list argument by value, which
4287 assumes it is the same size as or smaller than a UWord,
4288 which generally isn't the case. Hence are deprecated.
4289 The second two pass the vargs by reference and so are
4290 immune to this problem. */
4291 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00004292 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004293 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00004294 /* both :: char* fmt, va_list* vargs */
4295 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4296 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00004297
4298 /* Stack support. */
4299 VG_USERREQ__STACK_REGISTER = 0x1501,
4300 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004301 VG_USERREQ__STACK_CHANGE = 0x1503,
4302
4303 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00004304 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
4305
4306 /* Querying of debug info. */
4307 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701
njn25e49d8e72002-09-23 09:36:25 +00004308 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004309
sewardj0ec07f32006-01-12 12:32:32 +00004310#if !defined(__GNUC__)
4311# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004312#endif
sewardj2e93c502002-04-12 11:12:52 +00004313
bartfa5115a2010-09-02 09:33:02 +00004314
4315/*
4316 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
4317 * client request and whose value equals the client request result.
4318 */
4319
4320#if defined(NVALGRIND)
4321
4322#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4323 _zzq_default, _zzq_request, \
4324 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4325 (_zzq_default)
4326
4327#else /*defined(NVALGRIND)*/
4328
4329#if defined(_MSC_VER)
4330
4331#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4332 _zzq_default, _zzq_request, \
4333 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4334 (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \
4335 (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \
4336 (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \
4337 (uintptr_t)(_zzq_arg5)))
4338
4339static __inline unsigned
4340vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default,
4341 unsigned _zzq_request, uintptr_t _zzq_arg1,
4342 uintptr_t _zzq_arg2, uintptr_t _zzq_arg3,
4343 uintptr_t _zzq_arg4, uintptr_t _zzq_arg5)
4344{
4345 unsigned _zzq_rlval;
4346 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request,
4347 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5);
4348 return _zzq_rlval;
4349}
4350
4351#else /*defined(_MSC_VER)*/
4352
4353#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4354 _zzq_default, _zzq_request, \
4355 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4356 (__extension__({unsigned int _zzq_rlval; \
4357 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \
4358 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4359 _zzq_rlval; \
4360 }))
4361
4362#endif /*defined(_MSC_VER)*/
4363
4364#endif /*defined(NVALGRIND)*/
4365
4366
sewardj0ec07f32006-01-12 12:32:32 +00004367/* Returns the number of Valgrinds this code is running under. That
4368 is, 0 if running natively, 1 if running under Valgrind, 2 if
4369 running under Valgrind which is running under another Valgrind,
4370 etc. */
bartfa5115a2010-09-02 09:33:02 +00004371#define RUNNING_ON_VALGRIND \
4372 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
4373 VG_USERREQ__RUNNING_ON_VALGRIND, \
4374 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00004375
4376
sewardj18d75132002-05-16 11:06:21 +00004377/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4378 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4379 since it provides a way to make sure valgrind will retranslate the
4380 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00004381#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4382 {unsigned int _qzz_res; \
4383 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4384 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00004385 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00004386 }
4387
njn26aba4d2005-05-16 13:31:23 +00004388
sewardj0ec07f32006-01-12 12:32:32 +00004389/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004390 Possibly with a backtrace. This is a really ugly hack. The return value
4391 is the number of characters printed, excluding the "**<pid>** " part at the
4392 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004393
4394#if defined(NVALGRIND)
4395
4396# define VALGRIND_PRINTF(...)
4397# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00004398
4399#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004400
bart7f489812010-08-27 10:05:27 +00004401#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004402/* Modern GCC will optimize the static routine out if unused,
4403 and unused attribute will shut down warnings about it. */
4404static int VALGRIND_PRINTF(const char *format, ...)
4405 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004406#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004407static int
bart0da2c772010-09-01 10:18:36 +00004408#if defined(_MSC_VER)
4409__inline
4410#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004411VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004412{
njnc6168192004-11-29 13:54:10 +00004413 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004414 va_list vargs;
4415 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004416#if defined(_MSC_VER)
4417 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4418 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004419 (uintptr_t)format,
4420 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004421 0, 0, 0);
4422#else
sewardjc560fb32010-01-28 15:23:54 +00004423 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4424 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004425 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004426 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004427 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004428#endif
sewardjc560fb32010-01-28 15:23:54 +00004429 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004430 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004431}
4432
bart7f489812010-08-27 10:05:27 +00004433#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004434static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4435 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004436#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004437static int
bart0da2c772010-09-01 10:18:36 +00004438#if defined(_MSC_VER)
4439__inline
4440#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004441VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004442{
njnc6168192004-11-29 13:54:10 +00004443 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004444 va_list vargs;
4445 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004446#if defined(_MSC_VER)
4447 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4448 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004449 (uintptr_t)format,
4450 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004451 0, 0, 0);
4452#else
sewardjc560fb32010-01-28 15:23:54 +00004453 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4454 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004455 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004456 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004457 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004458#endif
sewardjc560fb32010-01-28 15:23:54 +00004459 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004460 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004461}
4462
fitzhardinge39de4b42003-10-31 07:12:21 +00004463#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00004464
sewardj0ec07f32006-01-12 12:32:32 +00004465
njn3e884182003-04-15 13:03:23 +00004466/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004467 real CPU, calling an arbitary function.
4468
4469 Note that the current ThreadId is inserted as the first argument.
4470 So this call:
4471
4472 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4473
4474 requires f to have this signature:
4475
4476 Word f(Word tid, Word arg1, Word arg2)
4477
4478 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004479
4480 Note that these client requests are not entirely reliable. For example,
4481 if you call a function with them that subsequently calls printf(),
4482 there's a high chance Valgrind will crash. Generally, your prospects of
4483 these working are made higher if the called function does not refer to
4484 any global variables, and does not refer to any libc or other functions
4485 (printf et al). Any kind of entanglement with libc or dynamic linking is
4486 likely to have a bad outcome, for tricky reasons which we've grappled
4487 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004488*/
sewardj0ec07f32006-01-12 12:32:32 +00004489#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00004490 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004491 ({unsigned long _qyy_res; \
4492 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4493 VG_USERREQ__CLIENT_CALL0, \
4494 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004495 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004496 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004497 })
4498
sewardj0ec07f32006-01-12 12:32:32 +00004499#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00004500 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004501 ({unsigned long _qyy_res; \
4502 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4503 VG_USERREQ__CLIENT_CALL1, \
4504 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004505 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004506 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004507 })
4508
sewardj0ec07f32006-01-12 12:32:32 +00004509#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00004510 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004511 ({unsigned long _qyy_res; \
4512 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4513 VG_USERREQ__CLIENT_CALL2, \
4514 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004515 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004516 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004517 })
4518
sewardj0ec07f32006-01-12 12:32:32 +00004519#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00004520 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004521 ({unsigned long _qyy_res; \
4522 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4523 VG_USERREQ__CLIENT_CALL3, \
4524 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004525 _qyy_arg1, _qyy_arg2, \
4526 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004527 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004528 })
4529
4530
nethercote7cc9c232004-01-21 15:08:04 +00004531/* Counts the number of errors that have been recorded by a tool. Nb:
4532 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004533 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004534#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00004535 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004536 ({unsigned int _qyy_res; \
4537 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4538 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00004539 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004540 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00004541 })
4542
njn3ac96952009-07-09 23:35:44 +00004543/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4544 when heap blocks are allocated in order to give accurate results. This
4545 happens automatically for the standard allocator functions such as
4546 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4547 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004548
njn3ac96952009-07-09 23:35:44 +00004549 But if your program uses a custom allocator, this doesn't automatically
4550 happen, and Valgrind will not do as well. For example, if you allocate
4551 superblocks with mmap() and then allocates chunks of the superblocks, all
4552 Valgrind's observations will be at the mmap() level and it won't know that
4553 the chunks should be considered separate entities. In Memcheck's case,
4554 that means you probably won't get heap block overrun detection (because
4555 there won't be redzones marked as unaddressable) and you definitely won't
4556 get any leak detection.
4557
4558 The following client requests allow a custom allocator to be annotated so
4559 that it can be handled accurately by Valgrind.
4560
4561 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4562 by a malloc()-like function. For Memcheck (an illustrative case), this
4563 does two things:
4564
4565 - It records that the block has been allocated. This means any addresses
4566 within the block mentioned in error messages will be
4567 identified as belonging to the block. It also means that if the block
4568 isn't freed it will be detected by the leak checker.
4569
4570 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4571 not set), or addressable and defined (if 'is_zeroed' is set). This
4572 controls how accesses to the block by the program are handled.
4573
4574 'addr' is the start of the usable block (ie. after any
4575 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4576 can apply redzones -- these are blocks of padding at the start and end of
4577 each block. Adding redzones is recommended as it makes it much more likely
4578 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4579 zeroed (or filled with another predictable value), as is the case for
4580 calloc().
4581
4582 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4583 heap block -- that will be used by the client program -- is allocated.
4584 It's best to put it at the outermost level of the allocator if possible;
4585 for example, if you have a function my_alloc() which calls
4586 internal_alloc(), and the client request is put inside internal_alloc(),
4587 stack traces relating to the heap block will contain entries for both
4588 my_alloc() and internal_alloc(), which is probably not what you want.
4589
njnb965efb2009-08-10 07:36:54 +00004590 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4591 custom blocks from within a heap block, B, that has been allocated with
4592 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4593 -- the custom blocks will take precedence.
4594
njn3ac96952009-07-09 23:35:44 +00004595 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4596 Memcheck, it does two things:
4597
4598 - It records that the block has been deallocated. This assumes that the
4599 block was annotated as having been allocated via
4600 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4601
4602 - It marks the block as being unaddressable.
4603
4604 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4605 heap block is deallocated.
4606
4607 In many cases, these two client requests will not be enough to get your
4608 allocator working well with Memcheck. More specifically, if your allocator
4609 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4610 will be necessary to mark the memory as addressable just before the zeroing
4611 occurs, otherwise you'll get a lot of invalid write errors. For example,
4612 you'll need to do this if your allocator recycles freed blocks, but it
4613 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4614 Alternatively, if your allocator reuses freed blocks for allocator-internal
4615 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4616
4617 Really, what's happening is a blurring of the lines between the client
4618 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4619 memory should be considered unaddressable to the client program, but the
4620 allocator knows more than the rest of the client program and so may be able
4621 to safely access it. Extra client requests are necessary for Valgrind to
4622 understand the distinction between the allocator and the rest of the
4623 program.
4624
4625 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4626 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4627
njn32f8d8c2009-07-15 02:31:45 +00004628 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004629*/
sewardj0ec07f32006-01-12 12:32:32 +00004630#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4631 {unsigned int _qzz_res; \
4632 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4633 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004634 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00004635 }
4636
njn32f8d8c2009-07-15 02:31:45 +00004637/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4638 Ignored if addr == 0.
4639*/
sewardj0ec07f32006-01-12 12:32:32 +00004640#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4641 {unsigned int _qzz_res; \
4642 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4643 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004644 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00004645 }
4646
rjwalshbc0bb832004-06-19 18:12:36 +00004647/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004648#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4649 {unsigned int _qzz_res; \
4650 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4651 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004652 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004653 }
4654
4655/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004656#define VALGRIND_DESTROY_MEMPOOL(pool) \
4657 {unsigned int _qzz_res; \
4658 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4659 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004660 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004661 }
4662
4663/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004664#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4665 {unsigned int _qzz_res; \
4666 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4667 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00004668 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004669 }
4670
4671/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004672#define VALGRIND_MEMPOOL_FREE(pool, addr) \
4673 {unsigned int _qzz_res; \
4674 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4675 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00004676 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004677 }
4678
sewardj2c1c9df2006-07-28 00:06:37 +00004679/* Disassociate any pieces outside a particular range. */
4680#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4681 {unsigned int _qzz_res; \
4682 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4683 VG_USERREQ__MEMPOOL_TRIM, \
4684 pool, addr, size, 0, 0); \
4685 }
4686
sewardjc740d762006-10-05 17:59:23 +00004687/* Resize and/or move a piece associated with a memory pool. */
4688#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4689 {unsigned int _qzz_res; \
4690 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4691 VG_USERREQ__MOVE_MEMPOOL, \
4692 poolA, poolB, 0, 0, 0); \
4693 }
4694
4695/* Resize and/or move a piece associated with a memory pool. */
4696#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4697 {unsigned int _qzz_res; \
4698 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4699 VG_USERREQ__MEMPOOL_CHANGE, \
4700 pool, addrA, addrB, size, 0); \
4701 }
4702
4703/* Return 1 if a mempool exists, else 0. */
4704#define VALGRIND_MEMPOOL_EXISTS(pool) \
njn44862972009-02-23 02:08:24 +00004705 __extension__ \
sewardjc740d762006-10-05 17:59:23 +00004706 ({unsigned int _qzz_res; \
4707 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4708 VG_USERREQ__MEMPOOL_EXISTS, \
4709 pool, 0, 0, 0, 0); \
4710 _qzz_res; \
4711 })
4712
rjwalsh0140af52005-06-04 20:42:33 +00004713/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004714#define VALGRIND_STACK_REGISTER(start, end) \
njn44862972009-02-23 02:08:24 +00004715 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004716 ({unsigned int _qzz_res; \
4717 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4718 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004719 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004720 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00004721 })
4722
4723/* Unmark the piece of memory associated with a stack id as being a
4724 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004725#define VALGRIND_STACK_DEREGISTER(id) \
4726 {unsigned int _qzz_res; \
4727 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4728 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004729 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004730 }
4731
4732/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004733#define VALGRIND_STACK_CHANGE(id, start, end) \
4734 {unsigned int _qzz_res; \
4735 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4736 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00004737 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004738 }
4739
sewardjc8259b82009-04-22 22:42:10 +00004740/* Load PDB debug info for Wine PE image_map. */
4741#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4742 {unsigned int _qzz_res; \
4743 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4744 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4745 fd, ptr, total_size, delta, 0); \
4746 }
4747
sewardj5c659622010-08-20 18:22:07 +00004748/* Map a code address to a source file name and line number. buf64
4749 must point to a 64-byte buffer in the caller's address space. The
4750 result will be dumped in there and is guaranteed to be zero
4751 terminated. If no info is found, the first byte is set to zero. */
4752#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
4753 {unsigned int _qzz_res; \
4754 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4755 VG_USERREQ__MAP_IP_TO_SRCLOC, \
4756 addr, buf64, 0, 0, 0); \
4757 }
4758
sewardj0ec07f32006-01-12 12:32:32 +00004759
sewardjf5c1a7f2006-10-17 01:32:48 +00004760#undef PLAT_x86_linux
4761#undef PLAT_amd64_linux
4762#undef PLAT_ppc32_linux
4763#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004764#undef PLAT_arm_linux
sewardjf5c1a7f2006-10-17 01:32:48 +00004765#undef PLAT_ppc32_aix5
4766#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00004767
njn3e884182003-04-15 13:03:23 +00004768#endif /* __VALGRIND_H */