blob: 85cb0746e89772c0a057848f311439f6107b7df9 [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
bart7f489812010-08-27 10:05:27 +0000207#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) || defined(PLAT_x86_win32) && defined(__GNUC__)
sewardjc8858442006-01-20 15:17:20 +0000208
209typedef
210 struct {
211 unsigned int nraddr; /* where's the code? */
212 }
213 OrigFn;
214
sewardj0ec07f32006-01-12 12:32:32 +0000215#define __SPECIAL_INSTRUCTION_PREAMBLE \
216 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000217 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000218
sewardj0ec07f32006-01-12 12:32:32 +0000219#define VALGRIND_DO_CLIENT_REQUEST( \
220 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000221 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
222 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000223 volatile unsigned int _zzq_result; \
224 _zzq_args[0] = (unsigned int)(_zzq_request); \
225 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
226 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
227 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
228 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000229 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000230 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
231 /* %EDX = client_request ( %EAX ) */ \
232 "xchgl %%ebx,%%ebx" \
233 : "=d" (_zzq_result) \
234 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
235 : "cc", "memory" \
236 ); \
237 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000238 }
sewardj2c48c7b2005-11-29 13:05:56 +0000239
sewardjc8858442006-01-20 15:17:20 +0000240#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
241 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
242 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000243 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
244 /* %EAX = guest_NRADDR */ \
245 "xchgl %%ecx,%%ecx" \
246 : "=a" (__addr) \
247 : \
248 : "cc", "memory" \
249 ); \
sewardjc8858442006-01-20 15:17:20 +0000250 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000251 }
sewardj0ec07f32006-01-12 12:32:32 +0000252
253#define VALGRIND_CALL_NOREDIR_EAX \
254 __SPECIAL_INSTRUCTION_PREAMBLE \
255 /* call-noredir *%EAX */ \
256 "xchgl %%edx,%%edx\n\t"
bart7f489812010-08-27 10:05:27 +0000257#endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_win32 && __GNUC__ */
258
259/* ------------------------- x86-Win32 ------------------------- */
260
261#if defined(PLAT_x86_win32) && !defined(__GNUC__)
262
263typedef
264 struct {
265 unsigned int nraddr; /* where's the code? */
266 }
267 OrigFn;
268
269#if defined(_MSC_VER)
270
271#define __SPECIAL_INSTRUCTION_PREAMBLE \
272 __asm rol edi, 3 __asm rol edi, 13 \
273 __asm rol edi, 29 __asm rol edi, 19
274
275#define VALGRIND_DO_CLIENT_REQUEST( \
276 _zzq_rlval, _zzq_default, _zzq_request, \
277 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bartfa5115a2010-09-02 09:33:02 +0000278 { volatile uintptr_t _zzq_args[6]; \
bart7f489812010-08-27 10:05:27 +0000279 volatile unsigned int _zzq_result; \
bartfa5115a2010-09-02 09:33:02 +0000280 _zzq_args[0] = (uintptr_t)(_zzq_request); \
281 _zzq_args[1] = (uintptr_t)(_zzq_arg1); \
282 _zzq_args[2] = (uintptr_t)(_zzq_arg2); \
283 _zzq_args[3] = (uintptr_t)(_zzq_arg3); \
284 _zzq_args[4] = (uintptr_t)(_zzq_arg4); \
285 _zzq_args[5] = (uintptr_t)(_zzq_arg5); \
bart7f489812010-08-27 10:05:27 +0000286 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default \
287 __SPECIAL_INSTRUCTION_PREAMBLE \
288 /* %EDX = client_request ( %EAX ) */ \
289 __asm xchg ebx,ebx \
290 __asm mov _zzq_result, edx \
291 } \
292 _zzq_rlval = _zzq_result; \
293 }
294
295#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
296 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
297 volatile unsigned int __addr; \
298 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
299 /* %EAX = guest_NRADDR */ \
300 __asm xchg ecx,ecx \
301 __asm mov __addr, eax \
302 } \
303 _zzq_orig->nraddr = __addr; \
304 }
305
306#define VALGRIND_CALL_NOREDIR_EAX ERROR
307
308#else
309#error Unsupported compiler.
310#endif
311
312#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000313
njnf76d27a2009-05-28 01:53:07 +0000314/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000315
njnf76d27a2009-05-28 01:53:07 +0000316#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000317
318typedef
319 struct {
320 unsigned long long int nraddr; /* where's the code? */
321 }
322 OrigFn;
323
sewardj0ec07f32006-01-12 12:32:32 +0000324#define __SPECIAL_INSTRUCTION_PREAMBLE \
325 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000326 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000327
328#define VALGRIND_DO_CLIENT_REQUEST( \
329 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000330 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
331 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000332 volatile unsigned long long int _zzq_result; \
333 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
334 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
335 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
336 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
337 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000338 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000339 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
340 /* %RDX = client_request ( %RAX ) */ \
341 "xchgq %%rbx,%%rbx" \
342 : "=d" (_zzq_result) \
343 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
344 : "cc", "memory" \
345 ); \
346 _zzq_rlval = _zzq_result; \
347 }
348
sewardjc8858442006-01-20 15:17:20 +0000349#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
350 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
351 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000352 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
353 /* %RAX = guest_NRADDR */ \
354 "xchgq %%rcx,%%rcx" \
355 : "=a" (__addr) \
356 : \
357 : "cc", "memory" \
358 ); \
sewardjc8858442006-01-20 15:17:20 +0000359 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000360 }
361
362#define VALGRIND_CALL_NOREDIR_RAX \
363 __SPECIAL_INSTRUCTION_PREAMBLE \
364 /* call-noredir *%RAX */ \
365 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000366#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000367
sewardjf5c1a7f2006-10-17 01:32:48 +0000368/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000369
sewardjf5c1a7f2006-10-17 01:32:48 +0000370#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000371
372typedef
373 struct {
sewardjc8858442006-01-20 15:17:20 +0000374 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000375 }
376 OrigFn;
377
sewardj0ec07f32006-01-12 12:32:32 +0000378#define __SPECIAL_INSTRUCTION_PREAMBLE \
379 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000380 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000381
382#define VALGRIND_DO_CLIENT_REQUEST( \
383 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000384 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000385 \
sewardj9af10a12006-02-01 14:59:42 +0000386 { unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000387 unsigned int _zzq_result; \
388 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000389 _zzq_args[0] = (unsigned int)(_zzq_request); \
390 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
391 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
392 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
393 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000394 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000395 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000396 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
397 "mr 4,%2\n\t" /*ptr*/ \
398 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000399 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000400 "or 1,1,1\n\t" \
401 "mr %0,3" /*result*/ \
402 : "=b" (_zzq_result) \
403 : "b" (_zzq_default), "b" (_zzq_ptr) \
404 : "cc", "memory", "r3", "r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000405 _zzq_rlval = _zzq_result; \
406 }
407
sewardjd68ac3e2006-01-20 14:31:57 +0000408#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
409 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000410 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000411 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
412 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000413 "or 2,2,2\n\t" \
414 "mr %0,3" \
415 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000416 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000417 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000418 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000419 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000420 }
421
422#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
423 __SPECIAL_INSTRUCTION_PREAMBLE \
424 /* branch-and-link-to-noredir *%R11 */ \
425 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000426#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000427
sewardjf5c1a7f2006-10-17 01:32:48 +0000428/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000429
sewardjf5c1a7f2006-10-17 01:32:48 +0000430#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000431
432typedef
433 struct {
434 unsigned long long int nraddr; /* where's the code? */
435 unsigned long long int r2; /* what tocptr do we need? */
436 }
437 OrigFn;
438
sewardj1a85f4f2006-01-12 21:15:35 +0000439#define __SPECIAL_INSTRUCTION_PREAMBLE \
440 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
441 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
442
sewardj0ec07f32006-01-12 12:32:32 +0000443#define VALGRIND_DO_CLIENT_REQUEST( \
444 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000445 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000446 \
sewardj9af10a12006-02-01 14:59:42 +0000447 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000448 register unsigned long long int _zzq_result __asm__("r3"); \
449 register unsigned long long int* _zzq_ptr __asm__("r4"); \
450 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
451 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
452 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
453 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
454 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000455 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000456 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000457 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
458 /* %R3 = client_request ( %R4 ) */ \
459 "or 1,1,1" \
460 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000461 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000462 : "cc", "memory"); \
463 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000464 }
sewardj1a85f4f2006-01-12 21:15:35 +0000465
sewardjd68ac3e2006-01-20 14:31:57 +0000466#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
467 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
468 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000469 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
470 /* %R3 = guest_NRADDR */ \
471 "or 2,2,2" \
472 : "=r" (__addr) \
473 : \
474 : "cc", "memory" \
475 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000476 _zzq_orig->nraddr = __addr; \
477 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
478 /* %R3 = guest_NRADDR_GPR2 */ \
479 "or 4,4,4" \
480 : "=r" (__addr) \
481 : \
482 : "cc", "memory" \
483 ); \
484 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000485 }
486
487#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
488 __SPECIAL_INSTRUCTION_PREAMBLE \
489 /* branch-and-link-to-noredir *%R11 */ \
490 "or 3,3,3\n\t"
491
sewardjf5c1a7f2006-10-17 01:32:48 +0000492#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000493
sewardj59570ff2010-01-01 11:59:33 +0000494/* ------------------------- arm-linux ------------------------- */
495
496#if defined(PLAT_arm_linux)
497
498typedef
499 struct {
500 unsigned int nraddr; /* where's the code? */
501 }
502 OrigFn;
503
504#define __SPECIAL_INSTRUCTION_PREAMBLE \
505 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
506 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
507
508#define VALGRIND_DO_CLIENT_REQUEST( \
509 _zzq_rlval, _zzq_default, _zzq_request, \
510 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
511 \
512 { volatile unsigned int _zzq_args[6]; \
513 volatile unsigned int _zzq_result; \
514 _zzq_args[0] = (unsigned int)(_zzq_request); \
515 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
516 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
517 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
518 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
519 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
520 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
521 "mov r4, %2\n\t" /*ptr*/ \
522 __SPECIAL_INSTRUCTION_PREAMBLE \
523 /* R3 = client_request ( R4 ) */ \
524 "orr r10, r10, r10\n\t" \
525 "mov %0, r3" /*result*/ \
526 : "=r" (_zzq_result) \
527 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
528 : "cc","memory", "r3", "r4"); \
529 _zzq_rlval = _zzq_result; \
530 }
531
532#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
533 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
534 unsigned int __addr; \
535 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
536 /* R3 = guest_NRADDR */ \
537 "orr r11, r11, r11\n\t" \
538 "mov %0, r3" \
539 : "=r" (__addr) \
540 : \
541 : "cc", "memory", "r3" \
542 ); \
543 _zzq_orig->nraddr = __addr; \
544 }
545
546#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
547 __SPECIAL_INSTRUCTION_PREAMBLE \
548 /* branch-and-link-to-noredir *%R4 */ \
549 "orr r12, r12, r12\n\t"
550
551#endif /* PLAT_arm_linux */
552
sewardjf5c1a7f2006-10-17 01:32:48 +0000553/* ------------------------ ppc32-aix5 ------------------------- */
554
555#if defined(PLAT_ppc32_aix5)
556
557typedef
558 struct {
559 unsigned int nraddr; /* where's the code? */
560 unsigned int r2; /* what tocptr do we need? */
561 }
562 OrigFn;
563
564#define __SPECIAL_INSTRUCTION_PREAMBLE \
565 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
566 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
567
568#define VALGRIND_DO_CLIENT_REQUEST( \
569 _zzq_rlval, _zzq_default, _zzq_request, \
570 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
571 \
572 { unsigned int _zzq_args[7]; \
573 register unsigned int _zzq_result; \
574 register unsigned int* _zzq_ptr; \
575 _zzq_args[0] = (unsigned int)(_zzq_request); \
576 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
577 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
578 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
579 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
580 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
581 _zzq_args[6] = (unsigned int)(_zzq_default); \
582 _zzq_ptr = _zzq_args; \
583 __asm__ volatile("mr 4,%1\n\t" \
584 "lwz 3, 24(4)\n\t" \
585 __SPECIAL_INSTRUCTION_PREAMBLE \
586 /* %R3 = client_request ( %R4 ) */ \
587 "or 1,1,1\n\t" \
588 "mr %0,3" \
589 : "=b" (_zzq_result) \
590 : "b" (_zzq_ptr) \
591 : "r3", "r4", "cc", "memory"); \
592 _zzq_rlval = _zzq_result; \
593 }
594
595#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
596 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
597 register unsigned int __addr; \
598 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
599 /* %R3 = guest_NRADDR */ \
600 "or 2,2,2\n\t" \
601 "mr %0,3" \
602 : "=b" (__addr) \
603 : \
604 : "r3", "cc", "memory" \
605 ); \
606 _zzq_orig->nraddr = __addr; \
607 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
608 /* %R3 = guest_NRADDR_GPR2 */ \
609 "or 4,4,4\n\t" \
610 "mr %0,3" \
611 : "=b" (__addr) \
612 : \
613 : "r3", "cc", "memory" \
614 ); \
615 _zzq_orig->r2 = __addr; \
616 }
617
618#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
619 __SPECIAL_INSTRUCTION_PREAMBLE \
620 /* branch-and-link-to-noredir *%R11 */ \
621 "or 3,3,3\n\t"
622
623#endif /* PLAT_ppc32_aix5 */
624
625/* ------------------------ ppc64-aix5 ------------------------- */
626
627#if defined(PLAT_ppc64_aix5)
628
629typedef
630 struct {
631 unsigned long long int nraddr; /* where's the code? */
632 unsigned long long int r2; /* what tocptr do we need? */
633 }
634 OrigFn;
635
636#define __SPECIAL_INSTRUCTION_PREAMBLE \
637 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
638 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
639
640#define VALGRIND_DO_CLIENT_REQUEST( \
641 _zzq_rlval, _zzq_default, _zzq_request, \
642 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
643 \
644 { unsigned long long int _zzq_args[7]; \
645 register unsigned long long int _zzq_result; \
646 register unsigned long long int* _zzq_ptr; \
647 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
648 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
649 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
650 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
651 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
652 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
653 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
654 _zzq_ptr = _zzq_args; \
655 __asm__ volatile("mr 4,%1\n\t" \
656 "ld 3, 48(4)\n\t" \
657 __SPECIAL_INSTRUCTION_PREAMBLE \
658 /* %R3 = client_request ( %R4 ) */ \
659 "or 1,1,1\n\t" \
660 "mr %0,3" \
661 : "=b" (_zzq_result) \
662 : "b" (_zzq_ptr) \
663 : "r3", "r4", "cc", "memory"); \
664 _zzq_rlval = _zzq_result; \
665 }
666
667#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
668 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
669 register unsigned long long int __addr; \
670 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
671 /* %R3 = guest_NRADDR */ \
672 "or 2,2,2\n\t" \
673 "mr %0,3" \
674 : "=b" (__addr) \
675 : \
676 : "r3", "cc", "memory" \
677 ); \
678 _zzq_orig->nraddr = __addr; \
679 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
680 /* %R3 = guest_NRADDR_GPR2 */ \
681 "or 4,4,4\n\t" \
682 "mr %0,3" \
683 : "=b" (__addr) \
684 : \
685 : "r3", "cc", "memory" \
686 ); \
687 _zzq_orig->r2 = __addr; \
688 }
689
690#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
691 __SPECIAL_INSTRUCTION_PREAMBLE \
692 /* branch-and-link-to-noredir *%R11 */ \
693 "or 3,3,3\n\t"
694
695#endif /* PLAT_ppc64_aix5 */
696
697/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000698
sewardj37091fb2002-11-16 11:06:50 +0000699#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000700
nethercote69d9c462004-10-26 13:00:12 +0000701
njn30d76c62005-06-18 15:07:39 +0000702/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000703/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000704/* ugly. It's the least-worst tradeoff I can think of. */
705/* ------------------------------------------------------------------ */
706
707/* This section defines magic (a.k.a appalling-hack) macros for doing
708 guaranteed-no-redirection macros, so as to get from function
709 wrappers to the functions they are wrapping. The whole point is to
710 construct standard call sequences, but to do the call itself with a
711 special no-redirect call pseudo-instruction that the JIT
712 understands and handles specially. This section is long and
713 repetitious, and I can't see a way to make it shorter.
714
715 The naming scheme is as follows:
716
717 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
718
719 'W' stands for "word" and 'v' for "void". Hence there are
720 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
721 and for each, the possibility of returning a word-typed result, or
722 no result.
723*/
724
725/* Use these to write the name of your wrapper. NOTE: duplicates
726 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
727
njn5f5ef2a2009-05-11 08:01:09 +0000728/* Use an extra level of macroisation so as to ensure the soname/fnname
729 args are fully macro-expanded before pasting them together. */
730#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
731
sewardj0ec07f32006-01-12 12:32:32 +0000732#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000733 VG_CONCAT4(_vgwZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000734
735#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000736 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000737
sewardjd68ac3e2006-01-20 14:31:57 +0000738/* Use this macro from within a wrapper function to collect the
739 context (address and possibly other info) of the original function.
740 Once you have that you can then use it in one of the CALL_FN_
741 macros. The type of the argument _lval is OrigFn. */
742#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000743
744/* Derivatives of the main macros below, for calling functions
745 returning void. */
746
747#define CALL_FN_v_v(fnptr) \
748 do { volatile unsigned long _junk; \
749 CALL_FN_W_v(_junk,fnptr); } while (0)
750
751#define CALL_FN_v_W(fnptr, arg1) \
752 do { volatile unsigned long _junk; \
753 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
754
755#define CALL_FN_v_WW(fnptr, arg1,arg2) \
756 do { volatile unsigned long _junk; \
757 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
758
sewardj5ce4b152006-03-11 12:57:41 +0000759#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
760 do { volatile unsigned long _junk; \
761 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
762
njn2b5f0a92009-05-19 01:24:50 +0000763#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
764 do { volatile unsigned long _junk; \
765 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
766
767#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
768 do { volatile unsigned long _junk; \
769 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
770
771#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
772 do { volatile unsigned long _junk; \
773 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
774
775#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
776 do { volatile unsigned long _junk; \
777 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
778
njnf76d27a2009-05-28 01:53:07 +0000779/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000780
njnf76d27a2009-05-28 01:53:07 +0000781#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000782
783/* These regs are trashed by the hidden call. No need to mention eax
784 as gcc can already see that, plus causes gcc to bomb. */
785#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
786
787/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
788 long) == 4. */
789
sewardj66226cc2006-01-20 15:46:46 +0000790#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000791 do { \
sewardj66226cc2006-01-20 15:46:46 +0000792 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000793 volatile unsigned long _argvec[1]; \
794 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000795 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000796 __asm__ volatile( \
797 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
798 VALGRIND_CALL_NOREDIR_EAX \
799 : /*out*/ "=a" (_res) \
800 : /*in*/ "a" (&_argvec[0]) \
801 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
802 ); \
803 lval = (__typeof__(lval)) _res; \
804 } while (0)
805
sewardj66226cc2006-01-20 15:46:46 +0000806#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000807 do { \
sewardj66226cc2006-01-20 15:46:46 +0000808 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000809 volatile unsigned long _argvec[2]; \
810 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000811 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000812 _argvec[1] = (unsigned long)(arg1); \
813 __asm__ volatile( \
814 "pushl 4(%%eax)\n\t" \
815 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
816 VALGRIND_CALL_NOREDIR_EAX \
817 "addl $4, %%esp\n" \
818 : /*out*/ "=a" (_res) \
819 : /*in*/ "a" (&_argvec[0]) \
820 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
821 ); \
822 lval = (__typeof__(lval)) _res; \
823 } while (0)
824
sewardj66226cc2006-01-20 15:46:46 +0000825#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000826 do { \
sewardj66226cc2006-01-20 15:46:46 +0000827 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000828 volatile unsigned long _argvec[3]; \
829 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000830 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000831 _argvec[1] = (unsigned long)(arg1); \
832 _argvec[2] = (unsigned long)(arg2); \
833 __asm__ volatile( \
834 "pushl 8(%%eax)\n\t" \
835 "pushl 4(%%eax)\n\t" \
836 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
837 VALGRIND_CALL_NOREDIR_EAX \
838 "addl $8, %%esp\n" \
839 : /*out*/ "=a" (_res) \
840 : /*in*/ "a" (&_argvec[0]) \
841 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
842 ); \
843 lval = (__typeof__(lval)) _res; \
844 } while (0)
845
sewardj9e8b07a2006-02-18 21:13:29 +0000846#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
847 do { \
848 volatile OrigFn _orig = (orig); \
849 volatile unsigned long _argvec[4]; \
850 volatile unsigned long _res; \
851 _argvec[0] = (unsigned long)_orig.nraddr; \
852 _argvec[1] = (unsigned long)(arg1); \
853 _argvec[2] = (unsigned long)(arg2); \
854 _argvec[3] = (unsigned long)(arg3); \
855 __asm__ volatile( \
856 "pushl 12(%%eax)\n\t" \
857 "pushl 8(%%eax)\n\t" \
858 "pushl 4(%%eax)\n\t" \
859 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
860 VALGRIND_CALL_NOREDIR_EAX \
861 "addl $12, %%esp\n" \
862 : /*out*/ "=a" (_res) \
863 : /*in*/ "a" (&_argvec[0]) \
864 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
865 ); \
866 lval = (__typeof__(lval)) _res; \
867 } while (0)
868
sewardj66226cc2006-01-20 15:46:46 +0000869#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000870 do { \
sewardj66226cc2006-01-20 15:46:46 +0000871 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000872 volatile unsigned long _argvec[5]; \
873 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000874 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000875 _argvec[1] = (unsigned long)(arg1); \
876 _argvec[2] = (unsigned long)(arg2); \
877 _argvec[3] = (unsigned long)(arg3); \
878 _argvec[4] = (unsigned long)(arg4); \
879 __asm__ volatile( \
880 "pushl 16(%%eax)\n\t" \
881 "pushl 12(%%eax)\n\t" \
882 "pushl 8(%%eax)\n\t" \
883 "pushl 4(%%eax)\n\t" \
884 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
885 VALGRIND_CALL_NOREDIR_EAX \
886 "addl $16, %%esp\n" \
887 : /*out*/ "=a" (_res) \
888 : /*in*/ "a" (&_argvec[0]) \
889 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
890 ); \
891 lval = (__typeof__(lval)) _res; \
892 } while (0)
893
sewardj66226cc2006-01-20 15:46:46 +0000894#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000895 do { \
sewardj66226cc2006-01-20 15:46:46 +0000896 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000897 volatile unsigned long _argvec[6]; \
898 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000899 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000900 _argvec[1] = (unsigned long)(arg1); \
901 _argvec[2] = (unsigned long)(arg2); \
902 _argvec[3] = (unsigned long)(arg3); \
903 _argvec[4] = (unsigned long)(arg4); \
904 _argvec[5] = (unsigned long)(arg5); \
905 __asm__ volatile( \
906 "pushl 20(%%eax)\n\t" \
907 "pushl 16(%%eax)\n\t" \
908 "pushl 12(%%eax)\n\t" \
909 "pushl 8(%%eax)\n\t" \
910 "pushl 4(%%eax)\n\t" \
911 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
912 VALGRIND_CALL_NOREDIR_EAX \
913 "addl $20, %%esp\n" \
914 : /*out*/ "=a" (_res) \
915 : /*in*/ "a" (&_argvec[0]) \
916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
917 ); \
918 lval = (__typeof__(lval)) _res; \
919 } while (0)
920
sewardj66226cc2006-01-20 15:46:46 +0000921#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000922 do { \
sewardj66226cc2006-01-20 15:46:46 +0000923 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000924 volatile unsigned long _argvec[7]; \
925 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000926 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000927 _argvec[1] = (unsigned long)(arg1); \
928 _argvec[2] = (unsigned long)(arg2); \
929 _argvec[3] = (unsigned long)(arg3); \
930 _argvec[4] = (unsigned long)(arg4); \
931 _argvec[5] = (unsigned long)(arg5); \
932 _argvec[6] = (unsigned long)(arg6); \
933 __asm__ volatile( \
934 "pushl 24(%%eax)\n\t" \
935 "pushl 20(%%eax)\n\t" \
936 "pushl 16(%%eax)\n\t" \
937 "pushl 12(%%eax)\n\t" \
938 "pushl 8(%%eax)\n\t" \
939 "pushl 4(%%eax)\n\t" \
940 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
941 VALGRIND_CALL_NOREDIR_EAX \
942 "addl $24, %%esp\n" \
943 : /*out*/ "=a" (_res) \
944 : /*in*/ "a" (&_argvec[0]) \
945 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
946 ); \
947 lval = (__typeof__(lval)) _res; \
948 } while (0)
949
sewardj66226cc2006-01-20 15:46:46 +0000950#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
951 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000952 do { \
sewardj66226cc2006-01-20 15:46:46 +0000953 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000954 volatile unsigned long _argvec[8]; \
955 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000956 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000957 _argvec[1] = (unsigned long)(arg1); \
958 _argvec[2] = (unsigned long)(arg2); \
959 _argvec[3] = (unsigned long)(arg3); \
960 _argvec[4] = (unsigned long)(arg4); \
961 _argvec[5] = (unsigned long)(arg5); \
962 _argvec[6] = (unsigned long)(arg6); \
963 _argvec[7] = (unsigned long)(arg7); \
964 __asm__ volatile( \
965 "pushl 28(%%eax)\n\t" \
966 "pushl 24(%%eax)\n\t" \
967 "pushl 20(%%eax)\n\t" \
968 "pushl 16(%%eax)\n\t" \
969 "pushl 12(%%eax)\n\t" \
970 "pushl 8(%%eax)\n\t" \
971 "pushl 4(%%eax)\n\t" \
972 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
973 VALGRIND_CALL_NOREDIR_EAX \
974 "addl $28, %%esp\n" \
975 : /*out*/ "=a" (_res) \
976 : /*in*/ "a" (&_argvec[0]) \
977 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
978 ); \
979 lval = (__typeof__(lval)) _res; \
980 } while (0)
981
sewardj66226cc2006-01-20 15:46:46 +0000982#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
983 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000984 do { \
sewardj66226cc2006-01-20 15:46:46 +0000985 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000986 volatile unsigned long _argvec[9]; \
987 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000988 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000989 _argvec[1] = (unsigned long)(arg1); \
990 _argvec[2] = (unsigned long)(arg2); \
991 _argvec[3] = (unsigned long)(arg3); \
992 _argvec[4] = (unsigned long)(arg4); \
993 _argvec[5] = (unsigned long)(arg5); \
994 _argvec[6] = (unsigned long)(arg6); \
995 _argvec[7] = (unsigned long)(arg7); \
996 _argvec[8] = (unsigned long)(arg8); \
997 __asm__ volatile( \
998 "pushl 32(%%eax)\n\t" \
999 "pushl 28(%%eax)\n\t" \
1000 "pushl 24(%%eax)\n\t" \
1001 "pushl 20(%%eax)\n\t" \
1002 "pushl 16(%%eax)\n\t" \
1003 "pushl 12(%%eax)\n\t" \
1004 "pushl 8(%%eax)\n\t" \
1005 "pushl 4(%%eax)\n\t" \
1006 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1007 VALGRIND_CALL_NOREDIR_EAX \
1008 "addl $32, %%esp\n" \
1009 : /*out*/ "=a" (_res) \
1010 : /*in*/ "a" (&_argvec[0]) \
1011 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1012 ); \
1013 lval = (__typeof__(lval)) _res; \
1014 } while (0)
1015
sewardj45fa5b02006-03-09 19:06:23 +00001016#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1017 arg7,arg8,arg9) \
1018 do { \
1019 volatile OrigFn _orig = (orig); \
1020 volatile unsigned long _argvec[10]; \
1021 volatile unsigned long _res; \
1022 _argvec[0] = (unsigned long)_orig.nraddr; \
1023 _argvec[1] = (unsigned long)(arg1); \
1024 _argvec[2] = (unsigned long)(arg2); \
1025 _argvec[3] = (unsigned long)(arg3); \
1026 _argvec[4] = (unsigned long)(arg4); \
1027 _argvec[5] = (unsigned long)(arg5); \
1028 _argvec[6] = (unsigned long)(arg6); \
1029 _argvec[7] = (unsigned long)(arg7); \
1030 _argvec[8] = (unsigned long)(arg8); \
1031 _argvec[9] = (unsigned long)(arg9); \
1032 __asm__ volatile( \
1033 "pushl 36(%%eax)\n\t" \
1034 "pushl 32(%%eax)\n\t" \
1035 "pushl 28(%%eax)\n\t" \
1036 "pushl 24(%%eax)\n\t" \
1037 "pushl 20(%%eax)\n\t" \
1038 "pushl 16(%%eax)\n\t" \
1039 "pushl 12(%%eax)\n\t" \
1040 "pushl 8(%%eax)\n\t" \
1041 "pushl 4(%%eax)\n\t" \
1042 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1043 VALGRIND_CALL_NOREDIR_EAX \
1044 "addl $36, %%esp\n" \
1045 : /*out*/ "=a" (_res) \
1046 : /*in*/ "a" (&_argvec[0]) \
1047 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1048 ); \
1049 lval = (__typeof__(lval)) _res; \
1050 } while (0)
1051
1052#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1053 arg7,arg8,arg9,arg10) \
1054 do { \
1055 volatile OrigFn _orig = (orig); \
1056 volatile unsigned long _argvec[11]; \
1057 volatile unsigned long _res; \
1058 _argvec[0] = (unsigned long)_orig.nraddr; \
1059 _argvec[1] = (unsigned long)(arg1); \
1060 _argvec[2] = (unsigned long)(arg2); \
1061 _argvec[3] = (unsigned long)(arg3); \
1062 _argvec[4] = (unsigned long)(arg4); \
1063 _argvec[5] = (unsigned long)(arg5); \
1064 _argvec[6] = (unsigned long)(arg6); \
1065 _argvec[7] = (unsigned long)(arg7); \
1066 _argvec[8] = (unsigned long)(arg8); \
1067 _argvec[9] = (unsigned long)(arg9); \
1068 _argvec[10] = (unsigned long)(arg10); \
1069 __asm__ volatile( \
1070 "pushl 40(%%eax)\n\t" \
1071 "pushl 36(%%eax)\n\t" \
1072 "pushl 32(%%eax)\n\t" \
1073 "pushl 28(%%eax)\n\t" \
1074 "pushl 24(%%eax)\n\t" \
1075 "pushl 20(%%eax)\n\t" \
1076 "pushl 16(%%eax)\n\t" \
1077 "pushl 12(%%eax)\n\t" \
1078 "pushl 8(%%eax)\n\t" \
1079 "pushl 4(%%eax)\n\t" \
1080 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1081 VALGRIND_CALL_NOREDIR_EAX \
1082 "addl $40, %%esp\n" \
1083 : /*out*/ "=a" (_res) \
1084 : /*in*/ "a" (&_argvec[0]) \
1085 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1086 ); \
1087 lval = (__typeof__(lval)) _res; \
1088 } while (0)
1089
sewardj5ce4b152006-03-11 12:57:41 +00001090#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1091 arg6,arg7,arg8,arg9,arg10, \
1092 arg11) \
1093 do { \
1094 volatile OrigFn _orig = (orig); \
1095 volatile unsigned long _argvec[12]; \
1096 volatile unsigned long _res; \
1097 _argvec[0] = (unsigned long)_orig.nraddr; \
1098 _argvec[1] = (unsigned long)(arg1); \
1099 _argvec[2] = (unsigned long)(arg2); \
1100 _argvec[3] = (unsigned long)(arg3); \
1101 _argvec[4] = (unsigned long)(arg4); \
1102 _argvec[5] = (unsigned long)(arg5); \
1103 _argvec[6] = (unsigned long)(arg6); \
1104 _argvec[7] = (unsigned long)(arg7); \
1105 _argvec[8] = (unsigned long)(arg8); \
1106 _argvec[9] = (unsigned long)(arg9); \
1107 _argvec[10] = (unsigned long)(arg10); \
1108 _argvec[11] = (unsigned long)(arg11); \
1109 __asm__ volatile( \
1110 "pushl 44(%%eax)\n\t" \
1111 "pushl 40(%%eax)\n\t" \
1112 "pushl 36(%%eax)\n\t" \
1113 "pushl 32(%%eax)\n\t" \
1114 "pushl 28(%%eax)\n\t" \
1115 "pushl 24(%%eax)\n\t" \
1116 "pushl 20(%%eax)\n\t" \
1117 "pushl 16(%%eax)\n\t" \
1118 "pushl 12(%%eax)\n\t" \
1119 "pushl 8(%%eax)\n\t" \
1120 "pushl 4(%%eax)\n\t" \
1121 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1122 VALGRIND_CALL_NOREDIR_EAX \
1123 "addl $44, %%esp\n" \
1124 : /*out*/ "=a" (_res) \
1125 : /*in*/ "a" (&_argvec[0]) \
1126 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1127 ); \
1128 lval = (__typeof__(lval)) _res; \
1129 } while (0)
1130
sewardj66226cc2006-01-20 15:46:46 +00001131#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1132 arg6,arg7,arg8,arg9,arg10, \
1133 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001134 do { \
sewardj66226cc2006-01-20 15:46:46 +00001135 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001136 volatile unsigned long _argvec[13]; \
1137 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001138 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001139 _argvec[1] = (unsigned long)(arg1); \
1140 _argvec[2] = (unsigned long)(arg2); \
1141 _argvec[3] = (unsigned long)(arg3); \
1142 _argvec[4] = (unsigned long)(arg4); \
1143 _argvec[5] = (unsigned long)(arg5); \
1144 _argvec[6] = (unsigned long)(arg6); \
1145 _argvec[7] = (unsigned long)(arg7); \
1146 _argvec[8] = (unsigned long)(arg8); \
1147 _argvec[9] = (unsigned long)(arg9); \
1148 _argvec[10] = (unsigned long)(arg10); \
1149 _argvec[11] = (unsigned long)(arg11); \
1150 _argvec[12] = (unsigned long)(arg12); \
1151 __asm__ volatile( \
1152 "pushl 48(%%eax)\n\t" \
1153 "pushl 44(%%eax)\n\t" \
1154 "pushl 40(%%eax)\n\t" \
1155 "pushl 36(%%eax)\n\t" \
1156 "pushl 32(%%eax)\n\t" \
1157 "pushl 28(%%eax)\n\t" \
1158 "pushl 24(%%eax)\n\t" \
1159 "pushl 20(%%eax)\n\t" \
1160 "pushl 16(%%eax)\n\t" \
1161 "pushl 12(%%eax)\n\t" \
1162 "pushl 8(%%eax)\n\t" \
1163 "pushl 4(%%eax)\n\t" \
1164 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1165 VALGRIND_CALL_NOREDIR_EAX \
1166 "addl $48, %%esp\n" \
1167 : /*out*/ "=a" (_res) \
1168 : /*in*/ "a" (&_argvec[0]) \
1169 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1170 ); \
1171 lval = (__typeof__(lval)) _res; \
1172 } while (0)
1173
njnf76d27a2009-05-28 01:53:07 +00001174#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001175
njnf76d27a2009-05-28 01:53:07 +00001176/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001177
njnf76d27a2009-05-28 01:53:07 +00001178#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001179
1180/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1181
1182/* These regs are trashed by the hidden call. */
1183#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1184 "rdi", "r8", "r9", "r10", "r11"
1185
1186/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1187 long) == 8. */
1188
sewardja07c2e12007-11-09 23:09:50 +00001189/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1190 macros. In order not to trash the stack redzone, we need to drop
1191 %rsp by 128 before the hidden call, and restore afterwards. The
1192 nastyness is that it is only by luck that the stack still appears
1193 to be unwindable during the hidden call - since then the behaviour
1194 of any routine using this macro does not match what the CFI data
1195 says. Sigh.
1196
1197 Why is this important? Imagine that a wrapper has a stack
1198 allocated local, and passes to the hidden call, a pointer to it.
1199 Because gcc does not know about the hidden call, it may allocate
1200 that local in the redzone. Unfortunately the hidden call may then
1201 trash it before it comes to use it. So we must step clear of the
1202 redzone, for the duration of the hidden call, to make it safe.
1203
1204 Probably the same problem afflicts the other redzone-style ABIs too
1205 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1206 self describing (none of this CFI nonsense) so at least messing
1207 with the stack pointer doesn't give a danger of non-unwindable
1208 stack. */
1209
sewardjc8858442006-01-20 15:17:20 +00001210#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001211 do { \
sewardjc8858442006-01-20 15:17:20 +00001212 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001213 volatile unsigned long _argvec[1]; \
1214 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001215 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001216 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001217 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001218 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1219 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001220 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001221 : /*out*/ "=a" (_res) \
1222 : /*in*/ "a" (&_argvec[0]) \
1223 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1224 ); \
1225 lval = (__typeof__(lval)) _res; \
1226 } while (0)
1227
sewardjc8858442006-01-20 15:17:20 +00001228#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001229 do { \
sewardjc8858442006-01-20 15:17:20 +00001230 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001231 volatile unsigned long _argvec[2]; \
1232 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001233 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001234 _argvec[1] = (unsigned long)(arg1); \
1235 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001236 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001237 "movq 8(%%rax), %%rdi\n\t" \
1238 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1239 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001240 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001241 : /*out*/ "=a" (_res) \
1242 : /*in*/ "a" (&_argvec[0]) \
1243 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1244 ); \
1245 lval = (__typeof__(lval)) _res; \
1246 } while (0)
1247
sewardjc8858442006-01-20 15:17:20 +00001248#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001249 do { \
sewardjc8858442006-01-20 15:17:20 +00001250 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001251 volatile unsigned long _argvec[3]; \
1252 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001253 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001254 _argvec[1] = (unsigned long)(arg1); \
1255 _argvec[2] = (unsigned long)(arg2); \
1256 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001257 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001258 "movq 16(%%rax), %%rsi\n\t" \
1259 "movq 8(%%rax), %%rdi\n\t" \
1260 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1261 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001262 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001263 : /*out*/ "=a" (_res) \
1264 : /*in*/ "a" (&_argvec[0]) \
1265 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1266 ); \
1267 lval = (__typeof__(lval)) _res; \
1268 } while (0)
1269
sewardja50f9dc2006-03-11 16:19:14 +00001270#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1271 do { \
1272 volatile OrigFn _orig = (orig); \
1273 volatile unsigned long _argvec[4]; \
1274 volatile unsigned long _res; \
1275 _argvec[0] = (unsigned long)_orig.nraddr; \
1276 _argvec[1] = (unsigned long)(arg1); \
1277 _argvec[2] = (unsigned long)(arg2); \
1278 _argvec[3] = (unsigned long)(arg3); \
1279 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001280 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001281 "movq 24(%%rax), %%rdx\n\t" \
1282 "movq 16(%%rax), %%rsi\n\t" \
1283 "movq 8(%%rax), %%rdi\n\t" \
1284 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1285 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001286 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001287 : /*out*/ "=a" (_res) \
1288 : /*in*/ "a" (&_argvec[0]) \
1289 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1290 ); \
1291 lval = (__typeof__(lval)) _res; \
1292 } while (0)
1293
1294#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1295 do { \
1296 volatile OrigFn _orig = (orig); \
1297 volatile unsigned long _argvec[5]; \
1298 volatile unsigned long _res; \
1299 _argvec[0] = (unsigned long)_orig.nraddr; \
1300 _argvec[1] = (unsigned long)(arg1); \
1301 _argvec[2] = (unsigned long)(arg2); \
1302 _argvec[3] = (unsigned long)(arg3); \
1303 _argvec[4] = (unsigned long)(arg4); \
1304 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001305 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001306 "movq 32(%%rax), %%rcx\n\t" \
1307 "movq 24(%%rax), %%rdx\n\t" \
1308 "movq 16(%%rax), %%rsi\n\t" \
1309 "movq 8(%%rax), %%rdi\n\t" \
1310 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1311 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001312 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001313 : /*out*/ "=a" (_res) \
1314 : /*in*/ "a" (&_argvec[0]) \
1315 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1316 ); \
1317 lval = (__typeof__(lval)) _res; \
1318 } while (0)
1319
1320#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1321 do { \
1322 volatile OrigFn _orig = (orig); \
1323 volatile unsigned long _argvec[6]; \
1324 volatile unsigned long _res; \
1325 _argvec[0] = (unsigned long)_orig.nraddr; \
1326 _argvec[1] = (unsigned long)(arg1); \
1327 _argvec[2] = (unsigned long)(arg2); \
1328 _argvec[3] = (unsigned long)(arg3); \
1329 _argvec[4] = (unsigned long)(arg4); \
1330 _argvec[5] = (unsigned long)(arg5); \
1331 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001332 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001333 "movq 40(%%rax), %%r8\n\t" \
1334 "movq 32(%%rax), %%rcx\n\t" \
1335 "movq 24(%%rax), %%rdx\n\t" \
1336 "movq 16(%%rax), %%rsi\n\t" \
1337 "movq 8(%%rax), %%rdi\n\t" \
1338 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1339 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001340 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001341 : /*out*/ "=a" (_res) \
1342 : /*in*/ "a" (&_argvec[0]) \
1343 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1344 ); \
1345 lval = (__typeof__(lval)) _res; \
1346 } while (0)
1347
1348#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1349 do { \
1350 volatile OrigFn _orig = (orig); \
1351 volatile unsigned long _argvec[7]; \
1352 volatile unsigned long _res; \
1353 _argvec[0] = (unsigned long)_orig.nraddr; \
1354 _argvec[1] = (unsigned long)(arg1); \
1355 _argvec[2] = (unsigned long)(arg2); \
1356 _argvec[3] = (unsigned long)(arg3); \
1357 _argvec[4] = (unsigned long)(arg4); \
1358 _argvec[5] = (unsigned long)(arg5); \
1359 _argvec[6] = (unsigned long)(arg6); \
1360 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001361 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001362 "movq 48(%%rax), %%r9\n\t" \
1363 "movq 40(%%rax), %%r8\n\t" \
1364 "movq 32(%%rax), %%rcx\n\t" \
1365 "movq 24(%%rax), %%rdx\n\t" \
1366 "movq 16(%%rax), %%rsi\n\t" \
1367 "movq 8(%%rax), %%rdi\n\t" \
1368 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
sewardja07c2e12007-11-09 23:09:50 +00001369 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001370 VALGRIND_CALL_NOREDIR_RAX \
1371 : /*out*/ "=a" (_res) \
1372 : /*in*/ "a" (&_argvec[0]) \
1373 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1374 ); \
1375 lval = (__typeof__(lval)) _res; \
1376 } while (0)
1377
1378#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1379 arg7) \
1380 do { \
1381 volatile OrigFn _orig = (orig); \
1382 volatile unsigned long _argvec[8]; \
1383 volatile unsigned long _res; \
1384 _argvec[0] = (unsigned long)_orig.nraddr; \
1385 _argvec[1] = (unsigned long)(arg1); \
1386 _argvec[2] = (unsigned long)(arg2); \
1387 _argvec[3] = (unsigned long)(arg3); \
1388 _argvec[4] = (unsigned long)(arg4); \
1389 _argvec[5] = (unsigned long)(arg5); \
1390 _argvec[6] = (unsigned long)(arg6); \
1391 _argvec[7] = (unsigned long)(arg7); \
1392 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001393 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001394 "pushq 56(%%rax)\n\t" \
1395 "movq 48(%%rax), %%r9\n\t" \
1396 "movq 40(%%rax), %%r8\n\t" \
1397 "movq 32(%%rax), %%rcx\n\t" \
1398 "movq 24(%%rax), %%rdx\n\t" \
1399 "movq 16(%%rax), %%rsi\n\t" \
1400 "movq 8(%%rax), %%rdi\n\t" \
1401 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1402 VALGRIND_CALL_NOREDIR_RAX \
1403 "addq $8, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001404 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001405 : /*out*/ "=a" (_res) \
1406 : /*in*/ "a" (&_argvec[0]) \
1407 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1408 ); \
1409 lval = (__typeof__(lval)) _res; \
1410 } while (0)
1411
1412#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1413 arg7,arg8) \
1414 do { \
1415 volatile OrigFn _orig = (orig); \
1416 volatile unsigned long _argvec[9]; \
1417 volatile unsigned long _res; \
1418 _argvec[0] = (unsigned long)_orig.nraddr; \
1419 _argvec[1] = (unsigned long)(arg1); \
1420 _argvec[2] = (unsigned long)(arg2); \
1421 _argvec[3] = (unsigned long)(arg3); \
1422 _argvec[4] = (unsigned long)(arg4); \
1423 _argvec[5] = (unsigned long)(arg5); \
1424 _argvec[6] = (unsigned long)(arg6); \
1425 _argvec[7] = (unsigned long)(arg7); \
1426 _argvec[8] = (unsigned long)(arg8); \
1427 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001428 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001429 "pushq 64(%%rax)\n\t" \
1430 "pushq 56(%%rax)\n\t" \
1431 "movq 48(%%rax), %%r9\n\t" \
1432 "movq 40(%%rax), %%r8\n\t" \
1433 "movq 32(%%rax), %%rcx\n\t" \
1434 "movq 24(%%rax), %%rdx\n\t" \
1435 "movq 16(%%rax), %%rsi\n\t" \
1436 "movq 8(%%rax), %%rdi\n\t" \
1437 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1438 VALGRIND_CALL_NOREDIR_RAX \
1439 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001440 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001441 : /*out*/ "=a" (_res) \
1442 : /*in*/ "a" (&_argvec[0]) \
1443 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1444 ); \
1445 lval = (__typeof__(lval)) _res; \
1446 } while (0)
1447
1448#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1449 arg7,arg8,arg9) \
1450 do { \
1451 volatile OrigFn _orig = (orig); \
1452 volatile unsigned long _argvec[10]; \
1453 volatile unsigned long _res; \
1454 _argvec[0] = (unsigned long)_orig.nraddr; \
1455 _argvec[1] = (unsigned long)(arg1); \
1456 _argvec[2] = (unsigned long)(arg2); \
1457 _argvec[3] = (unsigned long)(arg3); \
1458 _argvec[4] = (unsigned long)(arg4); \
1459 _argvec[5] = (unsigned long)(arg5); \
1460 _argvec[6] = (unsigned long)(arg6); \
1461 _argvec[7] = (unsigned long)(arg7); \
1462 _argvec[8] = (unsigned long)(arg8); \
1463 _argvec[9] = (unsigned long)(arg9); \
1464 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001465 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001466 "pushq 72(%%rax)\n\t" \
1467 "pushq 64(%%rax)\n\t" \
1468 "pushq 56(%%rax)\n\t" \
1469 "movq 48(%%rax), %%r9\n\t" \
1470 "movq 40(%%rax), %%r8\n\t" \
1471 "movq 32(%%rax), %%rcx\n\t" \
1472 "movq 24(%%rax), %%rdx\n\t" \
1473 "movq 16(%%rax), %%rsi\n\t" \
1474 "movq 8(%%rax), %%rdi\n\t" \
1475 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1476 VALGRIND_CALL_NOREDIR_RAX \
1477 "addq $24, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001478 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001479 : /*out*/ "=a" (_res) \
1480 : /*in*/ "a" (&_argvec[0]) \
1481 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1482 ); \
1483 lval = (__typeof__(lval)) _res; \
1484 } while (0)
1485
1486#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1487 arg7,arg8,arg9,arg10) \
1488 do { \
1489 volatile OrigFn _orig = (orig); \
1490 volatile unsigned long _argvec[11]; \
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 _argvec[9] = (unsigned long)(arg9); \
1502 _argvec[10] = (unsigned long)(arg10); \
1503 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001504 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001505 "pushq 80(%%rax)\n\t" \
1506 "pushq 72(%%rax)\n\t" \
1507 "pushq 64(%%rax)\n\t" \
1508 "pushq 56(%%rax)\n\t" \
1509 "movq 48(%%rax), %%r9\n\t" \
1510 "movq 40(%%rax), %%r8\n\t" \
1511 "movq 32(%%rax), %%rcx\n\t" \
1512 "movq 24(%%rax), %%rdx\n\t" \
1513 "movq 16(%%rax), %%rsi\n\t" \
1514 "movq 8(%%rax), %%rdi\n\t" \
1515 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1516 VALGRIND_CALL_NOREDIR_RAX \
1517 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001518 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001519 : /*out*/ "=a" (_res) \
1520 : /*in*/ "a" (&_argvec[0]) \
1521 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1522 ); \
1523 lval = (__typeof__(lval)) _res; \
1524 } while (0)
1525
1526#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1527 arg7,arg8,arg9,arg10,arg11) \
1528 do { \
1529 volatile OrigFn _orig = (orig); \
1530 volatile unsigned long _argvec[12]; \
1531 volatile unsigned long _res; \
1532 _argvec[0] = (unsigned long)_orig.nraddr; \
1533 _argvec[1] = (unsigned long)(arg1); \
1534 _argvec[2] = (unsigned long)(arg2); \
1535 _argvec[3] = (unsigned long)(arg3); \
1536 _argvec[4] = (unsigned long)(arg4); \
1537 _argvec[5] = (unsigned long)(arg5); \
1538 _argvec[6] = (unsigned long)(arg6); \
1539 _argvec[7] = (unsigned long)(arg7); \
1540 _argvec[8] = (unsigned long)(arg8); \
1541 _argvec[9] = (unsigned long)(arg9); \
1542 _argvec[10] = (unsigned long)(arg10); \
1543 _argvec[11] = (unsigned long)(arg11); \
1544 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001545 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001546 "pushq 88(%%rax)\n\t" \
1547 "pushq 80(%%rax)\n\t" \
1548 "pushq 72(%%rax)\n\t" \
1549 "pushq 64(%%rax)\n\t" \
1550 "pushq 56(%%rax)\n\t" \
1551 "movq 48(%%rax), %%r9\n\t" \
1552 "movq 40(%%rax), %%r8\n\t" \
1553 "movq 32(%%rax), %%rcx\n\t" \
1554 "movq 24(%%rax), %%rdx\n\t" \
1555 "movq 16(%%rax), %%rsi\n\t" \
1556 "movq 8(%%rax), %%rdi\n\t" \
1557 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1558 VALGRIND_CALL_NOREDIR_RAX \
1559 "addq $40, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001560 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001561 : /*out*/ "=a" (_res) \
1562 : /*in*/ "a" (&_argvec[0]) \
1563 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1564 ); \
1565 lval = (__typeof__(lval)) _res; \
1566 } while (0)
1567
1568#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1569 arg7,arg8,arg9,arg10,arg11,arg12) \
1570 do { \
1571 volatile OrigFn _orig = (orig); \
1572 volatile unsigned long _argvec[13]; \
1573 volatile unsigned long _res; \
1574 _argvec[0] = (unsigned long)_orig.nraddr; \
1575 _argvec[1] = (unsigned long)(arg1); \
1576 _argvec[2] = (unsigned long)(arg2); \
1577 _argvec[3] = (unsigned long)(arg3); \
1578 _argvec[4] = (unsigned long)(arg4); \
1579 _argvec[5] = (unsigned long)(arg5); \
1580 _argvec[6] = (unsigned long)(arg6); \
1581 _argvec[7] = (unsigned long)(arg7); \
1582 _argvec[8] = (unsigned long)(arg8); \
1583 _argvec[9] = (unsigned long)(arg9); \
1584 _argvec[10] = (unsigned long)(arg10); \
1585 _argvec[11] = (unsigned long)(arg11); \
1586 _argvec[12] = (unsigned long)(arg12); \
1587 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001588 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001589 "pushq 96(%%rax)\n\t" \
1590 "pushq 88(%%rax)\n\t" \
1591 "pushq 80(%%rax)\n\t" \
1592 "pushq 72(%%rax)\n\t" \
1593 "pushq 64(%%rax)\n\t" \
1594 "pushq 56(%%rax)\n\t" \
1595 "movq 48(%%rax), %%r9\n\t" \
1596 "movq 40(%%rax), %%r8\n\t" \
1597 "movq 32(%%rax), %%rcx\n\t" \
1598 "movq 24(%%rax), %%rdx\n\t" \
1599 "movq 16(%%rax), %%rsi\n\t" \
1600 "movq 8(%%rax), %%rdi\n\t" \
1601 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1602 VALGRIND_CALL_NOREDIR_RAX \
1603 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001604 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001605 : /*out*/ "=a" (_res) \
1606 : /*in*/ "a" (&_argvec[0]) \
1607 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1608 ); \
1609 lval = (__typeof__(lval)) _res; \
1610 } while (0)
1611
njnf76d27a2009-05-28 01:53:07 +00001612#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001613
sewardjf5c1a7f2006-10-17 01:32:48 +00001614/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001615
sewardjf5c1a7f2006-10-17 01:32:48 +00001616#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001617
sewardjead61df2006-03-12 13:39:15 +00001618/* This is useful for finding out about the on-stack stuff:
1619
1620 extern int f9 ( int,int,int,int,int,int,int,int,int );
1621 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1622 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1623 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1624
1625 int g9 ( void ) {
1626 return f9(11,22,33,44,55,66,77,88,99);
1627 }
1628 int g10 ( void ) {
1629 return f10(11,22,33,44,55,66,77,88,99,110);
1630 }
1631 int g11 ( void ) {
1632 return f11(11,22,33,44,55,66,77,88,99,110,121);
1633 }
1634 int g12 ( void ) {
1635 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1636 }
1637*/
1638
sewardj0ec07f32006-01-12 12:32:32 +00001639/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1640
1641/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001642#define __CALLER_SAVED_REGS \
1643 "lr", "ctr", "xer", \
1644 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1645 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1646 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001647
sewardjead61df2006-03-12 13:39:15 +00001648/* These CALL_FN_ macros assume that on ppc32-linux,
1649 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001650
sewardj38de0992006-01-20 16:46:34 +00001651#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001652 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001653 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001654 volatile unsigned long _argvec[1]; \
1655 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001656 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001657 __asm__ volatile( \
1658 "mr 11,%1\n\t" \
1659 "lwz 11,0(11)\n\t" /* target->r11 */ \
1660 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1661 "mr %0,3" \
1662 : /*out*/ "=r" (_res) \
1663 : /*in*/ "r" (&_argvec[0]) \
1664 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1665 ); \
1666 lval = (__typeof__(lval)) _res; \
1667 } while (0)
1668
sewardj38de0992006-01-20 16:46:34 +00001669#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001670 do { \
sewardj38de0992006-01-20 16:46:34 +00001671 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001672 volatile unsigned long _argvec[2]; \
1673 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001674 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001675 _argvec[1] = (unsigned long)arg1; \
1676 __asm__ volatile( \
1677 "mr 11,%1\n\t" \
1678 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1679 "lwz 11,0(11)\n\t" /* target->r11 */ \
1680 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1681 "mr %0,3" \
1682 : /*out*/ "=r" (_res) \
1683 : /*in*/ "r" (&_argvec[0]) \
1684 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1685 ); \
1686 lval = (__typeof__(lval)) _res; \
1687 } while (0)
1688
sewardj38de0992006-01-20 16:46:34 +00001689#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001690 do { \
sewardj38de0992006-01-20 16:46:34 +00001691 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001692 volatile unsigned long _argvec[3]; \
1693 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001694 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001695 _argvec[1] = (unsigned long)arg1; \
1696 _argvec[2] = (unsigned long)arg2; \
1697 __asm__ volatile( \
1698 "mr 11,%1\n\t" \
1699 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1700 "lwz 4,8(11)\n\t" \
1701 "lwz 11,0(11)\n\t" /* target->r11 */ \
1702 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1703 "mr %0,3" \
1704 : /*out*/ "=r" (_res) \
1705 : /*in*/ "r" (&_argvec[0]) \
1706 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1707 ); \
1708 lval = (__typeof__(lval)) _res; \
1709 } while (0)
1710
sewardjead61df2006-03-12 13:39:15 +00001711#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1712 do { \
1713 volatile OrigFn _orig = (orig); \
1714 volatile unsigned long _argvec[4]; \
1715 volatile unsigned long _res; \
1716 _argvec[0] = (unsigned long)_orig.nraddr; \
1717 _argvec[1] = (unsigned long)arg1; \
1718 _argvec[2] = (unsigned long)arg2; \
1719 _argvec[3] = (unsigned long)arg3; \
1720 __asm__ volatile( \
1721 "mr 11,%1\n\t" \
1722 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1723 "lwz 4,8(11)\n\t" \
1724 "lwz 5,12(11)\n\t" \
1725 "lwz 11,0(11)\n\t" /* target->r11 */ \
1726 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1727 "mr %0,3" \
1728 : /*out*/ "=r" (_res) \
1729 : /*in*/ "r" (&_argvec[0]) \
1730 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1731 ); \
1732 lval = (__typeof__(lval)) _res; \
1733 } while (0)
1734
1735#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1736 do { \
1737 volatile OrigFn _orig = (orig); \
1738 volatile unsigned long _argvec[5]; \
1739 volatile unsigned long _res; \
1740 _argvec[0] = (unsigned long)_orig.nraddr; \
1741 _argvec[1] = (unsigned long)arg1; \
1742 _argvec[2] = (unsigned long)arg2; \
1743 _argvec[3] = (unsigned long)arg3; \
1744 _argvec[4] = (unsigned long)arg4; \
1745 __asm__ volatile( \
1746 "mr 11,%1\n\t" \
1747 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1748 "lwz 4,8(11)\n\t" \
1749 "lwz 5,12(11)\n\t" \
1750 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1751 "lwz 11,0(11)\n\t" /* target->r11 */ \
1752 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1753 "mr %0,3" \
1754 : /*out*/ "=r" (_res) \
1755 : /*in*/ "r" (&_argvec[0]) \
1756 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1757 ); \
1758 lval = (__typeof__(lval)) _res; \
1759 } while (0)
1760
1761#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1762 do { \
1763 volatile OrigFn _orig = (orig); \
1764 volatile unsigned long _argvec[6]; \
1765 volatile unsigned long _res; \
1766 _argvec[0] = (unsigned long)_orig.nraddr; \
1767 _argvec[1] = (unsigned long)arg1; \
1768 _argvec[2] = (unsigned long)arg2; \
1769 _argvec[3] = (unsigned long)arg3; \
1770 _argvec[4] = (unsigned long)arg4; \
1771 _argvec[5] = (unsigned long)arg5; \
1772 __asm__ volatile( \
1773 "mr 11,%1\n\t" \
1774 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1775 "lwz 4,8(11)\n\t" \
1776 "lwz 5,12(11)\n\t" \
1777 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1778 "lwz 7,20(11)\n\t" \
1779 "lwz 11,0(11)\n\t" /* target->r11 */ \
1780 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1781 "mr %0,3" \
1782 : /*out*/ "=r" (_res) \
1783 : /*in*/ "r" (&_argvec[0]) \
1784 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1785 ); \
1786 lval = (__typeof__(lval)) _res; \
1787 } while (0)
1788
1789#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1790 do { \
1791 volatile OrigFn _orig = (orig); \
1792 volatile unsigned long _argvec[7]; \
1793 volatile unsigned long _res; \
1794 _argvec[0] = (unsigned long)_orig.nraddr; \
1795 _argvec[1] = (unsigned long)arg1; \
1796 _argvec[2] = (unsigned long)arg2; \
1797 _argvec[3] = (unsigned long)arg3; \
1798 _argvec[4] = (unsigned long)arg4; \
1799 _argvec[5] = (unsigned long)arg5; \
1800 _argvec[6] = (unsigned long)arg6; \
1801 __asm__ volatile( \
1802 "mr 11,%1\n\t" \
1803 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1804 "lwz 4,8(11)\n\t" \
1805 "lwz 5,12(11)\n\t" \
1806 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1807 "lwz 7,20(11)\n\t" \
1808 "lwz 8,24(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_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1820 arg7) \
1821 do { \
1822 volatile OrigFn _orig = (orig); \
1823 volatile unsigned long _argvec[8]; \
1824 volatile unsigned long _res; \
1825 _argvec[0] = (unsigned long)_orig.nraddr; \
1826 _argvec[1] = (unsigned long)arg1; \
1827 _argvec[2] = (unsigned long)arg2; \
1828 _argvec[3] = (unsigned long)arg3; \
1829 _argvec[4] = (unsigned long)arg4; \
1830 _argvec[5] = (unsigned long)arg5; \
1831 _argvec[6] = (unsigned long)arg6; \
1832 _argvec[7] = (unsigned long)arg7; \
1833 __asm__ volatile( \
1834 "mr 11,%1\n\t" \
1835 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1836 "lwz 4,8(11)\n\t" \
1837 "lwz 5,12(11)\n\t" \
1838 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1839 "lwz 7,20(11)\n\t" \
1840 "lwz 8,24(11)\n\t" \
1841 "lwz 9,28(11)\n\t" \
1842 "lwz 11,0(11)\n\t" /* target->r11 */ \
1843 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1844 "mr %0,3" \
1845 : /*out*/ "=r" (_res) \
1846 : /*in*/ "r" (&_argvec[0]) \
1847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1848 ); \
1849 lval = (__typeof__(lval)) _res; \
1850 } while (0)
1851
1852#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1853 arg7,arg8) \
1854 do { \
1855 volatile OrigFn _orig = (orig); \
1856 volatile unsigned long _argvec[9]; \
1857 volatile unsigned long _res; \
1858 _argvec[0] = (unsigned long)_orig.nraddr; \
1859 _argvec[1] = (unsigned long)arg1; \
1860 _argvec[2] = (unsigned long)arg2; \
1861 _argvec[3] = (unsigned long)arg3; \
1862 _argvec[4] = (unsigned long)arg4; \
1863 _argvec[5] = (unsigned long)arg5; \
1864 _argvec[6] = (unsigned long)arg6; \
1865 _argvec[7] = (unsigned long)arg7; \
1866 _argvec[8] = (unsigned long)arg8; \
1867 __asm__ volatile( \
1868 "mr 11,%1\n\t" \
1869 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1870 "lwz 4,8(11)\n\t" \
1871 "lwz 5,12(11)\n\t" \
1872 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1873 "lwz 7,20(11)\n\t" \
1874 "lwz 8,24(11)\n\t" \
1875 "lwz 9,28(11)\n\t" \
1876 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1877 "lwz 11,0(11)\n\t" /* target->r11 */ \
1878 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1879 "mr %0,3" \
1880 : /*out*/ "=r" (_res) \
1881 : /*in*/ "r" (&_argvec[0]) \
1882 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1883 ); \
1884 lval = (__typeof__(lval)) _res; \
1885 } while (0)
1886
1887#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1888 arg7,arg8,arg9) \
1889 do { \
1890 volatile OrigFn _orig = (orig); \
1891 volatile unsigned long _argvec[10]; \
1892 volatile unsigned long _res; \
1893 _argvec[0] = (unsigned long)_orig.nraddr; \
1894 _argvec[1] = (unsigned long)arg1; \
1895 _argvec[2] = (unsigned long)arg2; \
1896 _argvec[3] = (unsigned long)arg3; \
1897 _argvec[4] = (unsigned long)arg4; \
1898 _argvec[5] = (unsigned long)arg5; \
1899 _argvec[6] = (unsigned long)arg6; \
1900 _argvec[7] = (unsigned long)arg7; \
1901 _argvec[8] = (unsigned long)arg8; \
1902 _argvec[9] = (unsigned long)arg9; \
1903 __asm__ volatile( \
1904 "mr 11,%1\n\t" \
1905 "addi 1,1,-16\n\t" \
1906 /* arg9 */ \
1907 "lwz 3,36(11)\n\t" \
1908 "stw 3,8(1)\n\t" \
1909 /* args1-8 */ \
1910 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1911 "lwz 4,8(11)\n\t" \
1912 "lwz 5,12(11)\n\t" \
1913 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1914 "lwz 7,20(11)\n\t" \
1915 "lwz 8,24(11)\n\t" \
1916 "lwz 9,28(11)\n\t" \
1917 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1918 "lwz 11,0(11)\n\t" /* target->r11 */ \
1919 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1920 "addi 1,1,16\n\t" \
1921 "mr %0,3" \
1922 : /*out*/ "=r" (_res) \
1923 : /*in*/ "r" (&_argvec[0]) \
1924 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1925 ); \
1926 lval = (__typeof__(lval)) _res; \
1927 } while (0)
1928
1929#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1930 arg7,arg8,arg9,arg10) \
1931 do { \
1932 volatile OrigFn _orig = (orig); \
1933 volatile unsigned long _argvec[11]; \
1934 volatile unsigned long _res; \
1935 _argvec[0] = (unsigned long)_orig.nraddr; \
1936 _argvec[1] = (unsigned long)arg1; \
1937 _argvec[2] = (unsigned long)arg2; \
1938 _argvec[3] = (unsigned long)arg3; \
1939 _argvec[4] = (unsigned long)arg4; \
1940 _argvec[5] = (unsigned long)arg5; \
1941 _argvec[6] = (unsigned long)arg6; \
1942 _argvec[7] = (unsigned long)arg7; \
1943 _argvec[8] = (unsigned long)arg8; \
1944 _argvec[9] = (unsigned long)arg9; \
1945 _argvec[10] = (unsigned long)arg10; \
1946 __asm__ volatile( \
1947 "mr 11,%1\n\t" \
1948 "addi 1,1,-16\n\t" \
1949 /* arg10 */ \
1950 "lwz 3,40(11)\n\t" \
1951 "stw 3,12(1)\n\t" \
1952 /* arg9 */ \
1953 "lwz 3,36(11)\n\t" \
1954 "stw 3,8(1)\n\t" \
1955 /* args1-8 */ \
1956 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1957 "lwz 4,8(11)\n\t" \
1958 "lwz 5,12(11)\n\t" \
1959 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1960 "lwz 7,20(11)\n\t" \
1961 "lwz 8,24(11)\n\t" \
1962 "lwz 9,28(11)\n\t" \
1963 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1964 "lwz 11,0(11)\n\t" /* target->r11 */ \
1965 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1966 "addi 1,1,16\n\t" \
1967 "mr %0,3" \
1968 : /*out*/ "=r" (_res) \
1969 : /*in*/ "r" (&_argvec[0]) \
1970 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1971 ); \
1972 lval = (__typeof__(lval)) _res; \
1973 } while (0)
1974
1975#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1976 arg7,arg8,arg9,arg10,arg11) \
1977 do { \
1978 volatile OrigFn _orig = (orig); \
1979 volatile unsigned long _argvec[12]; \
1980 volatile unsigned long _res; \
1981 _argvec[0] = (unsigned long)_orig.nraddr; \
1982 _argvec[1] = (unsigned long)arg1; \
1983 _argvec[2] = (unsigned long)arg2; \
1984 _argvec[3] = (unsigned long)arg3; \
1985 _argvec[4] = (unsigned long)arg4; \
1986 _argvec[5] = (unsigned long)arg5; \
1987 _argvec[6] = (unsigned long)arg6; \
1988 _argvec[7] = (unsigned long)arg7; \
1989 _argvec[8] = (unsigned long)arg8; \
1990 _argvec[9] = (unsigned long)arg9; \
1991 _argvec[10] = (unsigned long)arg10; \
1992 _argvec[11] = (unsigned long)arg11; \
1993 __asm__ volatile( \
1994 "mr 11,%1\n\t" \
1995 "addi 1,1,-32\n\t" \
1996 /* arg11 */ \
1997 "lwz 3,44(11)\n\t" \
1998 "stw 3,16(1)\n\t" \
1999 /* arg10 */ \
2000 "lwz 3,40(11)\n\t" \
2001 "stw 3,12(1)\n\t" \
2002 /* arg9 */ \
2003 "lwz 3,36(11)\n\t" \
2004 "stw 3,8(1)\n\t" \
2005 /* args1-8 */ \
2006 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2007 "lwz 4,8(11)\n\t" \
2008 "lwz 5,12(11)\n\t" \
2009 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2010 "lwz 7,20(11)\n\t" \
2011 "lwz 8,24(11)\n\t" \
2012 "lwz 9,28(11)\n\t" \
2013 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2014 "lwz 11,0(11)\n\t" /* target->r11 */ \
2015 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2016 "addi 1,1,32\n\t" \
2017 "mr %0,3" \
2018 : /*out*/ "=r" (_res) \
2019 : /*in*/ "r" (&_argvec[0]) \
2020 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2021 ); \
2022 lval = (__typeof__(lval)) _res; \
2023 } while (0)
2024
2025#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2026 arg7,arg8,arg9,arg10,arg11,arg12) \
2027 do { \
2028 volatile OrigFn _orig = (orig); \
2029 volatile unsigned long _argvec[13]; \
2030 volatile unsigned long _res; \
2031 _argvec[0] = (unsigned long)_orig.nraddr; \
2032 _argvec[1] = (unsigned long)arg1; \
2033 _argvec[2] = (unsigned long)arg2; \
2034 _argvec[3] = (unsigned long)arg3; \
2035 _argvec[4] = (unsigned long)arg4; \
2036 _argvec[5] = (unsigned long)arg5; \
2037 _argvec[6] = (unsigned long)arg6; \
2038 _argvec[7] = (unsigned long)arg7; \
2039 _argvec[8] = (unsigned long)arg8; \
2040 _argvec[9] = (unsigned long)arg9; \
2041 _argvec[10] = (unsigned long)arg10; \
2042 _argvec[11] = (unsigned long)arg11; \
2043 _argvec[12] = (unsigned long)arg12; \
2044 __asm__ volatile( \
2045 "mr 11,%1\n\t" \
2046 "addi 1,1,-32\n\t" \
2047 /* arg12 */ \
2048 "lwz 3,48(11)\n\t" \
2049 "stw 3,20(1)\n\t" \
2050 /* arg11 */ \
2051 "lwz 3,44(11)\n\t" \
2052 "stw 3,16(1)\n\t" \
2053 /* arg10 */ \
2054 "lwz 3,40(11)\n\t" \
2055 "stw 3,12(1)\n\t" \
2056 /* arg9 */ \
2057 "lwz 3,36(11)\n\t" \
2058 "stw 3,8(1)\n\t" \
2059 /* args1-8 */ \
2060 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2061 "lwz 4,8(11)\n\t" \
2062 "lwz 5,12(11)\n\t" \
2063 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2064 "lwz 7,20(11)\n\t" \
2065 "lwz 8,24(11)\n\t" \
2066 "lwz 9,28(11)\n\t" \
2067 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2068 "lwz 11,0(11)\n\t" /* target->r11 */ \
2069 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2070 "addi 1,1,32\n\t" \
2071 "mr %0,3" \
2072 : /*out*/ "=r" (_res) \
2073 : /*in*/ "r" (&_argvec[0]) \
2074 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2075 ); \
2076 lval = (__typeof__(lval)) _res; \
2077 } while (0)
2078
sewardjf5c1a7f2006-10-17 01:32:48 +00002079#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002080
sewardjf5c1a7f2006-10-17 01:32:48 +00002081/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002082
sewardjf5c1a7f2006-10-17 01:32:48 +00002083#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002084
2085/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2086
2087/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002088#define __CALLER_SAVED_REGS \
2089 "lr", "ctr", "xer", \
2090 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2091 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2092 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002093
2094/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2095 long) == 8. */
2096
sewardjd68ac3e2006-01-20 14:31:57 +00002097#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002098 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002099 volatile OrigFn _orig = (orig); \
2100 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002101 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002102 /* _argvec[0] holds current r2 across the call */ \
2103 _argvec[1] = (unsigned long)_orig.r2; \
2104 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002105 __asm__ volatile( \
2106 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002107 "std 2,-16(11)\n\t" /* save tocptr */ \
2108 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2109 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002110 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2111 "mr 11,%1\n\t" \
2112 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002113 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002114 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002115 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002116 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2117 ); \
2118 lval = (__typeof__(lval)) _res; \
2119 } while (0)
2120
sewardjd68ac3e2006-01-20 14:31:57 +00002121#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002122 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002123 volatile OrigFn _orig = (orig); \
2124 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002125 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002126 /* _argvec[0] holds current r2 across the call */ \
2127 _argvec[1] = (unsigned long)_orig.r2; \
2128 _argvec[2] = (unsigned long)_orig.nraddr; \
2129 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002130 __asm__ volatile( \
2131 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002132 "std 2,-16(11)\n\t" /* save tocptr */ \
2133 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2134 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2135 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002136 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2137 "mr 11,%1\n\t" \
2138 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002139 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002140 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002141 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002142 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2143 ); \
2144 lval = (__typeof__(lval)) _res; \
2145 } while (0)
2146
sewardjd68ac3e2006-01-20 14:31:57 +00002147#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002148 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002149 volatile OrigFn _orig = (orig); \
2150 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002151 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002152 /* _argvec[0] holds current r2 across the call */ \
2153 _argvec[1] = (unsigned long)_orig.r2; \
2154 _argvec[2] = (unsigned long)_orig.nraddr; \
2155 _argvec[2+1] = (unsigned long)arg1; \
2156 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002157 __asm__ volatile( \
2158 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002159 "std 2,-16(11)\n\t" /* save tocptr */ \
2160 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2161 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002162 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002163 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002164 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2165 "mr 11,%1\n\t" \
2166 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002167 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002168 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002169 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002170 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2171 ); \
2172 lval = (__typeof__(lval)) _res; \
2173 } while (0)
2174
sewardjcd636392006-03-12 16:48:14 +00002175#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2176 do { \
2177 volatile OrigFn _orig = (orig); \
2178 volatile unsigned long _argvec[3+3]; \
2179 volatile unsigned long _res; \
2180 /* _argvec[0] holds current r2 across the call */ \
2181 _argvec[1] = (unsigned long)_orig.r2; \
2182 _argvec[2] = (unsigned long)_orig.nraddr; \
2183 _argvec[2+1] = (unsigned long)arg1; \
2184 _argvec[2+2] = (unsigned long)arg2; \
2185 _argvec[2+3] = (unsigned long)arg3; \
2186 __asm__ volatile( \
2187 "mr 11,%1\n\t" \
2188 "std 2,-16(11)\n\t" /* save tocptr */ \
2189 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2190 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2191 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2192 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2193 "ld 11, 0(11)\n\t" /* target->r11 */ \
2194 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2195 "mr 11,%1\n\t" \
2196 "mr %0,3\n\t" \
2197 "ld 2,-16(11)" /* restore tocptr */ \
2198 : /*out*/ "=r" (_res) \
2199 : /*in*/ "r" (&_argvec[2]) \
2200 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2201 ); \
2202 lval = (__typeof__(lval)) _res; \
2203 } while (0)
2204
2205#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2206 do { \
2207 volatile OrigFn _orig = (orig); \
2208 volatile unsigned long _argvec[3+4]; \
2209 volatile unsigned long _res; \
2210 /* _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; \
2214 _argvec[2+2] = (unsigned long)arg2; \
2215 _argvec[2+3] = (unsigned long)arg3; \
2216 _argvec[2+4] = (unsigned long)arg4; \
2217 __asm__ volatile( \
2218 "mr 11,%1\n\t" \
2219 "std 2,-16(11)\n\t" /* save tocptr */ \
2220 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2221 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2222 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2223 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2224 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2225 "ld 11, 0(11)\n\t" /* target->r11 */ \
2226 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2227 "mr 11,%1\n\t" \
2228 "mr %0,3\n\t" \
2229 "ld 2,-16(11)" /* restore tocptr */ \
2230 : /*out*/ "=r" (_res) \
2231 : /*in*/ "r" (&_argvec[2]) \
2232 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2233 ); \
2234 lval = (__typeof__(lval)) _res; \
2235 } while (0)
2236
2237#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2238 do { \
2239 volatile OrigFn _orig = (orig); \
2240 volatile unsigned long _argvec[3+5]; \
2241 volatile unsigned long _res; \
2242 /* _argvec[0] holds current r2 across the call */ \
2243 _argvec[1] = (unsigned long)_orig.r2; \
2244 _argvec[2] = (unsigned long)_orig.nraddr; \
2245 _argvec[2+1] = (unsigned long)arg1; \
2246 _argvec[2+2] = (unsigned long)arg2; \
2247 _argvec[2+3] = (unsigned long)arg3; \
2248 _argvec[2+4] = (unsigned long)arg4; \
2249 _argvec[2+5] = (unsigned long)arg5; \
2250 __asm__ volatile( \
2251 "mr 11,%1\n\t" \
2252 "std 2,-16(11)\n\t" /* save tocptr */ \
2253 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2254 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2255 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2256 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2257 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2258 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2259 "ld 11, 0(11)\n\t" /* target->r11 */ \
2260 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2261 "mr 11,%1\n\t" \
2262 "mr %0,3\n\t" \
2263 "ld 2,-16(11)" /* restore tocptr */ \
2264 : /*out*/ "=r" (_res) \
2265 : /*in*/ "r" (&_argvec[2]) \
2266 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2267 ); \
2268 lval = (__typeof__(lval)) _res; \
2269 } while (0)
2270
2271#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2272 do { \
2273 volatile OrigFn _orig = (orig); \
2274 volatile unsigned long _argvec[3+6]; \
2275 volatile unsigned long _res; \
2276 /* _argvec[0] holds current r2 across the call */ \
2277 _argvec[1] = (unsigned long)_orig.r2; \
2278 _argvec[2] = (unsigned long)_orig.nraddr; \
2279 _argvec[2+1] = (unsigned long)arg1; \
2280 _argvec[2+2] = (unsigned long)arg2; \
2281 _argvec[2+3] = (unsigned long)arg3; \
2282 _argvec[2+4] = (unsigned long)arg4; \
2283 _argvec[2+5] = (unsigned long)arg5; \
2284 _argvec[2+6] = (unsigned long)arg6; \
2285 __asm__ volatile( \
2286 "mr 11,%1\n\t" \
2287 "std 2,-16(11)\n\t" /* save tocptr */ \
2288 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2289 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2290 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2291 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2292 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2293 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2294 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2295 "ld 11, 0(11)\n\t" /* target->r11 */ \
2296 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2297 "mr 11,%1\n\t" \
2298 "mr %0,3\n\t" \
2299 "ld 2,-16(11)" /* restore tocptr */ \
2300 : /*out*/ "=r" (_res) \
2301 : /*in*/ "r" (&_argvec[2]) \
2302 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2303 ); \
2304 lval = (__typeof__(lval)) _res; \
2305 } while (0)
2306
2307#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2308 arg7) \
2309 do { \
2310 volatile OrigFn _orig = (orig); \
2311 volatile unsigned long _argvec[3+7]; \
2312 volatile unsigned long _res; \
2313 /* _argvec[0] holds current r2 across the call */ \
2314 _argvec[1] = (unsigned long)_orig.r2; \
2315 _argvec[2] = (unsigned long)_orig.nraddr; \
2316 _argvec[2+1] = (unsigned long)arg1; \
2317 _argvec[2+2] = (unsigned long)arg2; \
2318 _argvec[2+3] = (unsigned long)arg3; \
2319 _argvec[2+4] = (unsigned long)arg4; \
2320 _argvec[2+5] = (unsigned long)arg5; \
2321 _argvec[2+6] = (unsigned long)arg6; \
2322 _argvec[2+7] = (unsigned long)arg7; \
2323 __asm__ volatile( \
2324 "mr 11,%1\n\t" \
2325 "std 2,-16(11)\n\t" /* save tocptr */ \
2326 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2327 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2328 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2329 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2330 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2331 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2332 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2333 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2334 "ld 11, 0(11)\n\t" /* target->r11 */ \
2335 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2336 "mr 11,%1\n\t" \
2337 "mr %0,3\n\t" \
2338 "ld 2,-16(11)" /* restore tocptr */ \
2339 : /*out*/ "=r" (_res) \
2340 : /*in*/ "r" (&_argvec[2]) \
2341 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2342 ); \
2343 lval = (__typeof__(lval)) _res; \
2344 } while (0)
2345
2346#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2347 arg7,arg8) \
2348 do { \
2349 volatile OrigFn _orig = (orig); \
2350 volatile unsigned long _argvec[3+8]; \
2351 volatile unsigned long _res; \
2352 /* _argvec[0] holds current r2 across the call */ \
2353 _argvec[1] = (unsigned long)_orig.r2; \
2354 _argvec[2] = (unsigned long)_orig.nraddr; \
2355 _argvec[2+1] = (unsigned long)arg1; \
2356 _argvec[2+2] = (unsigned long)arg2; \
2357 _argvec[2+3] = (unsigned long)arg3; \
2358 _argvec[2+4] = (unsigned long)arg4; \
2359 _argvec[2+5] = (unsigned long)arg5; \
2360 _argvec[2+6] = (unsigned long)arg6; \
2361 _argvec[2+7] = (unsigned long)arg7; \
2362 _argvec[2+8] = (unsigned long)arg8; \
2363 __asm__ volatile( \
2364 "mr 11,%1\n\t" \
2365 "std 2,-16(11)\n\t" /* save tocptr */ \
2366 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2367 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2368 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2369 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2370 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2371 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2372 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2373 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2374 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2375 "ld 11, 0(11)\n\t" /* target->r11 */ \
2376 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2377 "mr 11,%1\n\t" \
2378 "mr %0,3\n\t" \
2379 "ld 2,-16(11)" /* restore tocptr */ \
2380 : /*out*/ "=r" (_res) \
2381 : /*in*/ "r" (&_argvec[2]) \
2382 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2383 ); \
2384 lval = (__typeof__(lval)) _res; \
2385 } while (0)
2386
2387#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2388 arg7,arg8,arg9) \
2389 do { \
2390 volatile OrigFn _orig = (orig); \
2391 volatile unsigned long _argvec[3+9]; \
2392 volatile unsigned long _res; \
2393 /* _argvec[0] holds current r2 across the call */ \
2394 _argvec[1] = (unsigned long)_orig.r2; \
2395 _argvec[2] = (unsigned long)_orig.nraddr; \
2396 _argvec[2+1] = (unsigned long)arg1; \
2397 _argvec[2+2] = (unsigned long)arg2; \
2398 _argvec[2+3] = (unsigned long)arg3; \
2399 _argvec[2+4] = (unsigned long)arg4; \
2400 _argvec[2+5] = (unsigned long)arg5; \
2401 _argvec[2+6] = (unsigned long)arg6; \
2402 _argvec[2+7] = (unsigned long)arg7; \
2403 _argvec[2+8] = (unsigned long)arg8; \
2404 _argvec[2+9] = (unsigned long)arg9; \
2405 __asm__ volatile( \
2406 "mr 11,%1\n\t" \
2407 "std 2,-16(11)\n\t" /* save tocptr */ \
2408 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2409 "addi 1,1,-128\n\t" /* expand stack frame */ \
2410 /* arg9 */ \
2411 "ld 3,72(11)\n\t" \
2412 "std 3,112(1)\n\t" \
2413 /* args1-8 */ \
2414 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2415 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2416 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2417 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2418 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2419 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2420 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2421 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2422 "ld 11, 0(11)\n\t" /* target->r11 */ \
2423 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2424 "mr 11,%1\n\t" \
2425 "mr %0,3\n\t" \
2426 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2427 "addi 1,1,128" /* restore frame */ \
2428 : /*out*/ "=r" (_res) \
2429 : /*in*/ "r" (&_argvec[2]) \
2430 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2431 ); \
2432 lval = (__typeof__(lval)) _res; \
2433 } while (0)
2434
2435#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2436 arg7,arg8,arg9,arg10) \
2437 do { \
2438 volatile OrigFn _orig = (orig); \
2439 volatile unsigned long _argvec[3+10]; \
2440 volatile unsigned long _res; \
2441 /* _argvec[0] holds current r2 across the call */ \
2442 _argvec[1] = (unsigned long)_orig.r2; \
2443 _argvec[2] = (unsigned long)_orig.nraddr; \
2444 _argvec[2+1] = (unsigned long)arg1; \
2445 _argvec[2+2] = (unsigned long)arg2; \
2446 _argvec[2+3] = (unsigned long)arg3; \
2447 _argvec[2+4] = (unsigned long)arg4; \
2448 _argvec[2+5] = (unsigned long)arg5; \
2449 _argvec[2+6] = (unsigned long)arg6; \
2450 _argvec[2+7] = (unsigned long)arg7; \
2451 _argvec[2+8] = (unsigned long)arg8; \
2452 _argvec[2+9] = (unsigned long)arg9; \
2453 _argvec[2+10] = (unsigned long)arg10; \
2454 __asm__ volatile( \
2455 "mr 11,%1\n\t" \
2456 "std 2,-16(11)\n\t" /* save tocptr */ \
2457 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2458 "addi 1,1,-128\n\t" /* expand stack frame */ \
2459 /* arg10 */ \
2460 "ld 3,80(11)\n\t" \
2461 "std 3,120(1)\n\t" \
2462 /* arg9 */ \
2463 "ld 3,72(11)\n\t" \
2464 "std 3,112(1)\n\t" \
2465 /* args1-8 */ \
2466 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2467 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2468 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2469 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2470 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2471 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2472 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2473 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2474 "ld 11, 0(11)\n\t" /* target->r11 */ \
2475 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2476 "mr 11,%1\n\t" \
2477 "mr %0,3\n\t" \
2478 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2479 "addi 1,1,128" /* restore frame */ \
2480 : /*out*/ "=r" (_res) \
2481 : /*in*/ "r" (&_argvec[2]) \
2482 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2483 ); \
2484 lval = (__typeof__(lval)) _res; \
2485 } while (0)
2486
2487#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2488 arg7,arg8,arg9,arg10,arg11) \
2489 do { \
2490 volatile OrigFn _orig = (orig); \
2491 volatile unsigned long _argvec[3+11]; \
2492 volatile unsigned long _res; \
2493 /* _argvec[0] holds current r2 across the call */ \
2494 _argvec[1] = (unsigned long)_orig.r2; \
2495 _argvec[2] = (unsigned long)_orig.nraddr; \
2496 _argvec[2+1] = (unsigned long)arg1; \
2497 _argvec[2+2] = (unsigned long)arg2; \
2498 _argvec[2+3] = (unsigned long)arg3; \
2499 _argvec[2+4] = (unsigned long)arg4; \
2500 _argvec[2+5] = (unsigned long)arg5; \
2501 _argvec[2+6] = (unsigned long)arg6; \
2502 _argvec[2+7] = (unsigned long)arg7; \
2503 _argvec[2+8] = (unsigned long)arg8; \
2504 _argvec[2+9] = (unsigned long)arg9; \
2505 _argvec[2+10] = (unsigned long)arg10; \
2506 _argvec[2+11] = (unsigned long)arg11; \
2507 __asm__ volatile( \
2508 "mr 11,%1\n\t" \
2509 "std 2,-16(11)\n\t" /* save tocptr */ \
2510 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2511 "addi 1,1,-144\n\t" /* expand stack frame */ \
2512 /* arg11 */ \
2513 "ld 3,88(11)\n\t" \
2514 "std 3,128(1)\n\t" \
2515 /* arg10 */ \
2516 "ld 3,80(11)\n\t" \
2517 "std 3,120(1)\n\t" \
2518 /* arg9 */ \
2519 "ld 3,72(11)\n\t" \
2520 "std 3,112(1)\n\t" \
2521 /* args1-8 */ \
2522 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2523 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2524 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2525 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2526 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2527 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2528 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2529 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2530 "ld 11, 0(11)\n\t" /* target->r11 */ \
2531 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2532 "mr 11,%1\n\t" \
2533 "mr %0,3\n\t" \
2534 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2535 "addi 1,1,144" /* restore frame */ \
2536 : /*out*/ "=r" (_res) \
2537 : /*in*/ "r" (&_argvec[2]) \
2538 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2539 ); \
2540 lval = (__typeof__(lval)) _res; \
2541 } while (0)
2542
2543#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2544 arg7,arg8,arg9,arg10,arg11,arg12) \
2545 do { \
2546 volatile OrigFn _orig = (orig); \
2547 volatile unsigned long _argvec[3+12]; \
2548 volatile unsigned long _res; \
2549 /* _argvec[0] holds current r2 across the call */ \
2550 _argvec[1] = (unsigned long)_orig.r2; \
2551 _argvec[2] = (unsigned long)_orig.nraddr; \
2552 _argvec[2+1] = (unsigned long)arg1; \
2553 _argvec[2+2] = (unsigned long)arg2; \
2554 _argvec[2+3] = (unsigned long)arg3; \
2555 _argvec[2+4] = (unsigned long)arg4; \
2556 _argvec[2+5] = (unsigned long)arg5; \
2557 _argvec[2+6] = (unsigned long)arg6; \
2558 _argvec[2+7] = (unsigned long)arg7; \
2559 _argvec[2+8] = (unsigned long)arg8; \
2560 _argvec[2+9] = (unsigned long)arg9; \
2561 _argvec[2+10] = (unsigned long)arg10; \
2562 _argvec[2+11] = (unsigned long)arg11; \
2563 _argvec[2+12] = (unsigned long)arg12; \
2564 __asm__ volatile( \
2565 "mr 11,%1\n\t" \
2566 "std 2,-16(11)\n\t" /* save tocptr */ \
2567 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2568 "addi 1,1,-144\n\t" /* expand stack frame */ \
2569 /* arg12 */ \
2570 "ld 3,96(11)\n\t" \
2571 "std 3,136(1)\n\t" \
2572 /* arg11 */ \
2573 "ld 3,88(11)\n\t" \
2574 "std 3,128(1)\n\t" \
2575 /* arg10 */ \
2576 "ld 3,80(11)\n\t" \
2577 "std 3,120(1)\n\t" \
2578 /* arg9 */ \
2579 "ld 3,72(11)\n\t" \
2580 "std 3,112(1)\n\t" \
2581 /* args1-8 */ \
2582 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2583 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2584 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2585 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2586 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2587 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2588 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2589 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2590 "ld 11, 0(11)\n\t" /* target->r11 */ \
2591 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2592 "mr 11,%1\n\t" \
2593 "mr %0,3\n\t" \
2594 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2595 "addi 1,1,144" /* restore frame */ \
2596 : /*out*/ "=r" (_res) \
2597 : /*in*/ "r" (&_argvec[2]) \
2598 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2599 ); \
2600 lval = (__typeof__(lval)) _res; \
2601 } while (0)
2602
sewardjf5c1a7f2006-10-17 01:32:48 +00002603#endif /* PLAT_ppc64_linux */
2604
sewardj59570ff2010-01-01 11:59:33 +00002605/* ------------------------- arm-linux ------------------------- */
2606
2607#if defined(PLAT_arm_linux)
2608
2609/* These regs are trashed by the hidden call. */
2610#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2611
2612/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2613 long) == 4. */
2614
2615#define CALL_FN_W_v(lval, orig) \
2616 do { \
2617 volatile OrigFn _orig = (orig); \
2618 volatile unsigned long _argvec[1]; \
2619 volatile unsigned long _res; \
2620 _argvec[0] = (unsigned long)_orig.nraddr; \
2621 __asm__ volatile( \
2622 "ldr r4, [%1] \n\t" /* target->r4 */ \
2623 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2624 "mov %0, r0\n" \
2625 : /*out*/ "=r" (_res) \
2626 : /*in*/ "0" (&_argvec[0]) \
2627 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2628 ); \
2629 lval = (__typeof__(lval)) _res; \
2630 } while (0)
2631
2632#define CALL_FN_W_W(lval, orig, arg1) \
2633 do { \
2634 volatile OrigFn _orig = (orig); \
2635 volatile unsigned long _argvec[2]; \
2636 volatile unsigned long _res; \
2637 _argvec[0] = (unsigned long)_orig.nraddr; \
2638 _argvec[1] = (unsigned long)(arg1); \
2639 __asm__ volatile( \
2640 "ldr r0, [%1, #4] \n\t" \
2641 "ldr r4, [%1] \n\t" /* target->r4 */ \
2642 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2643 "mov %0, r0\n" \
2644 : /*out*/ "=r" (_res) \
2645 : /*in*/ "0" (&_argvec[0]) \
2646 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2647 ); \
2648 lval = (__typeof__(lval)) _res; \
2649 } while (0)
2650
2651#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2652 do { \
2653 volatile OrigFn _orig = (orig); \
2654 volatile unsigned long _argvec[3]; \
2655 volatile unsigned long _res; \
2656 _argvec[0] = (unsigned long)_orig.nraddr; \
2657 _argvec[1] = (unsigned long)(arg1); \
2658 _argvec[2] = (unsigned long)(arg2); \
2659 __asm__ volatile( \
2660 "ldr r0, [%1, #4] \n\t" \
2661 "ldr r1, [%1, #8] \n\t" \
2662 "ldr r4, [%1] \n\t" /* target->r4 */ \
2663 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2664 "mov %0, r0\n" \
2665 : /*out*/ "=r" (_res) \
2666 : /*in*/ "0" (&_argvec[0]) \
2667 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2668 ); \
2669 lval = (__typeof__(lval)) _res; \
2670 } while (0)
2671
2672#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2673 do { \
2674 volatile OrigFn _orig = (orig); \
2675 volatile unsigned long _argvec[4]; \
2676 volatile unsigned long _res; \
2677 _argvec[0] = (unsigned long)_orig.nraddr; \
2678 _argvec[1] = (unsigned long)(arg1); \
2679 _argvec[2] = (unsigned long)(arg2); \
2680 _argvec[3] = (unsigned long)(arg3); \
2681 __asm__ volatile( \
2682 "ldr r0, [%1, #4] \n\t" \
2683 "ldr r1, [%1, #8] \n\t" \
2684 "ldr r2, [%1, #12] \n\t" \
2685 "ldr r4, [%1] \n\t" /* target->r4 */ \
2686 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2687 "mov %0, r0\n" \
2688 : /*out*/ "=r" (_res) \
2689 : /*in*/ "0" (&_argvec[0]) \
2690 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2691 ); \
2692 lval = (__typeof__(lval)) _res; \
2693 } while (0)
2694
2695#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2696 do { \
2697 volatile OrigFn _orig = (orig); \
2698 volatile unsigned long _argvec[5]; \
2699 volatile unsigned long _res; \
2700 _argvec[0] = (unsigned long)_orig.nraddr; \
2701 _argvec[1] = (unsigned long)(arg1); \
2702 _argvec[2] = (unsigned long)(arg2); \
2703 _argvec[3] = (unsigned long)(arg3); \
2704 _argvec[4] = (unsigned long)(arg4); \
2705 __asm__ volatile( \
2706 "ldr r0, [%1, #4] \n\t" \
2707 "ldr r1, [%1, #8] \n\t" \
2708 "ldr r2, [%1, #12] \n\t" \
2709 "ldr r3, [%1, #16] \n\t" \
2710 "ldr r4, [%1] \n\t" /* target->r4 */ \
2711 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2712 "mov %0, r0" \
2713 : /*out*/ "=r" (_res) \
2714 : /*in*/ "0" (&_argvec[0]) \
2715 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2716 ); \
2717 lval = (__typeof__(lval)) _res; \
2718 } while (0)
2719
2720#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2721 do { \
2722 volatile OrigFn _orig = (orig); \
2723 volatile unsigned long _argvec[6]; \
2724 volatile unsigned long _res; \
2725 _argvec[0] = (unsigned long)_orig.nraddr; \
2726 _argvec[1] = (unsigned long)(arg1); \
2727 _argvec[2] = (unsigned long)(arg2); \
2728 _argvec[3] = (unsigned long)(arg3); \
2729 _argvec[4] = (unsigned long)(arg4); \
2730 _argvec[5] = (unsigned long)(arg5); \
2731 __asm__ volatile( \
2732 "ldr r0, [%1, #20] \n\t" \
2733 "push {r0} \n\t" \
2734 "ldr r0, [%1, #4] \n\t" \
2735 "ldr r1, [%1, #8] \n\t" \
2736 "ldr r2, [%1, #12] \n\t" \
2737 "ldr r3, [%1, #16] \n\t" \
2738 "ldr r4, [%1] \n\t" /* target->r4 */ \
2739 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2740 "add sp, sp, #4 \n\t" \
2741 "mov %0, r0" \
2742 : /*out*/ "=r" (_res) \
2743 : /*in*/ "0" (&_argvec[0]) \
2744 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2745 ); \
2746 lval = (__typeof__(lval)) _res; \
2747 } while (0)
2748
2749#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2750 do { \
2751 volatile OrigFn _orig = (orig); \
2752 volatile unsigned long _argvec[7]; \
2753 volatile unsigned long _res; \
2754 _argvec[0] = (unsigned long)_orig.nraddr; \
2755 _argvec[1] = (unsigned long)(arg1); \
2756 _argvec[2] = (unsigned long)(arg2); \
2757 _argvec[3] = (unsigned long)(arg3); \
2758 _argvec[4] = (unsigned long)(arg4); \
2759 _argvec[5] = (unsigned long)(arg5); \
2760 _argvec[6] = (unsigned long)(arg6); \
2761 __asm__ volatile( \
2762 "ldr r0, [%1, #20] \n\t" \
2763 "ldr r1, [%1, #24] \n\t" \
2764 "push {r0, r1} \n\t" \
2765 "ldr r0, [%1, #4] \n\t" \
2766 "ldr r1, [%1, #8] \n\t" \
2767 "ldr r2, [%1, #12] \n\t" \
2768 "ldr r3, [%1, #16] \n\t" \
2769 "ldr r4, [%1] \n\t" /* target->r4 */ \
2770 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2771 "add sp, sp, #8 \n\t" \
2772 "mov %0, r0" \
2773 : /*out*/ "=r" (_res) \
2774 : /*in*/ "0" (&_argvec[0]) \
2775 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2776 ); \
2777 lval = (__typeof__(lval)) _res; \
2778 } while (0)
2779
2780#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2781 arg7) \
2782 do { \
2783 volatile OrigFn _orig = (orig); \
2784 volatile unsigned long _argvec[8]; \
2785 volatile unsigned long _res; \
2786 _argvec[0] = (unsigned long)_orig.nraddr; \
2787 _argvec[1] = (unsigned long)(arg1); \
2788 _argvec[2] = (unsigned long)(arg2); \
2789 _argvec[3] = (unsigned long)(arg3); \
2790 _argvec[4] = (unsigned long)(arg4); \
2791 _argvec[5] = (unsigned long)(arg5); \
2792 _argvec[6] = (unsigned long)(arg6); \
2793 _argvec[7] = (unsigned long)(arg7); \
2794 __asm__ volatile( \
2795 "ldr r0, [%1, #20] \n\t" \
2796 "ldr r1, [%1, #24] \n\t" \
2797 "ldr r2, [%1, #28] \n\t" \
2798 "push {r0, r1, r2} \n\t" \
2799 "ldr r0, [%1, #4] \n\t" \
2800 "ldr r1, [%1, #8] \n\t" \
2801 "ldr r2, [%1, #12] \n\t" \
2802 "ldr r3, [%1, #16] \n\t" \
2803 "ldr r4, [%1] \n\t" /* target->r4 */ \
2804 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2805 "add sp, sp, #12 \n\t" \
2806 "mov %0, r0" \
2807 : /*out*/ "=r" (_res) \
2808 : /*in*/ "0" (&_argvec[0]) \
2809 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2810 ); \
2811 lval = (__typeof__(lval)) _res; \
2812 } while (0)
2813
2814#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2815 arg7,arg8) \
2816 do { \
2817 volatile OrigFn _orig = (orig); \
2818 volatile unsigned long _argvec[9]; \
2819 volatile unsigned long _res; \
2820 _argvec[0] = (unsigned long)_orig.nraddr; \
2821 _argvec[1] = (unsigned long)(arg1); \
2822 _argvec[2] = (unsigned long)(arg2); \
2823 _argvec[3] = (unsigned long)(arg3); \
2824 _argvec[4] = (unsigned long)(arg4); \
2825 _argvec[5] = (unsigned long)(arg5); \
2826 _argvec[6] = (unsigned long)(arg6); \
2827 _argvec[7] = (unsigned long)(arg7); \
2828 _argvec[8] = (unsigned long)(arg8); \
2829 __asm__ volatile( \
2830 "ldr r0, [%1, #20] \n\t" \
2831 "ldr r1, [%1, #24] \n\t" \
2832 "ldr r2, [%1, #28] \n\t" \
2833 "ldr r3, [%1, #32] \n\t" \
2834 "push {r0, r1, r2, r3} \n\t" \
2835 "ldr r0, [%1, #4] \n\t" \
2836 "ldr r1, [%1, #8] \n\t" \
2837 "ldr r2, [%1, #12] \n\t" \
2838 "ldr r3, [%1, #16] \n\t" \
2839 "ldr r4, [%1] \n\t" /* target->r4 */ \
2840 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2841 "add sp, sp, #16 \n\t" \
2842 "mov %0, r0" \
2843 : /*out*/ "=r" (_res) \
2844 : /*in*/ "0" (&_argvec[0]) \
2845 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2846 ); \
2847 lval = (__typeof__(lval)) _res; \
2848 } while (0)
2849
2850#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2851 arg7,arg8,arg9) \
2852 do { \
2853 volatile OrigFn _orig = (orig); \
2854 volatile unsigned long _argvec[10]; \
2855 volatile unsigned long _res; \
2856 _argvec[0] = (unsigned long)_orig.nraddr; \
2857 _argvec[1] = (unsigned long)(arg1); \
2858 _argvec[2] = (unsigned long)(arg2); \
2859 _argvec[3] = (unsigned long)(arg3); \
2860 _argvec[4] = (unsigned long)(arg4); \
2861 _argvec[5] = (unsigned long)(arg5); \
2862 _argvec[6] = (unsigned long)(arg6); \
2863 _argvec[7] = (unsigned long)(arg7); \
2864 _argvec[8] = (unsigned long)(arg8); \
2865 _argvec[9] = (unsigned long)(arg9); \
2866 __asm__ volatile( \
2867 "ldr r0, [%1, #20] \n\t" \
2868 "ldr r1, [%1, #24] \n\t" \
2869 "ldr r2, [%1, #28] \n\t" \
2870 "ldr r3, [%1, #32] \n\t" \
2871 "ldr r4, [%1, #36] \n\t" \
2872 "push {r0, r1, r2, r3, r4} \n\t" \
2873 "ldr r0, [%1, #4] \n\t" \
2874 "ldr r1, [%1, #8] \n\t" \
2875 "ldr r2, [%1, #12] \n\t" \
2876 "ldr r3, [%1, #16] \n\t" \
2877 "ldr r4, [%1] \n\t" /* target->r4 */ \
2878 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2879 "add sp, sp, #20 \n\t" \
2880 "mov %0, r0" \
2881 : /*out*/ "=r" (_res) \
2882 : /*in*/ "0" (&_argvec[0]) \
2883 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2884 ); \
2885 lval = (__typeof__(lval)) _res; \
2886 } while (0)
2887
2888#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2889 arg7,arg8,arg9,arg10) \
2890 do { \
2891 volatile OrigFn _orig = (orig); \
2892 volatile unsigned long _argvec[11]; \
2893 volatile unsigned long _res; \
2894 _argvec[0] = (unsigned long)_orig.nraddr; \
2895 _argvec[1] = (unsigned long)(arg1); \
2896 _argvec[2] = (unsigned long)(arg2); \
2897 _argvec[3] = (unsigned long)(arg3); \
2898 _argvec[4] = (unsigned long)(arg4); \
2899 _argvec[5] = (unsigned long)(arg5); \
2900 _argvec[6] = (unsigned long)(arg6); \
2901 _argvec[7] = (unsigned long)(arg7); \
2902 _argvec[8] = (unsigned long)(arg8); \
2903 _argvec[9] = (unsigned long)(arg9); \
2904 _argvec[10] = (unsigned long)(arg10); \
2905 __asm__ volatile( \
2906 "ldr r0, [%1, #40] \n\t" \
2907 "push {r0} \n\t" \
2908 "ldr r0, [%1, #20] \n\t" \
2909 "ldr r1, [%1, #24] \n\t" \
2910 "ldr r2, [%1, #28] \n\t" \
2911 "ldr r3, [%1, #32] \n\t" \
2912 "ldr r4, [%1, #36] \n\t" \
2913 "push {r0, r1, r2, r3, r4} \n\t" \
2914 "ldr r0, [%1, #4] \n\t" \
2915 "ldr r1, [%1, #8] \n\t" \
2916 "ldr r2, [%1, #12] \n\t" \
2917 "ldr r3, [%1, #16] \n\t" \
2918 "ldr r4, [%1] \n\t" /* target->r4 */ \
2919 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2920 "add sp, sp, #24 \n\t" \
2921 "mov %0, r0" \
2922 : /*out*/ "=r" (_res) \
2923 : /*in*/ "0" (&_argvec[0]) \
2924 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2925 ); \
2926 lval = (__typeof__(lval)) _res; \
2927 } while (0)
2928
2929#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2930 arg6,arg7,arg8,arg9,arg10, \
2931 arg11) \
2932 do { \
2933 volatile OrigFn _orig = (orig); \
2934 volatile unsigned long _argvec[12]; \
2935 volatile unsigned long _res; \
2936 _argvec[0] = (unsigned long)_orig.nraddr; \
2937 _argvec[1] = (unsigned long)(arg1); \
2938 _argvec[2] = (unsigned long)(arg2); \
2939 _argvec[3] = (unsigned long)(arg3); \
2940 _argvec[4] = (unsigned long)(arg4); \
2941 _argvec[5] = (unsigned long)(arg5); \
2942 _argvec[6] = (unsigned long)(arg6); \
2943 _argvec[7] = (unsigned long)(arg7); \
2944 _argvec[8] = (unsigned long)(arg8); \
2945 _argvec[9] = (unsigned long)(arg9); \
2946 _argvec[10] = (unsigned long)(arg10); \
2947 _argvec[11] = (unsigned long)(arg11); \
2948 __asm__ volatile( \
2949 "ldr r0, [%1, #40] \n\t" \
2950 "ldr r1, [%1, #44] \n\t" \
2951 "push {r0, r1} \n\t" \
2952 "ldr r0, [%1, #20] \n\t" \
2953 "ldr r1, [%1, #24] \n\t" \
2954 "ldr r2, [%1, #28] \n\t" \
2955 "ldr r3, [%1, #32] \n\t" \
2956 "ldr r4, [%1, #36] \n\t" \
2957 "push {r0, r1, r2, r3, r4} \n\t" \
2958 "ldr r0, [%1, #4] \n\t" \
2959 "ldr r1, [%1, #8] \n\t" \
2960 "ldr r2, [%1, #12] \n\t" \
2961 "ldr r3, [%1, #16] \n\t" \
2962 "ldr r4, [%1] \n\t" /* target->r4 */ \
2963 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2964 "add sp, sp, #28 \n\t" \
2965 "mov %0, r0" \
2966 : /*out*/ "=r" (_res) \
2967 : /*in*/ "0" (&_argvec[0]) \
2968 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
2969 ); \
2970 lval = (__typeof__(lval)) _res; \
2971 } while (0)
2972
2973#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2974 arg6,arg7,arg8,arg9,arg10, \
2975 arg11,arg12) \
2976 do { \
2977 volatile OrigFn _orig = (orig); \
2978 volatile unsigned long _argvec[13]; \
2979 volatile unsigned long _res; \
2980 _argvec[0] = (unsigned long)_orig.nraddr; \
2981 _argvec[1] = (unsigned long)(arg1); \
2982 _argvec[2] = (unsigned long)(arg2); \
2983 _argvec[3] = (unsigned long)(arg3); \
2984 _argvec[4] = (unsigned long)(arg4); \
2985 _argvec[5] = (unsigned long)(arg5); \
2986 _argvec[6] = (unsigned long)(arg6); \
2987 _argvec[7] = (unsigned long)(arg7); \
2988 _argvec[8] = (unsigned long)(arg8); \
2989 _argvec[9] = (unsigned long)(arg9); \
2990 _argvec[10] = (unsigned long)(arg10); \
2991 _argvec[11] = (unsigned long)(arg11); \
2992 _argvec[12] = (unsigned long)(arg12); \
2993 __asm__ volatile( \
2994 "ldr r0, [%1, #40] \n\t" \
2995 "ldr r1, [%1, #44] \n\t" \
2996 "ldr r2, [%1, #48] \n\t" \
2997 "push {r0, r1, r2} \n\t" \
2998 "ldr r0, [%1, #20] \n\t" \
2999 "ldr r1, [%1, #24] \n\t" \
3000 "ldr r2, [%1, #28] \n\t" \
3001 "ldr r3, [%1, #32] \n\t" \
3002 "ldr r4, [%1, #36] \n\t" \
3003 "push {r0, r1, r2, r3, r4} \n\t" \
3004 "ldr r0, [%1, #4] \n\t" \
3005 "ldr r1, [%1, #8] \n\t" \
3006 "ldr r2, [%1, #12] \n\t" \
3007 "ldr r3, [%1, #16] \n\t" \
3008 "ldr r4, [%1] \n\t" /* target->r4 */ \
3009 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3010 "add sp, sp, #32 \n\t" \
3011 "mov %0, r0" \
3012 : /*out*/ "=r" (_res) \
3013 : /*in*/ "0" (&_argvec[0]) \
3014 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3015 ); \
3016 lval = (__typeof__(lval)) _res; \
3017 } while (0)
3018
3019#endif /* PLAT_arm_linux */
3020
sewardjf5c1a7f2006-10-17 01:32:48 +00003021/* ------------------------ ppc32-aix5 ------------------------- */
3022
3023#if defined(PLAT_ppc32_aix5)
3024
3025/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3026
3027/* These regs are trashed by the hidden call. */
3028#define __CALLER_SAVED_REGS \
3029 "lr", "ctr", "xer", \
3030 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3031 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3032 "r11", "r12", "r13"
3033
3034/* Expand the stack frame, copying enough info that unwinding
3035 still works. Trashes r3. */
3036
3037#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3038 "addi 1,1,-" #_n_fr "\n\t" \
3039 "lwz 3," #_n_fr "(1)\n\t" \
3040 "stw 3,0(1)\n\t"
3041
3042#define VG_CONTRACT_FRAME_BY(_n_fr) \
3043 "addi 1,1," #_n_fr "\n\t"
3044
3045/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
3046 long) == 4. */
3047
3048#define CALL_FN_W_v(lval, orig) \
3049 do { \
3050 volatile OrigFn _orig = (orig); \
3051 volatile unsigned long _argvec[3+0]; \
3052 volatile unsigned long _res; \
3053 /* _argvec[0] holds current r2 across the call */ \
3054 _argvec[1] = (unsigned long)_orig.r2; \
3055 _argvec[2] = (unsigned long)_orig.nraddr; \
3056 __asm__ volatile( \
3057 "mr 11,%1\n\t" \
3058 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3059 "stw 2,-8(11)\n\t" /* save tocptr */ \
3060 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3061 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3062 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3063 "mr 11,%1\n\t" \
3064 "mr %0,3\n\t" \
3065 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3066 VG_CONTRACT_FRAME_BY(512) \
3067 : /*out*/ "=r" (_res) \
3068 : /*in*/ "r" (&_argvec[2]) \
3069 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3070 ); \
3071 lval = (__typeof__(lval)) _res; \
3072 } while (0)
3073
3074#define CALL_FN_W_W(lval, orig, arg1) \
3075 do { \
3076 volatile OrigFn _orig = (orig); \
3077 volatile unsigned long _argvec[3+1]; \
3078 volatile unsigned long _res; \
3079 /* _argvec[0] holds current r2 across the call */ \
3080 _argvec[1] = (unsigned long)_orig.r2; \
3081 _argvec[2] = (unsigned long)_orig.nraddr; \
3082 _argvec[2+1] = (unsigned long)arg1; \
3083 __asm__ volatile( \
3084 "mr 11,%1\n\t" \
3085 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3086 "stw 2,-8(11)\n\t" /* save tocptr */ \
3087 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3088 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3089 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3090 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3091 "mr 11,%1\n\t" \
3092 "mr %0,3\n\t" \
3093 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3094 VG_CONTRACT_FRAME_BY(512) \
3095 : /*out*/ "=r" (_res) \
3096 : /*in*/ "r" (&_argvec[2]) \
3097 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3098 ); \
3099 lval = (__typeof__(lval)) _res; \
3100 } while (0)
3101
3102#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3103 do { \
3104 volatile OrigFn _orig = (orig); \
3105 volatile unsigned long _argvec[3+2]; \
3106 volatile unsigned long _res; \
3107 /* _argvec[0] holds current r2 across the call */ \
3108 _argvec[1] = (unsigned long)_orig.r2; \
3109 _argvec[2] = (unsigned long)_orig.nraddr; \
3110 _argvec[2+1] = (unsigned long)arg1; \
3111 _argvec[2+2] = (unsigned long)arg2; \
3112 __asm__ volatile( \
3113 "mr 11,%1\n\t" \
3114 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3115 "stw 2,-8(11)\n\t" /* save tocptr */ \
3116 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3117 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3118 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3119 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3120 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3121 "mr 11,%1\n\t" \
3122 "mr %0,3\n\t" \
3123 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3124 VG_CONTRACT_FRAME_BY(512) \
3125 : /*out*/ "=r" (_res) \
3126 : /*in*/ "r" (&_argvec[2]) \
3127 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3128 ); \
3129 lval = (__typeof__(lval)) _res; \
3130 } while (0)
3131
3132#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3133 do { \
3134 volatile OrigFn _orig = (orig); \
3135 volatile unsigned long _argvec[3+3]; \
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 _argvec[2+1] = (unsigned long)arg1; \
3141 _argvec[2+2] = (unsigned long)arg2; \
3142 _argvec[2+3] = (unsigned long)arg3; \
3143 __asm__ volatile( \
3144 "mr 11,%1\n\t" \
3145 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3146 "stw 2,-8(11)\n\t" /* save tocptr */ \
3147 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3148 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3149 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3150 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3151 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3152 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3153 "mr 11,%1\n\t" \
3154 "mr %0,3\n\t" \
3155 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3156 VG_CONTRACT_FRAME_BY(512) \
3157 : /*out*/ "=r" (_res) \
3158 : /*in*/ "r" (&_argvec[2]) \
3159 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3160 ); \
3161 lval = (__typeof__(lval)) _res; \
3162 } while (0)
3163
3164#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3165 do { \
3166 volatile OrigFn _orig = (orig); \
3167 volatile unsigned long _argvec[3+4]; \
3168 volatile unsigned long _res; \
3169 /* _argvec[0] holds current r2 across the call */ \
3170 _argvec[1] = (unsigned long)_orig.r2; \
3171 _argvec[2] = (unsigned long)_orig.nraddr; \
3172 _argvec[2+1] = (unsigned long)arg1; \
3173 _argvec[2+2] = (unsigned long)arg2; \
3174 _argvec[2+3] = (unsigned long)arg3; \
3175 _argvec[2+4] = (unsigned long)arg4; \
3176 __asm__ volatile( \
3177 "mr 11,%1\n\t" \
3178 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3179 "stw 2,-8(11)\n\t" /* save tocptr */ \
3180 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3181 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3182 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3183 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3184 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3185 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3186 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3187 "mr 11,%1\n\t" \
3188 "mr %0,3\n\t" \
3189 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3190 VG_CONTRACT_FRAME_BY(512) \
3191 : /*out*/ "=r" (_res) \
3192 : /*in*/ "r" (&_argvec[2]) \
3193 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3194 ); \
3195 lval = (__typeof__(lval)) _res; \
3196 } while (0)
3197
3198#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3199 do { \
3200 volatile OrigFn _orig = (orig); \
3201 volatile unsigned long _argvec[3+5]; \
3202 volatile unsigned long _res; \
3203 /* _argvec[0] holds current r2 across the call */ \
3204 _argvec[1] = (unsigned long)_orig.r2; \
3205 _argvec[2] = (unsigned long)_orig.nraddr; \
3206 _argvec[2+1] = (unsigned long)arg1; \
3207 _argvec[2+2] = (unsigned long)arg2; \
3208 _argvec[2+3] = (unsigned long)arg3; \
3209 _argvec[2+4] = (unsigned long)arg4; \
3210 _argvec[2+5] = (unsigned long)arg5; \
3211 __asm__ volatile( \
3212 "mr 11,%1\n\t" \
3213 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3214 "stw 2,-8(11)\n\t" /* save tocptr */ \
3215 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3216 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3217 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3218 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3219 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3220 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3221 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3222 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3223 "mr 11,%1\n\t" \
3224 "mr %0,3\n\t" \
3225 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3226 VG_CONTRACT_FRAME_BY(512) \
3227 : /*out*/ "=r" (_res) \
3228 : /*in*/ "r" (&_argvec[2]) \
3229 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3230 ); \
3231 lval = (__typeof__(lval)) _res; \
3232 } while (0)
3233
3234#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3235 do { \
3236 volatile OrigFn _orig = (orig); \
3237 volatile unsigned long _argvec[3+6]; \
3238 volatile unsigned long _res; \
3239 /* _argvec[0] holds current r2 across the call */ \
3240 _argvec[1] = (unsigned long)_orig.r2; \
3241 _argvec[2] = (unsigned long)_orig.nraddr; \
3242 _argvec[2+1] = (unsigned long)arg1; \
3243 _argvec[2+2] = (unsigned long)arg2; \
3244 _argvec[2+3] = (unsigned long)arg3; \
3245 _argvec[2+4] = (unsigned long)arg4; \
3246 _argvec[2+5] = (unsigned long)arg5; \
3247 _argvec[2+6] = (unsigned long)arg6; \
3248 __asm__ volatile( \
3249 "mr 11,%1\n\t" \
3250 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3251 "stw 2,-8(11)\n\t" /* save tocptr */ \
3252 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3253 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3254 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3255 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3256 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3257 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3258 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3259 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3260 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3261 "mr 11,%1\n\t" \
3262 "mr %0,3\n\t" \
3263 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3264 VG_CONTRACT_FRAME_BY(512) \
3265 : /*out*/ "=r" (_res) \
3266 : /*in*/ "r" (&_argvec[2]) \
3267 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3268 ); \
3269 lval = (__typeof__(lval)) _res; \
3270 } while (0)
3271
3272#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3273 arg7) \
3274 do { \
3275 volatile OrigFn _orig = (orig); \
3276 volatile unsigned long _argvec[3+7]; \
3277 volatile unsigned long _res; \
3278 /* _argvec[0] holds current r2 across the call */ \
3279 _argvec[1] = (unsigned long)_orig.r2; \
3280 _argvec[2] = (unsigned long)_orig.nraddr; \
3281 _argvec[2+1] = (unsigned long)arg1; \
3282 _argvec[2+2] = (unsigned long)arg2; \
3283 _argvec[2+3] = (unsigned long)arg3; \
3284 _argvec[2+4] = (unsigned long)arg4; \
3285 _argvec[2+5] = (unsigned long)arg5; \
3286 _argvec[2+6] = (unsigned long)arg6; \
3287 _argvec[2+7] = (unsigned long)arg7; \
3288 __asm__ volatile( \
3289 "mr 11,%1\n\t" \
3290 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3291 "stw 2,-8(11)\n\t" /* save tocptr */ \
3292 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3293 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3294 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3295 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3296 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3297 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3298 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3299 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3300 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3301 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3302 "mr 11,%1\n\t" \
3303 "mr %0,3\n\t" \
3304 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3305 VG_CONTRACT_FRAME_BY(512) \
3306 : /*out*/ "=r" (_res) \
3307 : /*in*/ "r" (&_argvec[2]) \
3308 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3309 ); \
3310 lval = (__typeof__(lval)) _res; \
3311 } while (0)
3312
3313#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3314 arg7,arg8) \
3315 do { \
3316 volatile OrigFn _orig = (orig); \
3317 volatile unsigned long _argvec[3+8]; \
3318 volatile unsigned long _res; \
3319 /* _argvec[0] holds current r2 across the call */ \
3320 _argvec[1] = (unsigned long)_orig.r2; \
3321 _argvec[2] = (unsigned long)_orig.nraddr; \
3322 _argvec[2+1] = (unsigned long)arg1; \
3323 _argvec[2+2] = (unsigned long)arg2; \
3324 _argvec[2+3] = (unsigned long)arg3; \
3325 _argvec[2+4] = (unsigned long)arg4; \
3326 _argvec[2+5] = (unsigned long)arg5; \
3327 _argvec[2+6] = (unsigned long)arg6; \
3328 _argvec[2+7] = (unsigned long)arg7; \
3329 _argvec[2+8] = (unsigned long)arg8; \
3330 __asm__ volatile( \
3331 "mr 11,%1\n\t" \
3332 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3333 "stw 2,-8(11)\n\t" /* save tocptr */ \
3334 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3335 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3336 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3337 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3338 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3339 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3340 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3341 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3342 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
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_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3357 arg7,arg8,arg9) \
3358 do { \
3359 volatile OrigFn _orig = (orig); \
3360 volatile unsigned long _argvec[3+9]; \
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 _argvec[2+8] = (unsigned long)arg8; \
3373 _argvec[2+9] = (unsigned long)arg9; \
3374 __asm__ volatile( \
3375 "mr 11,%1\n\t" \
3376 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3377 "stw 2,-8(11)\n\t" /* save tocptr */ \
3378 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3379 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3380 /* arg9 */ \
3381 "lwz 3,36(11)\n\t" \
3382 "stw 3,56(1)\n\t" \
3383 /* args1-8 */ \
3384 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3385 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3386 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3387 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3388 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3389 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3390 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3391 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3392 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3393 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3394 "mr 11,%1\n\t" \
3395 "mr %0,3\n\t" \
3396 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3397 VG_CONTRACT_FRAME_BY(64) \
3398 VG_CONTRACT_FRAME_BY(512) \
3399 : /*out*/ "=r" (_res) \
3400 : /*in*/ "r" (&_argvec[2]) \
3401 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3402 ); \
3403 lval = (__typeof__(lval)) _res; \
3404 } while (0)
3405
3406#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3407 arg7,arg8,arg9,arg10) \
3408 do { \
3409 volatile OrigFn _orig = (orig); \
3410 volatile unsigned long _argvec[3+10]; \
3411 volatile unsigned long _res; \
3412 /* _argvec[0] holds current r2 across the call */ \
3413 _argvec[1] = (unsigned long)_orig.r2; \
3414 _argvec[2] = (unsigned long)_orig.nraddr; \
3415 _argvec[2+1] = (unsigned long)arg1; \
3416 _argvec[2+2] = (unsigned long)arg2; \
3417 _argvec[2+3] = (unsigned long)arg3; \
3418 _argvec[2+4] = (unsigned long)arg4; \
3419 _argvec[2+5] = (unsigned long)arg5; \
3420 _argvec[2+6] = (unsigned long)arg6; \
3421 _argvec[2+7] = (unsigned long)arg7; \
3422 _argvec[2+8] = (unsigned long)arg8; \
3423 _argvec[2+9] = (unsigned long)arg9; \
3424 _argvec[2+10] = (unsigned long)arg10; \
3425 __asm__ volatile( \
3426 "mr 11,%1\n\t" \
3427 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3428 "stw 2,-8(11)\n\t" /* save tocptr */ \
3429 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3430 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3431 /* arg10 */ \
3432 "lwz 3,40(11)\n\t" \
3433 "stw 3,60(1)\n\t" \
3434 /* arg9 */ \
3435 "lwz 3,36(11)\n\t" \
3436 "stw 3,56(1)\n\t" \
3437 /* args1-8 */ \
3438 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3439 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3440 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3441 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3442 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3443 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3444 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3445 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3446 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3447 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3448 "mr 11,%1\n\t" \
3449 "mr %0,3\n\t" \
3450 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3451 VG_CONTRACT_FRAME_BY(64) \
3452 VG_CONTRACT_FRAME_BY(512) \
3453 : /*out*/ "=r" (_res) \
3454 : /*in*/ "r" (&_argvec[2]) \
3455 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3456 ); \
3457 lval = (__typeof__(lval)) _res; \
3458 } while (0)
3459
3460#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3461 arg7,arg8,arg9,arg10,arg11) \
3462 do { \
3463 volatile OrigFn _orig = (orig); \
3464 volatile unsigned long _argvec[3+11]; \
3465 volatile unsigned long _res; \
3466 /* _argvec[0] holds current r2 across the call */ \
3467 _argvec[1] = (unsigned long)_orig.r2; \
3468 _argvec[2] = (unsigned long)_orig.nraddr; \
3469 _argvec[2+1] = (unsigned long)arg1; \
3470 _argvec[2+2] = (unsigned long)arg2; \
3471 _argvec[2+3] = (unsigned long)arg3; \
3472 _argvec[2+4] = (unsigned long)arg4; \
3473 _argvec[2+5] = (unsigned long)arg5; \
3474 _argvec[2+6] = (unsigned long)arg6; \
3475 _argvec[2+7] = (unsigned long)arg7; \
3476 _argvec[2+8] = (unsigned long)arg8; \
3477 _argvec[2+9] = (unsigned long)arg9; \
3478 _argvec[2+10] = (unsigned long)arg10; \
3479 _argvec[2+11] = (unsigned long)arg11; \
3480 __asm__ volatile( \
3481 "mr 11,%1\n\t" \
3482 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3483 "stw 2,-8(11)\n\t" /* save tocptr */ \
3484 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3485 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3486 /* arg11 */ \
3487 "lwz 3,44(11)\n\t" \
3488 "stw 3,64(1)\n\t" \
3489 /* arg10 */ \
3490 "lwz 3,40(11)\n\t" \
3491 "stw 3,60(1)\n\t" \
3492 /* arg9 */ \
3493 "lwz 3,36(11)\n\t" \
3494 "stw 3,56(1)\n\t" \
3495 /* args1-8 */ \
3496 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3497 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3498 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3499 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3500 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3501 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3502 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3503 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3504 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3505 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3506 "mr 11,%1\n\t" \
3507 "mr %0,3\n\t" \
3508 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3509 VG_CONTRACT_FRAME_BY(72) \
3510 VG_CONTRACT_FRAME_BY(512) \
3511 : /*out*/ "=r" (_res) \
3512 : /*in*/ "r" (&_argvec[2]) \
3513 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3514 ); \
3515 lval = (__typeof__(lval)) _res; \
3516 } while (0)
3517
3518#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3519 arg7,arg8,arg9,arg10,arg11,arg12) \
3520 do { \
3521 volatile OrigFn _orig = (orig); \
3522 volatile unsigned long _argvec[3+12]; \
3523 volatile unsigned long _res; \
3524 /* _argvec[0] holds current r2 across the call */ \
3525 _argvec[1] = (unsigned long)_orig.r2; \
3526 _argvec[2] = (unsigned long)_orig.nraddr; \
3527 _argvec[2+1] = (unsigned long)arg1; \
3528 _argvec[2+2] = (unsigned long)arg2; \
3529 _argvec[2+3] = (unsigned long)arg3; \
3530 _argvec[2+4] = (unsigned long)arg4; \
3531 _argvec[2+5] = (unsigned long)arg5; \
3532 _argvec[2+6] = (unsigned long)arg6; \
3533 _argvec[2+7] = (unsigned long)arg7; \
3534 _argvec[2+8] = (unsigned long)arg8; \
3535 _argvec[2+9] = (unsigned long)arg9; \
3536 _argvec[2+10] = (unsigned long)arg10; \
3537 _argvec[2+11] = (unsigned long)arg11; \
3538 _argvec[2+12] = (unsigned long)arg12; \
3539 __asm__ volatile( \
3540 "mr 11,%1\n\t" \
3541 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3542 "stw 2,-8(11)\n\t" /* save tocptr */ \
3543 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3544 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3545 /* arg12 */ \
3546 "lwz 3,48(11)\n\t" \
3547 "stw 3,68(1)\n\t" \
3548 /* arg11 */ \
3549 "lwz 3,44(11)\n\t" \
3550 "stw 3,64(1)\n\t" \
3551 /* arg10 */ \
3552 "lwz 3,40(11)\n\t" \
3553 "stw 3,60(1)\n\t" \
3554 /* arg9 */ \
3555 "lwz 3,36(11)\n\t" \
3556 "stw 3,56(1)\n\t" \
3557 /* args1-8 */ \
3558 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3559 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3560 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3561 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3562 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3563 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3564 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3565 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3566 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3567 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3568 "mr 11,%1\n\t" \
3569 "mr %0,3\n\t" \
3570 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3571 VG_CONTRACT_FRAME_BY(72) \
3572 VG_CONTRACT_FRAME_BY(512) \
3573 : /*out*/ "=r" (_res) \
3574 : /*in*/ "r" (&_argvec[2]) \
3575 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3576 ); \
3577 lval = (__typeof__(lval)) _res; \
3578 } while (0)
3579
3580#endif /* PLAT_ppc32_aix5 */
3581
3582/* ------------------------ ppc64-aix5 ------------------------- */
3583
3584#if defined(PLAT_ppc64_aix5)
3585
3586/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3587
3588/* These regs are trashed by the hidden call. */
3589#define __CALLER_SAVED_REGS \
3590 "lr", "ctr", "xer", \
3591 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3592 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3593 "r11", "r12", "r13"
3594
3595/* Expand the stack frame, copying enough info that unwinding
3596 still works. Trashes r3. */
3597
3598#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3599 "addi 1,1,-" #_n_fr "\n\t" \
3600 "ld 3," #_n_fr "(1)\n\t" \
3601 "std 3,0(1)\n\t"
3602
3603#define VG_CONTRACT_FRAME_BY(_n_fr) \
3604 "addi 1,1," #_n_fr "\n\t"
3605
3606/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3607 long) == 8. */
3608
3609#define CALL_FN_W_v(lval, orig) \
3610 do { \
3611 volatile OrigFn _orig = (orig); \
3612 volatile unsigned long _argvec[3+0]; \
3613 volatile unsigned long _res; \
3614 /* _argvec[0] holds current r2 across the call */ \
3615 _argvec[1] = (unsigned long)_orig.r2; \
3616 _argvec[2] = (unsigned long)_orig.nraddr; \
3617 __asm__ volatile( \
3618 "mr 11,%1\n\t" \
3619 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3620 "std 2,-16(11)\n\t" /* save tocptr */ \
3621 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3622 "ld 11, 0(11)\n\t" /* target->r11 */ \
3623 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3624 "mr 11,%1\n\t" \
3625 "mr %0,3\n\t" \
3626 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3627 VG_CONTRACT_FRAME_BY(512) \
3628 : /*out*/ "=r" (_res) \
3629 : /*in*/ "r" (&_argvec[2]) \
3630 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3631 ); \
3632 lval = (__typeof__(lval)) _res; \
3633 } while (0)
3634
3635#define CALL_FN_W_W(lval, orig, arg1) \
3636 do { \
3637 volatile OrigFn _orig = (orig); \
3638 volatile unsigned long _argvec[3+1]; \
3639 volatile unsigned long _res; \
3640 /* _argvec[0] holds current r2 across the call */ \
3641 _argvec[1] = (unsigned long)_orig.r2; \
3642 _argvec[2] = (unsigned long)_orig.nraddr; \
3643 _argvec[2+1] = (unsigned long)arg1; \
3644 __asm__ volatile( \
3645 "mr 11,%1\n\t" \
3646 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3647 "std 2,-16(11)\n\t" /* save tocptr */ \
3648 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3649 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3650 "ld 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 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3655 VG_CONTRACT_FRAME_BY(512) \
3656 : /*out*/ "=r" (_res) \
3657 : /*in*/ "r" (&_argvec[2]) \
3658 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3659 ); \
3660 lval = (__typeof__(lval)) _res; \
3661 } while (0)
3662
3663#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3664 do { \
3665 volatile OrigFn _orig = (orig); \
3666 volatile unsigned long _argvec[3+2]; \
3667 volatile unsigned long _res; \
3668 /* _argvec[0] holds current r2 across the call */ \
3669 _argvec[1] = (unsigned long)_orig.r2; \
3670 _argvec[2] = (unsigned long)_orig.nraddr; \
3671 _argvec[2+1] = (unsigned long)arg1; \
3672 _argvec[2+2] = (unsigned long)arg2; \
3673 __asm__ volatile( \
3674 "mr 11,%1\n\t" \
3675 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3676 "std 2,-16(11)\n\t" /* save tocptr */ \
3677 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3678 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3679 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3680 "ld 11, 0(11)\n\t" /* target->r11 */ \
3681 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3682 "mr 11,%1\n\t" \
3683 "mr %0,3\n\t" \
3684 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3685 VG_CONTRACT_FRAME_BY(512) \
3686 : /*out*/ "=r" (_res) \
3687 : /*in*/ "r" (&_argvec[2]) \
3688 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3689 ); \
3690 lval = (__typeof__(lval)) _res; \
3691 } while (0)
3692
3693#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3694 do { \
3695 volatile OrigFn _orig = (orig); \
3696 volatile unsigned long _argvec[3+3]; \
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 _argvec[2+1] = (unsigned long)arg1; \
3702 _argvec[2+2] = (unsigned long)arg2; \
3703 _argvec[2+3] = (unsigned long)arg3; \
3704 __asm__ volatile( \
3705 "mr 11,%1\n\t" \
3706 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3707 "std 2,-16(11)\n\t" /* save tocptr */ \
3708 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3709 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3710 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3711 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3712 "ld 11, 0(11)\n\t" /* target->r11 */ \
3713 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3714 "mr 11,%1\n\t" \
3715 "mr %0,3\n\t" \
3716 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3717 VG_CONTRACT_FRAME_BY(512) \
3718 : /*out*/ "=r" (_res) \
3719 : /*in*/ "r" (&_argvec[2]) \
3720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3721 ); \
3722 lval = (__typeof__(lval)) _res; \
3723 } while (0)
3724
3725#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3726 do { \
3727 volatile OrigFn _orig = (orig); \
3728 volatile unsigned long _argvec[3+4]; \
3729 volatile unsigned long _res; \
3730 /* _argvec[0] holds current r2 across the call */ \
3731 _argvec[1] = (unsigned long)_orig.r2; \
3732 _argvec[2] = (unsigned long)_orig.nraddr; \
3733 _argvec[2+1] = (unsigned long)arg1; \
3734 _argvec[2+2] = (unsigned long)arg2; \
3735 _argvec[2+3] = (unsigned long)arg3; \
3736 _argvec[2+4] = (unsigned long)arg4; \
3737 __asm__ volatile( \
3738 "mr 11,%1\n\t" \
3739 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3740 "std 2,-16(11)\n\t" /* save tocptr */ \
3741 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3742 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3743 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3744 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3745 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3746 "ld 11, 0(11)\n\t" /* target->r11 */ \
3747 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3748 "mr 11,%1\n\t" \
3749 "mr %0,3\n\t" \
3750 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3751 VG_CONTRACT_FRAME_BY(512) \
3752 : /*out*/ "=r" (_res) \
3753 : /*in*/ "r" (&_argvec[2]) \
3754 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3755 ); \
3756 lval = (__typeof__(lval)) _res; \
3757 } while (0)
3758
3759#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3760 do { \
3761 volatile OrigFn _orig = (orig); \
3762 volatile unsigned long _argvec[3+5]; \
3763 volatile unsigned long _res; \
3764 /* _argvec[0] holds current r2 across the call */ \
3765 _argvec[1] = (unsigned long)_orig.r2; \
3766 _argvec[2] = (unsigned long)_orig.nraddr; \
3767 _argvec[2+1] = (unsigned long)arg1; \
3768 _argvec[2+2] = (unsigned long)arg2; \
3769 _argvec[2+3] = (unsigned long)arg3; \
3770 _argvec[2+4] = (unsigned long)arg4; \
3771 _argvec[2+5] = (unsigned long)arg5; \
3772 __asm__ volatile( \
3773 "mr 11,%1\n\t" \
3774 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3775 "std 2,-16(11)\n\t" /* save tocptr */ \
3776 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3777 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3778 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3779 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3780 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3781 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3782 "ld 11, 0(11)\n\t" /* target->r11 */ \
3783 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3784 "mr 11,%1\n\t" \
3785 "mr %0,3\n\t" \
3786 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3787 VG_CONTRACT_FRAME_BY(512) \
3788 : /*out*/ "=r" (_res) \
3789 : /*in*/ "r" (&_argvec[2]) \
3790 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3791 ); \
3792 lval = (__typeof__(lval)) _res; \
3793 } while (0)
3794
3795#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3796 do { \
3797 volatile OrigFn _orig = (orig); \
3798 volatile unsigned long _argvec[3+6]; \
3799 volatile unsigned long _res; \
3800 /* _argvec[0] holds current r2 across the call */ \
3801 _argvec[1] = (unsigned long)_orig.r2; \
3802 _argvec[2] = (unsigned long)_orig.nraddr; \
3803 _argvec[2+1] = (unsigned long)arg1; \
3804 _argvec[2+2] = (unsigned long)arg2; \
3805 _argvec[2+3] = (unsigned long)arg3; \
3806 _argvec[2+4] = (unsigned long)arg4; \
3807 _argvec[2+5] = (unsigned long)arg5; \
3808 _argvec[2+6] = (unsigned long)arg6; \
3809 __asm__ volatile( \
3810 "mr 11,%1\n\t" \
3811 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3812 "std 2,-16(11)\n\t" /* save tocptr */ \
3813 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3814 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3815 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3816 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3817 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3818 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3819 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3820 "ld 11, 0(11)\n\t" /* target->r11 */ \
3821 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3822 "mr 11,%1\n\t" \
3823 "mr %0,3\n\t" \
3824 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3825 VG_CONTRACT_FRAME_BY(512) \
3826 : /*out*/ "=r" (_res) \
3827 : /*in*/ "r" (&_argvec[2]) \
3828 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3829 ); \
3830 lval = (__typeof__(lval)) _res; \
3831 } while (0)
3832
3833#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3834 arg7) \
3835 do { \
3836 volatile OrigFn _orig = (orig); \
3837 volatile unsigned long _argvec[3+7]; \
3838 volatile unsigned long _res; \
3839 /* _argvec[0] holds current r2 across the call */ \
3840 _argvec[1] = (unsigned long)_orig.r2; \
3841 _argvec[2] = (unsigned long)_orig.nraddr; \
3842 _argvec[2+1] = (unsigned long)arg1; \
3843 _argvec[2+2] = (unsigned long)arg2; \
3844 _argvec[2+3] = (unsigned long)arg3; \
3845 _argvec[2+4] = (unsigned long)arg4; \
3846 _argvec[2+5] = (unsigned long)arg5; \
3847 _argvec[2+6] = (unsigned long)arg6; \
3848 _argvec[2+7] = (unsigned long)arg7; \
3849 __asm__ volatile( \
3850 "mr 11,%1\n\t" \
3851 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3852 "std 2,-16(11)\n\t" /* save tocptr */ \
3853 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3854 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3855 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3856 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3857 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3858 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3859 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3860 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3861 "ld 11, 0(11)\n\t" /* target->r11 */ \
3862 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3863 "mr 11,%1\n\t" \
3864 "mr %0,3\n\t" \
3865 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3866 VG_CONTRACT_FRAME_BY(512) \
3867 : /*out*/ "=r" (_res) \
3868 : /*in*/ "r" (&_argvec[2]) \
3869 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3870 ); \
3871 lval = (__typeof__(lval)) _res; \
3872 } while (0)
3873
3874#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3875 arg7,arg8) \
3876 do { \
3877 volatile OrigFn _orig = (orig); \
3878 volatile unsigned long _argvec[3+8]; \
3879 volatile unsigned long _res; \
3880 /* _argvec[0] holds current r2 across the call */ \
3881 _argvec[1] = (unsigned long)_orig.r2; \
3882 _argvec[2] = (unsigned long)_orig.nraddr; \
3883 _argvec[2+1] = (unsigned long)arg1; \
3884 _argvec[2+2] = (unsigned long)arg2; \
3885 _argvec[2+3] = (unsigned long)arg3; \
3886 _argvec[2+4] = (unsigned long)arg4; \
3887 _argvec[2+5] = (unsigned long)arg5; \
3888 _argvec[2+6] = (unsigned long)arg6; \
3889 _argvec[2+7] = (unsigned long)arg7; \
3890 _argvec[2+8] = (unsigned long)arg8; \
3891 __asm__ volatile( \
3892 "mr 11,%1\n\t" \
3893 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3894 "std 2,-16(11)\n\t" /* save tocptr */ \
3895 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3896 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3897 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3898 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3899 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3900 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3901 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3902 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3903 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
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_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3918 arg7,arg8,arg9) \
3919 do { \
3920 volatile OrigFn _orig = (orig); \
3921 volatile unsigned long _argvec[3+9]; \
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 _argvec[2+8] = (unsigned long)arg8; \
3934 _argvec[2+9] = (unsigned long)arg9; \
3935 __asm__ volatile( \
3936 "mr 11,%1\n\t" \
3937 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3938 "std 2,-16(11)\n\t" /* save tocptr */ \
3939 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3940 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3941 /* arg9 */ \
3942 "ld 3,72(11)\n\t" \
3943 "std 3,112(1)\n\t" \
3944 /* args1-8 */ \
3945 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3946 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3947 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3948 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3949 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3950 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3951 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3952 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3953 "ld 11, 0(11)\n\t" /* target->r11 */ \
3954 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3955 "mr 11,%1\n\t" \
3956 "mr %0,3\n\t" \
3957 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3958 VG_CONTRACT_FRAME_BY(128) \
3959 VG_CONTRACT_FRAME_BY(512) \
3960 : /*out*/ "=r" (_res) \
3961 : /*in*/ "r" (&_argvec[2]) \
3962 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3963 ); \
3964 lval = (__typeof__(lval)) _res; \
3965 } while (0)
3966
3967#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3968 arg7,arg8,arg9,arg10) \
3969 do { \
3970 volatile OrigFn _orig = (orig); \
3971 volatile unsigned long _argvec[3+10]; \
3972 volatile unsigned long _res; \
3973 /* _argvec[0] holds current r2 across the call */ \
3974 _argvec[1] = (unsigned long)_orig.r2; \
3975 _argvec[2] = (unsigned long)_orig.nraddr; \
3976 _argvec[2+1] = (unsigned long)arg1; \
3977 _argvec[2+2] = (unsigned long)arg2; \
3978 _argvec[2+3] = (unsigned long)arg3; \
3979 _argvec[2+4] = (unsigned long)arg4; \
3980 _argvec[2+5] = (unsigned long)arg5; \
3981 _argvec[2+6] = (unsigned long)arg6; \
3982 _argvec[2+7] = (unsigned long)arg7; \
3983 _argvec[2+8] = (unsigned long)arg8; \
3984 _argvec[2+9] = (unsigned long)arg9; \
3985 _argvec[2+10] = (unsigned long)arg10; \
3986 __asm__ volatile( \
3987 "mr 11,%1\n\t" \
3988 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3989 "std 2,-16(11)\n\t" /* save tocptr */ \
3990 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3991 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3992 /* arg10 */ \
3993 "ld 3,80(11)\n\t" \
3994 "std 3,120(1)\n\t" \
3995 /* arg9 */ \
3996 "ld 3,72(11)\n\t" \
3997 "std 3,112(1)\n\t" \
3998 /* args1-8 */ \
3999 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4000 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4001 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4002 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4003 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4004 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4005 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4006 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4007 "ld 11, 0(11)\n\t" /* target->r11 */ \
4008 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4009 "mr 11,%1\n\t" \
4010 "mr %0,3\n\t" \
4011 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4012 VG_CONTRACT_FRAME_BY(128) \
4013 VG_CONTRACT_FRAME_BY(512) \
4014 : /*out*/ "=r" (_res) \
4015 : /*in*/ "r" (&_argvec[2]) \
4016 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4017 ); \
4018 lval = (__typeof__(lval)) _res; \
4019 } while (0)
4020
4021#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4022 arg7,arg8,arg9,arg10,arg11) \
4023 do { \
4024 volatile OrigFn _orig = (orig); \
4025 volatile unsigned long _argvec[3+11]; \
4026 volatile unsigned long _res; \
4027 /* _argvec[0] holds current r2 across the call */ \
4028 _argvec[1] = (unsigned long)_orig.r2; \
4029 _argvec[2] = (unsigned long)_orig.nraddr; \
4030 _argvec[2+1] = (unsigned long)arg1; \
4031 _argvec[2+2] = (unsigned long)arg2; \
4032 _argvec[2+3] = (unsigned long)arg3; \
4033 _argvec[2+4] = (unsigned long)arg4; \
4034 _argvec[2+5] = (unsigned long)arg5; \
4035 _argvec[2+6] = (unsigned long)arg6; \
4036 _argvec[2+7] = (unsigned long)arg7; \
4037 _argvec[2+8] = (unsigned long)arg8; \
4038 _argvec[2+9] = (unsigned long)arg9; \
4039 _argvec[2+10] = (unsigned long)arg10; \
4040 _argvec[2+11] = (unsigned long)arg11; \
4041 __asm__ volatile( \
4042 "mr 11,%1\n\t" \
4043 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4044 "std 2,-16(11)\n\t" /* save tocptr */ \
4045 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4046 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4047 /* arg11 */ \
4048 "ld 3,88(11)\n\t" \
4049 "std 3,128(1)\n\t" \
4050 /* arg10 */ \
4051 "ld 3,80(11)\n\t" \
4052 "std 3,120(1)\n\t" \
4053 /* arg9 */ \
4054 "ld 3,72(11)\n\t" \
4055 "std 3,112(1)\n\t" \
4056 /* args1-8 */ \
4057 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4058 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4059 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4060 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4061 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4062 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4063 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4064 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4065 "ld 11, 0(11)\n\t" /* target->r11 */ \
4066 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4067 "mr 11,%1\n\t" \
4068 "mr %0,3\n\t" \
4069 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4070 VG_CONTRACT_FRAME_BY(144) \
4071 VG_CONTRACT_FRAME_BY(512) \
4072 : /*out*/ "=r" (_res) \
4073 : /*in*/ "r" (&_argvec[2]) \
4074 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4075 ); \
4076 lval = (__typeof__(lval)) _res; \
4077 } while (0)
4078
4079#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4080 arg7,arg8,arg9,arg10,arg11,arg12) \
4081 do { \
4082 volatile OrigFn _orig = (orig); \
4083 volatile unsigned long _argvec[3+12]; \
4084 volatile unsigned long _res; \
4085 /* _argvec[0] holds current r2 across the call */ \
4086 _argvec[1] = (unsigned long)_orig.r2; \
4087 _argvec[2] = (unsigned long)_orig.nraddr; \
4088 _argvec[2+1] = (unsigned long)arg1; \
4089 _argvec[2+2] = (unsigned long)arg2; \
4090 _argvec[2+3] = (unsigned long)arg3; \
4091 _argvec[2+4] = (unsigned long)arg4; \
4092 _argvec[2+5] = (unsigned long)arg5; \
4093 _argvec[2+6] = (unsigned long)arg6; \
4094 _argvec[2+7] = (unsigned long)arg7; \
4095 _argvec[2+8] = (unsigned long)arg8; \
4096 _argvec[2+9] = (unsigned long)arg9; \
4097 _argvec[2+10] = (unsigned long)arg10; \
4098 _argvec[2+11] = (unsigned long)arg11; \
4099 _argvec[2+12] = (unsigned long)arg12; \
4100 __asm__ volatile( \
4101 "mr 11,%1\n\t" \
4102 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4103 "std 2,-16(11)\n\t" /* save tocptr */ \
4104 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4105 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4106 /* arg12 */ \
4107 "ld 3,96(11)\n\t" \
4108 "std 3,136(1)\n\t" \
4109 /* arg11 */ \
4110 "ld 3,88(11)\n\t" \
4111 "std 3,128(1)\n\t" \
4112 /* arg10 */ \
4113 "ld 3,80(11)\n\t" \
4114 "std 3,120(1)\n\t" \
4115 /* arg9 */ \
4116 "ld 3,72(11)\n\t" \
4117 "std 3,112(1)\n\t" \
4118 /* args1-8 */ \
4119 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4120 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4121 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4122 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4123 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4124 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4125 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4126 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4127 "ld 11, 0(11)\n\t" /* target->r11 */ \
4128 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4129 "mr 11,%1\n\t" \
4130 "mr %0,3\n\t" \
4131 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4132 VG_CONTRACT_FRAME_BY(144) \
4133 VG_CONTRACT_FRAME_BY(512) \
4134 : /*out*/ "=r" (_res) \
4135 : /*in*/ "r" (&_argvec[2]) \
4136 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4137 ); \
4138 lval = (__typeof__(lval)) _res; \
4139 } while (0)
4140
4141#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00004142
sewardj0ec07f32006-01-12 12:32:32 +00004143
4144/* ------------------------------------------------------------------ */
4145/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4146/* */
njn30d76c62005-06-18 15:07:39 +00004147/* ------------------------------------------------------------------ */
4148
sewardj2e93c502002-04-12 11:12:52 +00004149/* Some request codes. There are many more of these, but most are not
4150 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004151 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004152
sewardj0ec07f32006-01-12 12:32:32 +00004153 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4154 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004155*/
4156
sewardj0ec07f32006-01-12 12:32:32 +00004157/* These macros are used by tools -- they must be public, but don't
4158 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004159#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004160 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004161#define VG_IS_TOOL_USERREQ(a, b, v) \
4162 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004163
sewardj5ce4b152006-03-11 12:57:41 +00004164/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4165 This enum comprises an ABI exported by Valgrind to programs
4166 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4167 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004168typedef
njn4c791212003-05-02 17:53:54 +00004169 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4170 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004171
sewardj0ec07f32006-01-12 12:32:32 +00004172 /* These allow any function to be called from the simulated
4173 CPU but run on the real CPU. Nb: the first arg passed to
4174 the function is always the ThreadId of the running
4175 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004176 function, etc. */
njn4c791212003-05-02 17:53:54 +00004177 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4178 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4179 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4180 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004181
sewardj0ec07f32006-01-12 12:32:32 +00004182 /* Can be useful in regression testing suites -- eg. can
4183 send Valgrind's output to /dev/null and still count
4184 errors. */
njn4c791212003-05-02 17:53:54 +00004185 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004186
sewardj0ec07f32006-01-12 12:32:32 +00004187 /* These are useful and can be interpreted by any tool that
4188 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004189 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4190 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004191 /* Memory pool support. */
4192 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4193 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4194 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4195 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004196 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004197 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4198 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4199 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004200
fitzhardinge39de4b42003-10-31 07:12:21 +00004201 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00004202 /* The first two pass the va_list argument by value, which
4203 assumes it is the same size as or smaller than a UWord,
4204 which generally isn't the case. Hence are deprecated.
4205 The second two pass the vargs by reference and so are
4206 immune to this problem. */
4207 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00004208 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004209 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00004210 /* both :: char* fmt, va_list* vargs */
4211 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4212 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00004213
4214 /* Stack support. */
4215 VG_USERREQ__STACK_REGISTER = 0x1501,
4216 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004217 VG_USERREQ__STACK_CHANGE = 0x1503,
4218
4219 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00004220 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
4221
4222 /* Querying of debug info. */
4223 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701
njn25e49d8e72002-09-23 09:36:25 +00004224 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004225
sewardj0ec07f32006-01-12 12:32:32 +00004226#if !defined(__GNUC__)
4227# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004228#endif
sewardj2e93c502002-04-12 11:12:52 +00004229
bartfa5115a2010-09-02 09:33:02 +00004230
4231/*
4232 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
4233 * client request and whose value equals the client request result.
4234 */
4235
4236#if defined(NVALGRIND)
4237
4238#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4239 _zzq_default, _zzq_request, \
4240 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4241 (_zzq_default)
4242
4243#else /*defined(NVALGRIND)*/
4244
4245#if defined(_MSC_VER)
4246
4247#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4248 _zzq_default, _zzq_request, \
4249 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4250 (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \
4251 (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \
4252 (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \
4253 (uintptr_t)(_zzq_arg5)))
4254
4255static __inline unsigned
4256vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default,
4257 unsigned _zzq_request, uintptr_t _zzq_arg1,
4258 uintptr_t _zzq_arg2, uintptr_t _zzq_arg3,
4259 uintptr_t _zzq_arg4, uintptr_t _zzq_arg5)
4260{
4261 unsigned _zzq_rlval;
4262 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request,
4263 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5);
4264 return _zzq_rlval;
4265}
4266
4267#else /*defined(_MSC_VER)*/
4268
4269#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4270 _zzq_default, _zzq_request, \
4271 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4272 (__extension__({unsigned int _zzq_rlval; \
4273 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \
4274 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4275 _zzq_rlval; \
4276 }))
4277
4278#endif /*defined(_MSC_VER)*/
4279
4280#endif /*defined(NVALGRIND)*/
4281
4282
sewardj0ec07f32006-01-12 12:32:32 +00004283/* Returns the number of Valgrinds this code is running under. That
4284 is, 0 if running natively, 1 if running under Valgrind, 2 if
4285 running under Valgrind which is running under another Valgrind,
4286 etc. */
bartfa5115a2010-09-02 09:33:02 +00004287#define RUNNING_ON_VALGRIND \
4288 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
4289 VG_USERREQ__RUNNING_ON_VALGRIND, \
4290 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00004291
4292
sewardj18d75132002-05-16 11:06:21 +00004293/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4294 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4295 since it provides a way to make sure valgrind will retranslate the
4296 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00004297#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4298 {unsigned int _qzz_res; \
4299 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4300 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00004301 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00004302 }
4303
njn26aba4d2005-05-16 13:31:23 +00004304
sewardj0ec07f32006-01-12 12:32:32 +00004305/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004306 Possibly with a backtrace. This is a really ugly hack. The return value
4307 is the number of characters printed, excluding the "**<pid>** " part at the
4308 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004309
4310#if defined(NVALGRIND)
4311
4312# define VALGRIND_PRINTF(...)
4313# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00004314
4315#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004316
bart7f489812010-08-27 10:05:27 +00004317#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004318/* Modern GCC will optimize the static routine out if unused,
4319 and unused attribute will shut down warnings about it. */
4320static int VALGRIND_PRINTF(const char *format, ...)
4321 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004322#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004323static int
bart0da2c772010-09-01 10:18:36 +00004324#if defined(_MSC_VER)
4325__inline
4326#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004327VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004328{
njnc6168192004-11-29 13:54:10 +00004329 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004330 va_list vargs;
4331 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004332#if defined(_MSC_VER)
4333 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4334 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004335 (uintptr_t)format,
4336 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004337 0, 0, 0);
4338#else
sewardjc560fb32010-01-28 15:23:54 +00004339 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4340 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004341 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004342 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004343 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004344#endif
sewardjc560fb32010-01-28 15:23:54 +00004345 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004346 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004347}
4348
bart7f489812010-08-27 10:05:27 +00004349#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004350static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4351 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004352#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004353static int
bart0da2c772010-09-01 10:18:36 +00004354#if defined(_MSC_VER)
4355__inline
4356#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004357VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004358{
njnc6168192004-11-29 13:54:10 +00004359 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004360 va_list vargs;
4361 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004362#if defined(_MSC_VER)
4363 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4364 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004365 (uintptr_t)format,
4366 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004367 0, 0, 0);
4368#else
sewardjc560fb32010-01-28 15:23:54 +00004369 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4370 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004371 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004372 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004373 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004374#endif
sewardjc560fb32010-01-28 15:23:54 +00004375 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004376 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004377}
4378
fitzhardinge39de4b42003-10-31 07:12:21 +00004379#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00004380
sewardj0ec07f32006-01-12 12:32:32 +00004381
njn3e884182003-04-15 13:03:23 +00004382/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004383 real CPU, calling an arbitary function.
4384
4385 Note that the current ThreadId is inserted as the first argument.
4386 So this call:
4387
4388 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4389
4390 requires f to have this signature:
4391
4392 Word f(Word tid, Word arg1, Word arg2)
4393
4394 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004395
4396 Note that these client requests are not entirely reliable. For example,
4397 if you call a function with them that subsequently calls printf(),
4398 there's a high chance Valgrind will crash. Generally, your prospects of
4399 these working are made higher if the called function does not refer to
4400 any global variables, and does not refer to any libc or other functions
4401 (printf et al). Any kind of entanglement with libc or dynamic linking is
4402 likely to have a bad outcome, for tricky reasons which we've grappled
4403 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004404*/
sewardj0ec07f32006-01-12 12:32:32 +00004405#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00004406 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004407 ({unsigned long _qyy_res; \
4408 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4409 VG_USERREQ__CLIENT_CALL0, \
4410 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004411 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004412 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004413 })
4414
sewardj0ec07f32006-01-12 12:32:32 +00004415#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00004416 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004417 ({unsigned long _qyy_res; \
4418 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4419 VG_USERREQ__CLIENT_CALL1, \
4420 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004421 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004422 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004423 })
4424
sewardj0ec07f32006-01-12 12:32:32 +00004425#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00004426 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004427 ({unsigned long _qyy_res; \
4428 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4429 VG_USERREQ__CLIENT_CALL2, \
4430 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004431 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004432 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004433 })
4434
sewardj0ec07f32006-01-12 12:32:32 +00004435#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00004436 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004437 ({unsigned long _qyy_res; \
4438 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4439 VG_USERREQ__CLIENT_CALL3, \
4440 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004441 _qyy_arg1, _qyy_arg2, \
4442 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004443 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004444 })
4445
4446
nethercote7cc9c232004-01-21 15:08:04 +00004447/* Counts the number of errors that have been recorded by a tool. Nb:
4448 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004449 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004450#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00004451 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004452 ({unsigned int _qyy_res; \
4453 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4454 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00004455 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004456 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00004457 })
4458
njn3ac96952009-07-09 23:35:44 +00004459/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4460 when heap blocks are allocated in order to give accurate results. This
4461 happens automatically for the standard allocator functions such as
4462 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4463 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004464
njn3ac96952009-07-09 23:35:44 +00004465 But if your program uses a custom allocator, this doesn't automatically
4466 happen, and Valgrind will not do as well. For example, if you allocate
4467 superblocks with mmap() and then allocates chunks of the superblocks, all
4468 Valgrind's observations will be at the mmap() level and it won't know that
4469 the chunks should be considered separate entities. In Memcheck's case,
4470 that means you probably won't get heap block overrun detection (because
4471 there won't be redzones marked as unaddressable) and you definitely won't
4472 get any leak detection.
4473
4474 The following client requests allow a custom allocator to be annotated so
4475 that it can be handled accurately by Valgrind.
4476
4477 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4478 by a malloc()-like function. For Memcheck (an illustrative case), this
4479 does two things:
4480
4481 - It records that the block has been allocated. This means any addresses
4482 within the block mentioned in error messages will be
4483 identified as belonging to the block. It also means that if the block
4484 isn't freed it will be detected by the leak checker.
4485
4486 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4487 not set), or addressable and defined (if 'is_zeroed' is set). This
4488 controls how accesses to the block by the program are handled.
4489
4490 'addr' is the start of the usable block (ie. after any
4491 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4492 can apply redzones -- these are blocks of padding at the start and end of
4493 each block. Adding redzones is recommended as it makes it much more likely
4494 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4495 zeroed (or filled with another predictable value), as is the case for
4496 calloc().
4497
4498 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4499 heap block -- that will be used by the client program -- is allocated.
4500 It's best to put it at the outermost level of the allocator if possible;
4501 for example, if you have a function my_alloc() which calls
4502 internal_alloc(), and the client request is put inside internal_alloc(),
4503 stack traces relating to the heap block will contain entries for both
4504 my_alloc() and internal_alloc(), which is probably not what you want.
4505
njnb965efb2009-08-10 07:36:54 +00004506 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4507 custom blocks from within a heap block, B, that has been allocated with
4508 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4509 -- the custom blocks will take precedence.
4510
njn3ac96952009-07-09 23:35:44 +00004511 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4512 Memcheck, it does two things:
4513
4514 - It records that the block has been deallocated. This assumes that the
4515 block was annotated as having been allocated via
4516 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4517
4518 - It marks the block as being unaddressable.
4519
4520 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4521 heap block is deallocated.
4522
4523 In many cases, these two client requests will not be enough to get your
4524 allocator working well with Memcheck. More specifically, if your allocator
4525 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4526 will be necessary to mark the memory as addressable just before the zeroing
4527 occurs, otherwise you'll get a lot of invalid write errors. For example,
4528 you'll need to do this if your allocator recycles freed blocks, but it
4529 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4530 Alternatively, if your allocator reuses freed blocks for allocator-internal
4531 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4532
4533 Really, what's happening is a blurring of the lines between the client
4534 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4535 memory should be considered unaddressable to the client program, but the
4536 allocator knows more than the rest of the client program and so may be able
4537 to safely access it. Extra client requests are necessary for Valgrind to
4538 understand the distinction between the allocator and the rest of the
4539 program.
4540
4541 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4542 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4543
njn32f8d8c2009-07-15 02:31:45 +00004544 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004545*/
sewardj0ec07f32006-01-12 12:32:32 +00004546#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4547 {unsigned int _qzz_res; \
4548 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4549 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004550 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00004551 }
4552
njn32f8d8c2009-07-15 02:31:45 +00004553/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4554 Ignored if addr == 0.
4555*/
sewardj0ec07f32006-01-12 12:32:32 +00004556#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4557 {unsigned int _qzz_res; \
4558 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4559 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004560 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00004561 }
4562
rjwalshbc0bb832004-06-19 18:12:36 +00004563/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004564#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4565 {unsigned int _qzz_res; \
4566 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4567 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004568 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004569 }
4570
4571/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004572#define VALGRIND_DESTROY_MEMPOOL(pool) \
4573 {unsigned int _qzz_res; \
4574 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4575 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004576 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004577 }
4578
4579/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004580#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4581 {unsigned int _qzz_res; \
4582 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4583 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00004584 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004585 }
4586
4587/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004588#define VALGRIND_MEMPOOL_FREE(pool, addr) \
4589 {unsigned int _qzz_res; \
4590 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4591 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00004592 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004593 }
4594
sewardj2c1c9df2006-07-28 00:06:37 +00004595/* Disassociate any pieces outside a particular range. */
4596#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4597 {unsigned int _qzz_res; \
4598 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4599 VG_USERREQ__MEMPOOL_TRIM, \
4600 pool, addr, size, 0, 0); \
4601 }
4602
sewardjc740d762006-10-05 17:59:23 +00004603/* Resize and/or move a piece associated with a memory pool. */
4604#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4605 {unsigned int _qzz_res; \
4606 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4607 VG_USERREQ__MOVE_MEMPOOL, \
4608 poolA, poolB, 0, 0, 0); \
4609 }
4610
4611/* Resize and/or move a piece associated with a memory pool. */
4612#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4613 {unsigned int _qzz_res; \
4614 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4615 VG_USERREQ__MEMPOOL_CHANGE, \
4616 pool, addrA, addrB, size, 0); \
4617 }
4618
4619/* Return 1 if a mempool exists, else 0. */
4620#define VALGRIND_MEMPOOL_EXISTS(pool) \
njn44862972009-02-23 02:08:24 +00004621 __extension__ \
sewardjc740d762006-10-05 17:59:23 +00004622 ({unsigned int _qzz_res; \
4623 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4624 VG_USERREQ__MEMPOOL_EXISTS, \
4625 pool, 0, 0, 0, 0); \
4626 _qzz_res; \
4627 })
4628
rjwalsh0140af52005-06-04 20:42:33 +00004629/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004630#define VALGRIND_STACK_REGISTER(start, end) \
njn44862972009-02-23 02:08:24 +00004631 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004632 ({unsigned int _qzz_res; \
4633 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4634 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004635 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004636 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00004637 })
4638
4639/* Unmark the piece of memory associated with a stack id as being a
4640 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004641#define VALGRIND_STACK_DEREGISTER(id) \
4642 {unsigned int _qzz_res; \
4643 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4644 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004645 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004646 }
4647
4648/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004649#define VALGRIND_STACK_CHANGE(id, start, end) \
4650 {unsigned int _qzz_res; \
4651 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4652 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00004653 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004654 }
4655
sewardjc8259b82009-04-22 22:42:10 +00004656/* Load PDB debug info for Wine PE image_map. */
4657#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4658 {unsigned int _qzz_res; \
4659 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4660 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4661 fd, ptr, total_size, delta, 0); \
4662 }
4663
sewardj5c659622010-08-20 18:22:07 +00004664/* Map a code address to a source file name and line number. buf64
4665 must point to a 64-byte buffer in the caller's address space. The
4666 result will be dumped in there and is guaranteed to be zero
4667 terminated. If no info is found, the first byte is set to zero. */
4668#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
4669 {unsigned int _qzz_res; \
4670 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4671 VG_USERREQ__MAP_IP_TO_SRCLOC, \
4672 addr, buf64, 0, 0, 0); \
4673 }
4674
sewardj0ec07f32006-01-12 12:32:32 +00004675
sewardjf5c1a7f2006-10-17 01:32:48 +00004676#undef PLAT_x86_linux
4677#undef PLAT_amd64_linux
4678#undef PLAT_ppc32_linux
4679#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004680#undef PLAT_arm_linux
sewardjf5c1a7f2006-10-17 01:32:48 +00004681#undef PLAT_ppc32_aix5
4682#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00004683
njn3e884182003-04-15 13:03:23 +00004684#endif /* __VALGRIND_H */