blob: 10ca6b8b6551741b1505d5177fa64db8dd109eb2 [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_x86_darwin
112#undef PLAT_amd64_darwin
bart7f489812010-08-27 10:05:27 +0000113#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +0000114#undef PLAT_x86_linux
115#undef PLAT_amd64_linux
116#undef PLAT_ppc32_linux
117#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000118#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +0000119#undef PLAT_s390x_linux
120
sewardj0ec07f32006-01-12 12:32:32 +0000121
sewardj6e9de462011-06-28 07:25:29 +0000122#if defined(__APPLE__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000123# define PLAT_x86_darwin 1
124#elif defined(__APPLE__) && defined(__x86_64__)
125# define PLAT_amd64_darwin 1
sewardj6e9de462011-06-28 07:25:29 +0000126#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
127 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000128# define PLAT_x86_win32 1
sewardj59570ff2010-01-01 11:59:33 +0000129#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000130# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000131#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000132# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000133#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000134# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000135#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000136# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000137#elif defined(__linux__) && defined(__arm__)
138# define PLAT_arm_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000139#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
140# define PLAT_s390x_linux 1
njnf76d27a2009-05-28 01:53:07 +0000141#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000142/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000143 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000144# if !defined(NVALGRIND)
145# define NVALGRIND 1
146# endif
147#endif
148
149
njn30d76c62005-06-18 15:07:39 +0000150/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000151/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
152/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000153/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000154
bart575ce8e2011-05-15 07:04:03 +0000155/*
156 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
157 * request. Accepts both pointers and integers as arguments.
158 *
159 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
160 * client request and whose value equals the client request result. Accepts
161 * both pointers and integers as arguments.
162 */
163
164#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
165 _zzq_request, _zzq_arg1, _zzq_arg2, \
166 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000167 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000168 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000169 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000170
sewardj0ec07f32006-01-12 12:32:32 +0000171#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000172
173/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000174 from the compiled code (analogous to NDEBUG's effects on
175 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000176#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
177 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000178 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000179 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000180
sewardj0ec07f32006-01-12 12:32:32 +0000181#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000182
sewardj0ec07f32006-01-12 12:32:32 +0000183/* The following defines the magic code sequences which the JITter
184 spots and handles magically. Don't look too closely at them as
185 they will rot your brain.
186
187 The assembly code sequences for all architectures is in this one
188 file. This is because this file must be stand-alone, and we don't
189 want to have multiple files.
190
191 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
192 value gets put in the return slot, so that everything works when
193 this is executed not under Valgrind. Args are passed in a memory
194 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000195 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000196
nethercote54265442004-10-26 12:56:58 +0000197 The macro args are:
198 _zzq_rlval result lvalue
199 _zzq_default default value (result returned when running on real CPU)
200 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000201 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000202
sewardj0ec07f32006-01-12 12:32:32 +0000203 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000204 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
205 guest's NRADDR pseudo-register and whatever other information is
206 needed to safely run the call original from the wrapper: on
207 ppc64-linux, the R2 value at the divert point is also needed. This
208 information is abstracted into a user-visible type, OrigFn.
209
210 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
211 guest, but guarantees that the branch instruction will not be
212 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
213 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
214 complete inline asm, since it needs to be combined with more magic
215 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000216*/
217
njnf76d27a2009-05-28 01:53:07 +0000218/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000219
sewardj520a03a2010-10-07 10:46:15 +0000220#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000221 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000222
223typedef
224 struct {
225 unsigned int nraddr; /* where's the code? */
226 }
227 OrigFn;
228
sewardj0ec07f32006-01-12 12:32:32 +0000229#define __SPECIAL_INSTRUCTION_PREAMBLE \
230 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000231 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000232
bart575ce8e2011-05-15 07:04:03 +0000233#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
234 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000235 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000236 __extension__ \
237 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000238 volatile unsigned int _zzq_result; \
239 _zzq_args[0] = (unsigned int)(_zzq_request); \
240 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
241 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
242 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
243 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000244 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000245 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
246 /* %EDX = client_request ( %EAX ) */ \
247 "xchgl %%ebx,%%ebx" \
248 : "=d" (_zzq_result) \
249 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
250 : "cc", "memory" \
251 ); \
bart575ce8e2011-05-15 07:04:03 +0000252 _zzq_result; \
253 })
sewardj2c48c7b2005-11-29 13:05:56 +0000254
sewardjc8858442006-01-20 15:17:20 +0000255#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
256 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
257 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000258 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
259 /* %EAX = guest_NRADDR */ \
260 "xchgl %%ecx,%%ecx" \
261 : "=a" (__addr) \
262 : \
263 : "cc", "memory" \
264 ); \
sewardjc8858442006-01-20 15:17:20 +0000265 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000266 }
sewardj0ec07f32006-01-12 12:32:32 +0000267
268#define VALGRIND_CALL_NOREDIR_EAX \
269 __SPECIAL_INSTRUCTION_PREAMBLE \
270 /* call-noredir *%EAX */ \
271 "xchgl %%edx,%%edx\n\t"
sewardj60227842010-10-07 10:00:56 +0000272#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000273
274/* ------------------------- x86-Win32 ------------------------- */
275
276#if defined(PLAT_x86_win32) && !defined(__GNUC__)
277
278typedef
279 struct {
280 unsigned int nraddr; /* where's the code? */
281 }
282 OrigFn;
283
284#if defined(_MSC_VER)
285
286#define __SPECIAL_INSTRUCTION_PREAMBLE \
287 __asm rol edi, 3 __asm rol edi, 13 \
288 __asm rol edi, 29 __asm rol edi, 19
289
bart575ce8e2011-05-15 07:04:03 +0000290#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
291 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000292 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000293 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
294 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
295 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
296 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
297
298static __inline uintptr_t
299valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
300 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
301 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
302 uintptr_t _zzq_arg5)
303{
304 volatile uintptr_t _zzq_args[6];
305 volatile unsigned int _zzq_result;
306 _zzq_args[0] = (uintptr_t)(_zzq_request);
307 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
308 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
309 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
310 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
311 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
312 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
313 __SPECIAL_INSTRUCTION_PREAMBLE
314 /* %EDX = client_request ( %EAX ) */
315 __asm xchg ebx,ebx
316 __asm mov _zzq_result, edx
317 }
318 return _zzq_result;
319}
bart7f489812010-08-27 10:05:27 +0000320
321#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
322 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
323 volatile unsigned int __addr; \
324 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
325 /* %EAX = guest_NRADDR */ \
326 __asm xchg ecx,ecx \
327 __asm mov __addr, eax \
328 } \
329 _zzq_orig->nraddr = __addr; \
330 }
331
332#define VALGRIND_CALL_NOREDIR_EAX ERROR
333
334#else
335#error Unsupported compiler.
336#endif
337
338#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000339
njnf76d27a2009-05-28 01:53:07 +0000340/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000341
njnf76d27a2009-05-28 01:53:07 +0000342#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000343
344typedef
345 struct {
346 unsigned long long int nraddr; /* where's the code? */
347 }
348 OrigFn;
349
sewardj0ec07f32006-01-12 12:32:32 +0000350#define __SPECIAL_INSTRUCTION_PREAMBLE \
351 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000352 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000353
bart575ce8e2011-05-15 07:04:03 +0000354#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
355 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000356 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000357 __extension__ \
358 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000359 volatile unsigned long long int _zzq_result; \
360 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
361 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
362 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
363 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
364 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000365 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000366 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
367 /* %RDX = client_request ( %RAX ) */ \
368 "xchgq %%rbx,%%rbx" \
369 : "=d" (_zzq_result) \
370 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
371 : "cc", "memory" \
372 ); \
bart575ce8e2011-05-15 07:04:03 +0000373 _zzq_result; \
374 })
sewardj0ec07f32006-01-12 12:32:32 +0000375
sewardjc8858442006-01-20 15:17:20 +0000376#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
377 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
378 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000379 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
380 /* %RAX = guest_NRADDR */ \
381 "xchgq %%rcx,%%rcx" \
382 : "=a" (__addr) \
383 : \
384 : "cc", "memory" \
385 ); \
sewardjc8858442006-01-20 15:17:20 +0000386 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000387 }
388
389#define VALGRIND_CALL_NOREDIR_RAX \
390 __SPECIAL_INSTRUCTION_PREAMBLE \
391 /* call-noredir *%RAX */ \
392 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000393#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000394
sewardjf5c1a7f2006-10-17 01:32:48 +0000395/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000396
sewardjf5c1a7f2006-10-17 01:32:48 +0000397#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000398
399typedef
400 struct {
sewardjc8858442006-01-20 15:17:20 +0000401 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000402 }
403 OrigFn;
404
sewardj0ec07f32006-01-12 12:32:32 +0000405#define __SPECIAL_INSTRUCTION_PREAMBLE \
406 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000407 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000408
bart575ce8e2011-05-15 07:04:03 +0000409#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
410 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000411 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000412 \
bart575ce8e2011-05-15 07:04:03 +0000413 __extension__ \
414 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000415 unsigned int _zzq_result; \
416 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000417 _zzq_args[0] = (unsigned int)(_zzq_request); \
418 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
419 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
420 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
421 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000422 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000423 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000424 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
425 "mr 4,%2\n\t" /*ptr*/ \
426 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000427 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000428 "or 1,1,1\n\t" \
429 "mr %0,3" /*result*/ \
430 : "=b" (_zzq_result) \
431 : "b" (_zzq_default), "b" (_zzq_ptr) \
432 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000433 _zzq_result; \
434 })
sewardj0ec07f32006-01-12 12:32:32 +0000435
sewardjd68ac3e2006-01-20 14:31:57 +0000436#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
437 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000438 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000439 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
440 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000441 "or 2,2,2\n\t" \
442 "mr %0,3" \
443 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000444 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000445 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000446 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000447 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000448 }
449
450#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
451 __SPECIAL_INSTRUCTION_PREAMBLE \
452 /* branch-and-link-to-noredir *%R11 */ \
453 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000454#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000455
sewardjf5c1a7f2006-10-17 01:32:48 +0000456/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000457
sewardjf5c1a7f2006-10-17 01:32:48 +0000458#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000459
460typedef
461 struct {
462 unsigned long long int nraddr; /* where's the code? */
463 unsigned long long int r2; /* what tocptr do we need? */
464 }
465 OrigFn;
466
sewardj1a85f4f2006-01-12 21:15:35 +0000467#define __SPECIAL_INSTRUCTION_PREAMBLE \
468 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
469 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
470
bart575ce8e2011-05-15 07:04:03 +0000471#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
472 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000473 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000474 \
bart575ce8e2011-05-15 07:04:03 +0000475 __extension__ \
476 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000477 unsigned long long int _zzq_result; \
478 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000479 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
480 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
481 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
482 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
483 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000484 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000485 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000486 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
487 "mr 4,%2\n\t" /*ptr*/ \
488 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000489 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000490 "or 1,1,1\n\t" \
491 "mr %0,3" /*result*/ \
492 : "=b" (_zzq_result) \
493 : "b" (_zzq_default), "b" (_zzq_ptr) \
494 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000495 _zzq_result; \
496 })
sewardj1a85f4f2006-01-12 21:15:35 +0000497
sewardjd68ac3e2006-01-20 14:31:57 +0000498#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
499 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000500 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000501 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
502 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000503 "or 2,2,2\n\t" \
504 "mr %0,3" \
505 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000506 : \
sewardj8258a3a2011-10-05 07:39:07 +0000507 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000508 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000509 _zzq_orig->nraddr = __addr; \
510 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
511 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000512 "or 4,4,4\n\t" \
513 "mr %0,3" \
514 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000515 : \
sewardj8258a3a2011-10-05 07:39:07 +0000516 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000517 ); \
518 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000519 }
520
521#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
522 __SPECIAL_INSTRUCTION_PREAMBLE \
523 /* branch-and-link-to-noredir *%R11 */ \
524 "or 3,3,3\n\t"
525
sewardjf5c1a7f2006-10-17 01:32:48 +0000526#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000527
sewardj59570ff2010-01-01 11:59:33 +0000528/* ------------------------- arm-linux ------------------------- */
529
530#if defined(PLAT_arm_linux)
531
532typedef
533 struct {
534 unsigned int nraddr; /* where's the code? */
535 }
536 OrigFn;
537
538#define __SPECIAL_INSTRUCTION_PREAMBLE \
539 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
540 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
541
bart575ce8e2011-05-15 07:04:03 +0000542#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
543 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000544 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
545 \
bart575ce8e2011-05-15 07:04:03 +0000546 __extension__ \
547 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000548 volatile unsigned int _zzq_result; \
549 _zzq_args[0] = (unsigned int)(_zzq_request); \
550 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
551 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
552 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
553 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
554 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
555 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
556 "mov r4, %2\n\t" /*ptr*/ \
557 __SPECIAL_INSTRUCTION_PREAMBLE \
558 /* R3 = client_request ( R4 ) */ \
559 "orr r10, r10, r10\n\t" \
560 "mov %0, r3" /*result*/ \
561 : "=r" (_zzq_result) \
562 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
563 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000564 _zzq_result; \
565 })
sewardj59570ff2010-01-01 11:59:33 +0000566
567#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
568 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
569 unsigned int __addr; \
570 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
571 /* R3 = guest_NRADDR */ \
572 "orr r11, r11, r11\n\t" \
573 "mov %0, r3" \
574 : "=r" (__addr) \
575 : \
576 : "cc", "memory", "r3" \
577 ); \
578 _zzq_orig->nraddr = __addr; \
579 }
580
581#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
582 __SPECIAL_INSTRUCTION_PREAMBLE \
583 /* branch-and-link-to-noredir *%R4 */ \
584 "orr r12, r12, r12\n\t"
585
586#endif /* PLAT_arm_linux */
587
sewardjb5b87402011-03-07 16:05:35 +0000588/* ------------------------ s390x-linux ------------------------ */
589
590#if defined(PLAT_s390x_linux)
591
592typedef
593 struct {
594 unsigned long long int nraddr; /* where's the code? */
595 }
596 OrigFn;
597
598/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
599 * code. This detection is implemented in platform specific toIR.c
600 * (e.g. VEX/priv/guest_s390_decoder.c).
601 */
602#define __SPECIAL_INSTRUCTION_PREAMBLE \
603 "lr 15,15\n\t" \
604 "lr 1,1\n\t" \
605 "lr 2,2\n\t" \
606 "lr 3,3\n\t"
607
608#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
609#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
610#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
611
bart575ce8e2011-05-15 07:04:03 +0000612#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
613 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000614 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000615 __extension__ \
616 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000617 volatile unsigned long long int _zzq_result; \
618 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
619 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
620 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
621 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
622 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
623 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
624 __asm__ volatile(/* r2 = args */ \
625 "lgr 2,%1\n\t" \
626 /* r3 = default */ \
627 "lgr 3,%2\n\t" \
628 __SPECIAL_INSTRUCTION_PREAMBLE \
629 __CLIENT_REQUEST_CODE \
630 /* results = r3 */ \
631 "lgr %0, 3\n\t" \
632 : "=d" (_zzq_result) \
633 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
634 : "cc", "2", "3", "memory" \
635 ); \
bart575ce8e2011-05-15 07:04:03 +0000636 _zzq_result; \
637 })
sewardjb5b87402011-03-07 16:05:35 +0000638
639#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
640 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
641 volatile unsigned long long int __addr; \
642 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
643 __GET_NR_CONTEXT_CODE \
644 "lgr %0, 3\n\t" \
645 : "=a" (__addr) \
646 : \
647 : "cc", "3", "memory" \
648 ); \
649 _zzq_orig->nraddr = __addr; \
650 }
651
652#define VALGRIND_CALL_NOREDIR_R1 \
653 __SPECIAL_INSTRUCTION_PREAMBLE \
654 __CALL_NO_REDIR_CODE
655
656#endif /* PLAT_s390x_linux */
657
sewardjf5c1a7f2006-10-17 01:32:48 +0000658/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000659
sewardj37091fb2002-11-16 11:06:50 +0000660#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000661
nethercote69d9c462004-10-26 13:00:12 +0000662
njn30d76c62005-06-18 15:07:39 +0000663/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000664/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000665/* ugly. It's the least-worst tradeoff I can think of. */
666/* ------------------------------------------------------------------ */
667
668/* This section defines magic (a.k.a appalling-hack) macros for doing
669 guaranteed-no-redirection macros, so as to get from function
670 wrappers to the functions they are wrapping. The whole point is to
671 construct standard call sequences, but to do the call itself with a
672 special no-redirect call pseudo-instruction that the JIT
673 understands and handles specially. This section is long and
674 repetitious, and I can't see a way to make it shorter.
675
676 The naming scheme is as follows:
677
678 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
679
680 'W' stands for "word" and 'v' for "void". Hence there are
681 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
682 and for each, the possibility of returning a word-typed result, or
683 no result.
684*/
685
686/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +0000687 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
688 the default behaviour equivalance class tag "0000" into the name.
689 See pub_tool_redir.h for details -- normally you don't need to
690 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +0000691
njn5f5ef2a2009-05-11 08:01:09 +0000692/* Use an extra level of macroisation so as to ensure the soname/fnname
693 args are fully macro-expanded before pasting them together. */
694#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
695
sewardj0ec07f32006-01-12 12:32:32 +0000696#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000697 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000698
699#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000700 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000701
sewardjd68ac3e2006-01-20 14:31:57 +0000702/* Use this macro from within a wrapper function to collect the
703 context (address and possibly other info) of the original function.
704 Once you have that you can then use it in one of the CALL_FN_
705 macros. The type of the argument _lval is OrigFn. */
706#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000707
708/* Derivatives of the main macros below, for calling functions
709 returning void. */
710
711#define CALL_FN_v_v(fnptr) \
712 do { volatile unsigned long _junk; \
713 CALL_FN_W_v(_junk,fnptr); } while (0)
714
715#define CALL_FN_v_W(fnptr, arg1) \
716 do { volatile unsigned long _junk; \
717 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
718
719#define CALL_FN_v_WW(fnptr, arg1,arg2) \
720 do { volatile unsigned long _junk; \
721 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
722
sewardj5ce4b152006-03-11 12:57:41 +0000723#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
724 do { volatile unsigned long _junk; \
725 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
726
njn2b5f0a92009-05-19 01:24:50 +0000727#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
728 do { volatile unsigned long _junk; \
729 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
730
731#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
732 do { volatile unsigned long _junk; \
733 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
734
735#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
736 do { volatile unsigned long _junk; \
737 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
738
739#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
740 do { volatile unsigned long _junk; \
741 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
742
njnf76d27a2009-05-28 01:53:07 +0000743/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000744
njnf76d27a2009-05-28 01:53:07 +0000745#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000746
747/* These regs are trashed by the hidden call. No need to mention eax
748 as gcc can already see that, plus causes gcc to bomb. */
749#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
750
751/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
752 long) == 4. */
753
sewardj66226cc2006-01-20 15:46:46 +0000754#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000755 do { \
sewardj66226cc2006-01-20 15:46:46 +0000756 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000757 volatile unsigned long _argvec[1]; \
758 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000759 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000760 __asm__ volatile( \
761 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
762 VALGRIND_CALL_NOREDIR_EAX \
763 : /*out*/ "=a" (_res) \
764 : /*in*/ "a" (&_argvec[0]) \
765 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
766 ); \
767 lval = (__typeof__(lval)) _res; \
768 } while (0)
769
sewardj66226cc2006-01-20 15:46:46 +0000770#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000771 do { \
sewardj66226cc2006-01-20 15:46:46 +0000772 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000773 volatile unsigned long _argvec[2]; \
774 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000775 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000776 _argvec[1] = (unsigned long)(arg1); \
777 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000778 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000779 "pushl 4(%%eax)\n\t" \
780 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
781 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000782 "addl $16, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000783 : /*out*/ "=a" (_res) \
784 : /*in*/ "a" (&_argvec[0]) \
785 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
786 ); \
787 lval = (__typeof__(lval)) _res; \
788 } while (0)
789
sewardj66226cc2006-01-20 15:46:46 +0000790#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
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[3]; \
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 _argvec[1] = (unsigned long)(arg1); \
797 _argvec[2] = (unsigned long)(arg2); \
798 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000799 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000800 "pushl 8(%%eax)\n\t" \
801 "pushl 4(%%eax)\n\t" \
802 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
803 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000804 "addl $16, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000805 : /*out*/ "=a" (_res) \
806 : /*in*/ "a" (&_argvec[0]) \
807 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
808 ); \
809 lval = (__typeof__(lval)) _res; \
810 } while (0)
811
sewardj9e8b07a2006-02-18 21:13:29 +0000812#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
813 do { \
814 volatile OrigFn _orig = (orig); \
815 volatile unsigned long _argvec[4]; \
816 volatile unsigned long _res; \
817 _argvec[0] = (unsigned long)_orig.nraddr; \
818 _argvec[1] = (unsigned long)(arg1); \
819 _argvec[2] = (unsigned long)(arg2); \
820 _argvec[3] = (unsigned long)(arg3); \
821 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000822 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +0000823 "pushl 12(%%eax)\n\t" \
824 "pushl 8(%%eax)\n\t" \
825 "pushl 4(%%eax)\n\t" \
826 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
827 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000828 "addl $16, %%esp\n" \
sewardj9e8b07a2006-02-18 21:13:29 +0000829 : /*out*/ "=a" (_res) \
830 : /*in*/ "a" (&_argvec[0]) \
831 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
832 ); \
833 lval = (__typeof__(lval)) _res; \
834 } while (0)
835
sewardj66226cc2006-01-20 15:46:46 +0000836#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000837 do { \
sewardj66226cc2006-01-20 15:46:46 +0000838 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000839 volatile unsigned long _argvec[5]; \
840 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000841 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000842 _argvec[1] = (unsigned long)(arg1); \
843 _argvec[2] = (unsigned long)(arg2); \
844 _argvec[3] = (unsigned long)(arg3); \
845 _argvec[4] = (unsigned long)(arg4); \
846 __asm__ volatile( \
847 "pushl 16(%%eax)\n\t" \
848 "pushl 12(%%eax)\n\t" \
849 "pushl 8(%%eax)\n\t" \
850 "pushl 4(%%eax)\n\t" \
851 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
852 VALGRIND_CALL_NOREDIR_EAX \
853 "addl $16, %%esp\n" \
854 : /*out*/ "=a" (_res) \
855 : /*in*/ "a" (&_argvec[0]) \
856 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
857 ); \
858 lval = (__typeof__(lval)) _res; \
859 } while (0)
860
sewardj66226cc2006-01-20 15:46:46 +0000861#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000862 do { \
sewardj66226cc2006-01-20 15:46:46 +0000863 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000864 volatile unsigned long _argvec[6]; \
865 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000866 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000867 _argvec[1] = (unsigned long)(arg1); \
868 _argvec[2] = (unsigned long)(arg2); \
869 _argvec[3] = (unsigned long)(arg3); \
870 _argvec[4] = (unsigned long)(arg4); \
871 _argvec[5] = (unsigned long)(arg5); \
872 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000873 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000874 "pushl 20(%%eax)\n\t" \
875 "pushl 16(%%eax)\n\t" \
876 "pushl 12(%%eax)\n\t" \
877 "pushl 8(%%eax)\n\t" \
878 "pushl 4(%%eax)\n\t" \
879 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
880 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000881 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000882 : /*out*/ "=a" (_res) \
883 : /*in*/ "a" (&_argvec[0]) \
884 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
885 ); \
886 lval = (__typeof__(lval)) _res; \
887 } while (0)
888
sewardj66226cc2006-01-20 15:46:46 +0000889#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000890 do { \
sewardj66226cc2006-01-20 15:46:46 +0000891 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000892 volatile unsigned long _argvec[7]; \
893 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000894 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000895 _argvec[1] = (unsigned long)(arg1); \
896 _argvec[2] = (unsigned long)(arg2); \
897 _argvec[3] = (unsigned long)(arg3); \
898 _argvec[4] = (unsigned long)(arg4); \
899 _argvec[5] = (unsigned long)(arg5); \
900 _argvec[6] = (unsigned long)(arg6); \
901 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000902 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000903 "pushl 24(%%eax)\n\t" \
904 "pushl 20(%%eax)\n\t" \
905 "pushl 16(%%eax)\n\t" \
906 "pushl 12(%%eax)\n\t" \
907 "pushl 8(%%eax)\n\t" \
908 "pushl 4(%%eax)\n\t" \
909 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
910 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000911 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000912 : /*out*/ "=a" (_res) \
913 : /*in*/ "a" (&_argvec[0]) \
914 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
915 ); \
916 lval = (__typeof__(lval)) _res; \
917 } while (0)
918
sewardj66226cc2006-01-20 15:46:46 +0000919#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
920 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000921 do { \
sewardj66226cc2006-01-20 15:46:46 +0000922 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000923 volatile unsigned long _argvec[8]; \
924 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000925 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000926 _argvec[1] = (unsigned long)(arg1); \
927 _argvec[2] = (unsigned long)(arg2); \
928 _argvec[3] = (unsigned long)(arg3); \
929 _argvec[4] = (unsigned long)(arg4); \
930 _argvec[5] = (unsigned long)(arg5); \
931 _argvec[6] = (unsigned long)(arg6); \
932 _argvec[7] = (unsigned long)(arg7); \
933 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000934 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000935 "pushl 28(%%eax)\n\t" \
936 "pushl 24(%%eax)\n\t" \
937 "pushl 20(%%eax)\n\t" \
938 "pushl 16(%%eax)\n\t" \
939 "pushl 12(%%eax)\n\t" \
940 "pushl 8(%%eax)\n\t" \
941 "pushl 4(%%eax)\n\t" \
942 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
943 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000944 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000945 : /*out*/ "=a" (_res) \
946 : /*in*/ "a" (&_argvec[0]) \
947 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
948 ); \
949 lval = (__typeof__(lval)) _res; \
950 } while (0)
951
sewardj66226cc2006-01-20 15:46:46 +0000952#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
953 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000954 do { \
sewardj66226cc2006-01-20 15:46:46 +0000955 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000956 volatile unsigned long _argvec[9]; \
957 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000958 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000959 _argvec[1] = (unsigned long)(arg1); \
960 _argvec[2] = (unsigned long)(arg2); \
961 _argvec[3] = (unsigned long)(arg3); \
962 _argvec[4] = (unsigned long)(arg4); \
963 _argvec[5] = (unsigned long)(arg5); \
964 _argvec[6] = (unsigned long)(arg6); \
965 _argvec[7] = (unsigned long)(arg7); \
966 _argvec[8] = (unsigned long)(arg8); \
967 __asm__ volatile( \
968 "pushl 32(%%eax)\n\t" \
969 "pushl 28(%%eax)\n\t" \
970 "pushl 24(%%eax)\n\t" \
971 "pushl 20(%%eax)\n\t" \
972 "pushl 16(%%eax)\n\t" \
973 "pushl 12(%%eax)\n\t" \
974 "pushl 8(%%eax)\n\t" \
975 "pushl 4(%%eax)\n\t" \
976 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
977 VALGRIND_CALL_NOREDIR_EAX \
978 "addl $32, %%esp\n" \
979 : /*out*/ "=a" (_res) \
980 : /*in*/ "a" (&_argvec[0]) \
981 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
982 ); \
983 lval = (__typeof__(lval)) _res; \
984 } while (0)
985
sewardj45fa5b02006-03-09 19:06:23 +0000986#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
987 arg7,arg8,arg9) \
988 do { \
989 volatile OrigFn _orig = (orig); \
990 volatile unsigned long _argvec[10]; \
991 volatile unsigned long _res; \
992 _argvec[0] = (unsigned long)_orig.nraddr; \
993 _argvec[1] = (unsigned long)(arg1); \
994 _argvec[2] = (unsigned long)(arg2); \
995 _argvec[3] = (unsigned long)(arg3); \
996 _argvec[4] = (unsigned long)(arg4); \
997 _argvec[5] = (unsigned long)(arg5); \
998 _argvec[6] = (unsigned long)(arg6); \
999 _argvec[7] = (unsigned long)(arg7); \
1000 _argvec[8] = (unsigned long)(arg8); \
1001 _argvec[9] = (unsigned long)(arg9); \
1002 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001003 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001004 "pushl 36(%%eax)\n\t" \
1005 "pushl 32(%%eax)\n\t" \
1006 "pushl 28(%%eax)\n\t" \
1007 "pushl 24(%%eax)\n\t" \
1008 "pushl 20(%%eax)\n\t" \
1009 "pushl 16(%%eax)\n\t" \
1010 "pushl 12(%%eax)\n\t" \
1011 "pushl 8(%%eax)\n\t" \
1012 "pushl 4(%%eax)\n\t" \
1013 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1014 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001015 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001016 : /*out*/ "=a" (_res) \
1017 : /*in*/ "a" (&_argvec[0]) \
1018 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1019 ); \
1020 lval = (__typeof__(lval)) _res; \
1021 } while (0)
1022
1023#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1024 arg7,arg8,arg9,arg10) \
1025 do { \
1026 volatile OrigFn _orig = (orig); \
1027 volatile unsigned long _argvec[11]; \
1028 volatile unsigned long _res; \
1029 _argvec[0] = (unsigned long)_orig.nraddr; \
1030 _argvec[1] = (unsigned long)(arg1); \
1031 _argvec[2] = (unsigned long)(arg2); \
1032 _argvec[3] = (unsigned long)(arg3); \
1033 _argvec[4] = (unsigned long)(arg4); \
1034 _argvec[5] = (unsigned long)(arg5); \
1035 _argvec[6] = (unsigned long)(arg6); \
1036 _argvec[7] = (unsigned long)(arg7); \
1037 _argvec[8] = (unsigned long)(arg8); \
1038 _argvec[9] = (unsigned long)(arg9); \
1039 _argvec[10] = (unsigned long)(arg10); \
1040 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001041 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001042 "pushl 40(%%eax)\n\t" \
1043 "pushl 36(%%eax)\n\t" \
1044 "pushl 32(%%eax)\n\t" \
1045 "pushl 28(%%eax)\n\t" \
1046 "pushl 24(%%eax)\n\t" \
1047 "pushl 20(%%eax)\n\t" \
1048 "pushl 16(%%eax)\n\t" \
1049 "pushl 12(%%eax)\n\t" \
1050 "pushl 8(%%eax)\n\t" \
1051 "pushl 4(%%eax)\n\t" \
1052 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1053 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001054 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001055 : /*out*/ "=a" (_res) \
1056 : /*in*/ "a" (&_argvec[0]) \
1057 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1058 ); \
1059 lval = (__typeof__(lval)) _res; \
1060 } while (0)
1061
sewardj5ce4b152006-03-11 12:57:41 +00001062#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1063 arg6,arg7,arg8,arg9,arg10, \
1064 arg11) \
1065 do { \
1066 volatile OrigFn _orig = (orig); \
1067 volatile unsigned long _argvec[12]; \
1068 volatile unsigned long _res; \
1069 _argvec[0] = (unsigned long)_orig.nraddr; \
1070 _argvec[1] = (unsigned long)(arg1); \
1071 _argvec[2] = (unsigned long)(arg2); \
1072 _argvec[3] = (unsigned long)(arg3); \
1073 _argvec[4] = (unsigned long)(arg4); \
1074 _argvec[5] = (unsigned long)(arg5); \
1075 _argvec[6] = (unsigned long)(arg6); \
1076 _argvec[7] = (unsigned long)(arg7); \
1077 _argvec[8] = (unsigned long)(arg8); \
1078 _argvec[9] = (unsigned long)(arg9); \
1079 _argvec[10] = (unsigned long)(arg10); \
1080 _argvec[11] = (unsigned long)(arg11); \
1081 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001082 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001083 "pushl 44(%%eax)\n\t" \
1084 "pushl 40(%%eax)\n\t" \
1085 "pushl 36(%%eax)\n\t" \
1086 "pushl 32(%%eax)\n\t" \
1087 "pushl 28(%%eax)\n\t" \
1088 "pushl 24(%%eax)\n\t" \
1089 "pushl 20(%%eax)\n\t" \
1090 "pushl 16(%%eax)\n\t" \
1091 "pushl 12(%%eax)\n\t" \
1092 "pushl 8(%%eax)\n\t" \
1093 "pushl 4(%%eax)\n\t" \
1094 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1095 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001096 "addl $48, %%esp\n" \
sewardj5ce4b152006-03-11 12:57:41 +00001097 : /*out*/ "=a" (_res) \
1098 : /*in*/ "a" (&_argvec[0]) \
1099 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1100 ); \
1101 lval = (__typeof__(lval)) _res; \
1102 } while (0)
1103
sewardj66226cc2006-01-20 15:46:46 +00001104#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1105 arg6,arg7,arg8,arg9,arg10, \
1106 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001107 do { \
sewardj66226cc2006-01-20 15:46:46 +00001108 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001109 volatile unsigned long _argvec[13]; \
1110 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001111 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001112 _argvec[1] = (unsigned long)(arg1); \
1113 _argvec[2] = (unsigned long)(arg2); \
1114 _argvec[3] = (unsigned long)(arg3); \
1115 _argvec[4] = (unsigned long)(arg4); \
1116 _argvec[5] = (unsigned long)(arg5); \
1117 _argvec[6] = (unsigned long)(arg6); \
1118 _argvec[7] = (unsigned long)(arg7); \
1119 _argvec[8] = (unsigned long)(arg8); \
1120 _argvec[9] = (unsigned long)(arg9); \
1121 _argvec[10] = (unsigned long)(arg10); \
1122 _argvec[11] = (unsigned long)(arg11); \
1123 _argvec[12] = (unsigned long)(arg12); \
1124 __asm__ volatile( \
1125 "pushl 48(%%eax)\n\t" \
1126 "pushl 44(%%eax)\n\t" \
1127 "pushl 40(%%eax)\n\t" \
1128 "pushl 36(%%eax)\n\t" \
1129 "pushl 32(%%eax)\n\t" \
1130 "pushl 28(%%eax)\n\t" \
1131 "pushl 24(%%eax)\n\t" \
1132 "pushl 20(%%eax)\n\t" \
1133 "pushl 16(%%eax)\n\t" \
1134 "pushl 12(%%eax)\n\t" \
1135 "pushl 8(%%eax)\n\t" \
1136 "pushl 4(%%eax)\n\t" \
1137 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1138 VALGRIND_CALL_NOREDIR_EAX \
1139 "addl $48, %%esp\n" \
1140 : /*out*/ "=a" (_res) \
1141 : /*in*/ "a" (&_argvec[0]) \
1142 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1143 ); \
1144 lval = (__typeof__(lval)) _res; \
1145 } while (0)
1146
njnf76d27a2009-05-28 01:53:07 +00001147#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001148
njnf76d27a2009-05-28 01:53:07 +00001149/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001150
njnf76d27a2009-05-28 01:53:07 +00001151#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001152
1153/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1154
1155/* These regs are trashed by the hidden call. */
1156#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1157 "rdi", "r8", "r9", "r10", "r11"
1158
sewardjdfa55cf2010-10-06 22:07:06 +00001159/* This is all pretty complex. It's so as to make stack unwinding
1160 work reliably. See bug 243270. The basic problem is the sub and
1161 add of 128 of %rsp in all of the following macros. If gcc believes
1162 the CFA is in %rsp, then unwinding may fail, because what's at the
1163 CFA is not what gcc "expected" when it constructs the CFIs for the
1164 places where the macros are instantiated.
1165
1166 But we can't just add a CFI annotation to increase the CFA offset
1167 by 128, to match the sub of 128 from %rsp, because we don't know
1168 whether gcc has chosen %rsp as the CFA at that point, or whether it
1169 has chosen some other register (eg, %rbp). In the latter case,
1170 adding a CFI annotation to change the CFA offset is simply wrong.
1171
1172 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001173 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001174 CFI annotation to say what the register is. We choose %rbp for
1175 this (perhaps perversely), because:
1176
1177 (1) %rbp is already subject to unwinding. If a new register was
1178 chosen then the unwinder would have to unwind it in all stack
1179 traces, which is expensive, and
1180
1181 (2) %rbp is already subject to precise exception updates in the
1182 JIT. If a new register was chosen, we'd have to have precise
1183 exceptions for it too, which reduces performance of the
1184 generated code.
1185
1186 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001187 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001188 list of trashed registers at the end of the inline assembly
1189 fragments; gcc won't allow %rbp to appear in that list. Hence
1190 instead we need to stash %rbp in %r15 for the duration of the asm,
1191 and say that %r15 is trashed instead. gcc seems happy to go with
1192 that.
1193
1194 Oh .. and this all needs to be conditionalised so that it is
1195 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001196 that don't support __builtin_dwarf_cfa. Furthermore, since
1197 this header file is freestanding, it has to be independent of
1198 config.h, and so the following conditionalisation cannot depend on
1199 configure time checks.
1200
1201 Although it's not clear from
1202 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1203 this expression excludes Darwin.
1204 .cfi directives in Darwin assembly appear to be completely
1205 different and I haven't investigated how they work.
1206
1207 For even more entertainment value, note we have to use the
1208 completely undocumented __builtin_dwarf_cfa(), which appears to
1209 really compute the CFA, whereas __builtin_frame_address(0) claims
1210 to but actually doesn't. See
1211 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001212*/
sewardj8d1dc152010-10-08 17:43:26 +00001213#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001214# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001215 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001216# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001217 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001218 "movq %2, %%rbp\n\t" \
1219 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001220 ".cfi_def_cfa rbp, 0\n\t"
1221# define VALGRIND_CFI_EPILOGUE \
1222 "movq %%r15, %%rbp\n\t" \
1223 ".cfi_restore_state\n\t"
1224#else
1225# define __FRAME_POINTER
1226# define VALGRIND_CFI_PROLOGUE
1227# define VALGRIND_CFI_EPILOGUE
1228#endif
1229
1230
sewardj0ec07f32006-01-12 12:32:32 +00001231/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1232 long) == 8. */
1233
sewardja07c2e12007-11-09 23:09:50 +00001234/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1235 macros. In order not to trash the stack redzone, we need to drop
1236 %rsp by 128 before the hidden call, and restore afterwards. The
1237 nastyness is that it is only by luck that the stack still appears
1238 to be unwindable during the hidden call - since then the behaviour
1239 of any routine using this macro does not match what the CFI data
1240 says. Sigh.
1241
1242 Why is this important? Imagine that a wrapper has a stack
1243 allocated local, and passes to the hidden call, a pointer to it.
1244 Because gcc does not know about the hidden call, it may allocate
1245 that local in the redzone. Unfortunately the hidden call may then
1246 trash it before it comes to use it. So we must step clear of the
1247 redzone, for the duration of the hidden call, to make it safe.
1248
1249 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001250 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001251 self describing (none of this CFI nonsense) so at least messing
1252 with the stack pointer doesn't give a danger of non-unwindable
1253 stack. */
1254
sewardjc8858442006-01-20 15:17:20 +00001255#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001256 do { \
sewardjc8858442006-01-20 15:17:20 +00001257 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001258 volatile unsigned long _argvec[1]; \
1259 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001260 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001261 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001262 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001263 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001264 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1265 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001266 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001267 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001268 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001269 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1270 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001271 ); \
1272 lval = (__typeof__(lval)) _res; \
1273 } while (0)
1274
sewardjc8858442006-01-20 15:17:20 +00001275#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001276 do { \
sewardjc8858442006-01-20 15:17:20 +00001277 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001278 volatile unsigned long _argvec[2]; \
1279 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001280 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001281 _argvec[1] = (unsigned long)(arg1); \
1282 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001283 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001284 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001285 "movq 8(%%rax), %%rdi\n\t" \
1286 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1287 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001288 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001289 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001290 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001291 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1292 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001293 ); \
1294 lval = (__typeof__(lval)) _res; \
1295 } while (0)
1296
sewardjc8858442006-01-20 15:17:20 +00001297#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001298 do { \
sewardjc8858442006-01-20 15:17:20 +00001299 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001300 volatile unsigned long _argvec[3]; \
1301 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001302 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001303 _argvec[1] = (unsigned long)(arg1); \
1304 _argvec[2] = (unsigned long)(arg2); \
1305 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001306 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001307 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001308 "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" \
sewardjdfa55cf2010-10-06 22:07:06 +00001313 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001314 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001315 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1316 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001317 ); \
1318 lval = (__typeof__(lval)) _res; \
1319 } while (0)
1320
sewardja50f9dc2006-03-11 16:19:14 +00001321#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1322 do { \
1323 volatile OrigFn _orig = (orig); \
1324 volatile unsigned long _argvec[4]; \
1325 volatile unsigned long _res; \
1326 _argvec[0] = (unsigned long)_orig.nraddr; \
1327 _argvec[1] = (unsigned long)(arg1); \
1328 _argvec[2] = (unsigned long)(arg2); \
1329 _argvec[3] = (unsigned long)(arg3); \
1330 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001331 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001332 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001333 "movq 24(%%rax), %%rdx\n\t" \
1334 "movq 16(%%rax), %%rsi\n\t" \
1335 "movq 8(%%rax), %%rdi\n\t" \
1336 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1337 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001338 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001339 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001340 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001341 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1342 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001343 ); \
1344 lval = (__typeof__(lval)) _res; \
1345 } while (0)
1346
1347#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1348 do { \
1349 volatile OrigFn _orig = (orig); \
1350 volatile unsigned long _argvec[5]; \
1351 volatile unsigned long _res; \
1352 _argvec[0] = (unsigned long)_orig.nraddr; \
1353 _argvec[1] = (unsigned long)(arg1); \
1354 _argvec[2] = (unsigned long)(arg2); \
1355 _argvec[3] = (unsigned long)(arg3); \
1356 _argvec[4] = (unsigned long)(arg4); \
1357 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001358 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001359 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001360 "movq 32(%%rax), %%rcx\n\t" \
1361 "movq 24(%%rax), %%rdx\n\t" \
1362 "movq 16(%%rax), %%rsi\n\t" \
1363 "movq 8(%%rax), %%rdi\n\t" \
1364 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1365 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001366 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001367 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001368 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001369 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1370 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001371 ); \
1372 lval = (__typeof__(lval)) _res; \
1373 } while (0)
1374
1375#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1376 do { \
1377 volatile OrigFn _orig = (orig); \
1378 volatile unsigned long _argvec[6]; \
1379 volatile unsigned long _res; \
1380 _argvec[0] = (unsigned long)_orig.nraddr; \
1381 _argvec[1] = (unsigned long)(arg1); \
1382 _argvec[2] = (unsigned long)(arg2); \
1383 _argvec[3] = (unsigned long)(arg3); \
1384 _argvec[4] = (unsigned long)(arg4); \
1385 _argvec[5] = (unsigned long)(arg5); \
1386 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001387 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001388 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001389 "movq 40(%%rax), %%r8\n\t" \
1390 "movq 32(%%rax), %%rcx\n\t" \
1391 "movq 24(%%rax), %%rdx\n\t" \
1392 "movq 16(%%rax), %%rsi\n\t" \
1393 "movq 8(%%rax), %%rdi\n\t" \
1394 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1395 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001396 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001397 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001398 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001399 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1400 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001401 ); \
1402 lval = (__typeof__(lval)) _res; \
1403 } while (0)
1404
1405#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1406 do { \
1407 volatile OrigFn _orig = (orig); \
1408 volatile unsigned long _argvec[7]; \
1409 volatile unsigned long _res; \
1410 _argvec[0] = (unsigned long)_orig.nraddr; \
1411 _argvec[1] = (unsigned long)(arg1); \
1412 _argvec[2] = (unsigned long)(arg2); \
1413 _argvec[3] = (unsigned long)(arg3); \
1414 _argvec[4] = (unsigned long)(arg4); \
1415 _argvec[5] = (unsigned long)(arg5); \
1416 _argvec[6] = (unsigned long)(arg6); \
1417 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001418 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001419 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001420 "movq 48(%%rax), %%r9\n\t" \
1421 "movq 40(%%rax), %%r8\n\t" \
1422 "movq 32(%%rax), %%rcx\n\t" \
1423 "movq 24(%%rax), %%rdx\n\t" \
1424 "movq 16(%%rax), %%rsi\n\t" \
1425 "movq 8(%%rax), %%rdi\n\t" \
1426 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1427 VALGRIND_CALL_NOREDIR_RAX \
bart2823aac2010-09-05 12:10:25 +00001428 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001429 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001430 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001431 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1432 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001433 ); \
1434 lval = (__typeof__(lval)) _res; \
1435 } while (0)
1436
1437#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1438 arg7) \
1439 do { \
1440 volatile OrigFn _orig = (orig); \
1441 volatile unsigned long _argvec[8]; \
1442 volatile unsigned long _res; \
1443 _argvec[0] = (unsigned long)_orig.nraddr; \
1444 _argvec[1] = (unsigned long)(arg1); \
1445 _argvec[2] = (unsigned long)(arg2); \
1446 _argvec[3] = (unsigned long)(arg3); \
1447 _argvec[4] = (unsigned long)(arg4); \
1448 _argvec[5] = (unsigned long)(arg5); \
1449 _argvec[6] = (unsigned long)(arg6); \
1450 _argvec[7] = (unsigned long)(arg7); \
1451 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001452 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001453 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001454 "pushq 56(%%rax)\n\t" \
1455 "movq 48(%%rax), %%r9\n\t" \
1456 "movq 40(%%rax), %%r8\n\t" \
1457 "movq 32(%%rax), %%rcx\n\t" \
1458 "movq 24(%%rax), %%rdx\n\t" \
1459 "movq 16(%%rax), %%rsi\n\t" \
1460 "movq 8(%%rax), %%rdi\n\t" \
1461 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1462 VALGRIND_CALL_NOREDIR_RAX \
1463 "addq $8, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001464 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001465 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001466 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001467 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1468 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001469 ); \
1470 lval = (__typeof__(lval)) _res; \
1471 } while (0)
1472
1473#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1474 arg7,arg8) \
1475 do { \
1476 volatile OrigFn _orig = (orig); \
1477 volatile unsigned long _argvec[9]; \
1478 volatile unsigned long _res; \
1479 _argvec[0] = (unsigned long)_orig.nraddr; \
1480 _argvec[1] = (unsigned long)(arg1); \
1481 _argvec[2] = (unsigned long)(arg2); \
1482 _argvec[3] = (unsigned long)(arg3); \
1483 _argvec[4] = (unsigned long)(arg4); \
1484 _argvec[5] = (unsigned long)(arg5); \
1485 _argvec[6] = (unsigned long)(arg6); \
1486 _argvec[7] = (unsigned long)(arg7); \
1487 _argvec[8] = (unsigned long)(arg8); \
1488 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001489 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001490 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001491 "pushq 64(%%rax)\n\t" \
1492 "pushq 56(%%rax)\n\t" \
1493 "movq 48(%%rax), %%r9\n\t" \
1494 "movq 40(%%rax), %%r8\n\t" \
1495 "movq 32(%%rax), %%rcx\n\t" \
1496 "movq 24(%%rax), %%rdx\n\t" \
1497 "movq 16(%%rax), %%rsi\n\t" \
1498 "movq 8(%%rax), %%rdi\n\t" \
1499 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1500 VALGRIND_CALL_NOREDIR_RAX \
1501 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001502 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001503 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001504 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001505 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1506 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001507 ); \
1508 lval = (__typeof__(lval)) _res; \
1509 } while (0)
1510
1511#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1512 arg7,arg8,arg9) \
1513 do { \
1514 volatile OrigFn _orig = (orig); \
1515 volatile unsigned long _argvec[10]; \
1516 volatile unsigned long _res; \
1517 _argvec[0] = (unsigned long)_orig.nraddr; \
1518 _argvec[1] = (unsigned long)(arg1); \
1519 _argvec[2] = (unsigned long)(arg2); \
1520 _argvec[3] = (unsigned long)(arg3); \
1521 _argvec[4] = (unsigned long)(arg4); \
1522 _argvec[5] = (unsigned long)(arg5); \
1523 _argvec[6] = (unsigned long)(arg6); \
1524 _argvec[7] = (unsigned long)(arg7); \
1525 _argvec[8] = (unsigned long)(arg8); \
1526 _argvec[9] = (unsigned long)(arg9); \
1527 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001528 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001529 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001530 "pushq 72(%%rax)\n\t" \
1531 "pushq 64(%%rax)\n\t" \
1532 "pushq 56(%%rax)\n\t" \
1533 "movq 48(%%rax), %%r9\n\t" \
1534 "movq 40(%%rax), %%r8\n\t" \
1535 "movq 32(%%rax), %%rcx\n\t" \
1536 "movq 24(%%rax), %%rdx\n\t" \
1537 "movq 16(%%rax), %%rsi\n\t" \
1538 "movq 8(%%rax), %%rdi\n\t" \
1539 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1540 VALGRIND_CALL_NOREDIR_RAX \
1541 "addq $24, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001542 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001543 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001544 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001545 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1546 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001547 ); \
1548 lval = (__typeof__(lval)) _res; \
1549 } while (0)
1550
1551#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1552 arg7,arg8,arg9,arg10) \
1553 do { \
1554 volatile OrigFn _orig = (orig); \
1555 volatile unsigned long _argvec[11]; \
1556 volatile unsigned long _res; \
1557 _argvec[0] = (unsigned long)_orig.nraddr; \
1558 _argvec[1] = (unsigned long)(arg1); \
1559 _argvec[2] = (unsigned long)(arg2); \
1560 _argvec[3] = (unsigned long)(arg3); \
1561 _argvec[4] = (unsigned long)(arg4); \
1562 _argvec[5] = (unsigned long)(arg5); \
1563 _argvec[6] = (unsigned long)(arg6); \
1564 _argvec[7] = (unsigned long)(arg7); \
1565 _argvec[8] = (unsigned long)(arg8); \
1566 _argvec[9] = (unsigned long)(arg9); \
1567 _argvec[10] = (unsigned long)(arg10); \
1568 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001569 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001570 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001571 "pushq 80(%%rax)\n\t" \
1572 "pushq 72(%%rax)\n\t" \
1573 "pushq 64(%%rax)\n\t" \
1574 "pushq 56(%%rax)\n\t" \
1575 "movq 48(%%rax), %%r9\n\t" \
1576 "movq 40(%%rax), %%r8\n\t" \
1577 "movq 32(%%rax), %%rcx\n\t" \
1578 "movq 24(%%rax), %%rdx\n\t" \
1579 "movq 16(%%rax), %%rsi\n\t" \
1580 "movq 8(%%rax), %%rdi\n\t" \
1581 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1582 VALGRIND_CALL_NOREDIR_RAX \
1583 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001584 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001585 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001586 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001587 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1588 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001589 ); \
1590 lval = (__typeof__(lval)) _res; \
1591 } while (0)
1592
1593#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1594 arg7,arg8,arg9,arg10,arg11) \
1595 do { \
1596 volatile OrigFn _orig = (orig); \
1597 volatile unsigned long _argvec[12]; \
1598 volatile unsigned long _res; \
1599 _argvec[0] = (unsigned long)_orig.nraddr; \
1600 _argvec[1] = (unsigned long)(arg1); \
1601 _argvec[2] = (unsigned long)(arg2); \
1602 _argvec[3] = (unsigned long)(arg3); \
1603 _argvec[4] = (unsigned long)(arg4); \
1604 _argvec[5] = (unsigned long)(arg5); \
1605 _argvec[6] = (unsigned long)(arg6); \
1606 _argvec[7] = (unsigned long)(arg7); \
1607 _argvec[8] = (unsigned long)(arg8); \
1608 _argvec[9] = (unsigned long)(arg9); \
1609 _argvec[10] = (unsigned long)(arg10); \
1610 _argvec[11] = (unsigned long)(arg11); \
1611 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001612 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001613 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001614 "pushq 88(%%rax)\n\t" \
1615 "pushq 80(%%rax)\n\t" \
1616 "pushq 72(%%rax)\n\t" \
1617 "pushq 64(%%rax)\n\t" \
1618 "pushq 56(%%rax)\n\t" \
1619 "movq 48(%%rax), %%r9\n\t" \
1620 "movq 40(%%rax), %%r8\n\t" \
1621 "movq 32(%%rax), %%rcx\n\t" \
1622 "movq 24(%%rax), %%rdx\n\t" \
1623 "movq 16(%%rax), %%rsi\n\t" \
1624 "movq 8(%%rax), %%rdi\n\t" \
1625 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1626 VALGRIND_CALL_NOREDIR_RAX \
1627 "addq $40, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001628 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001629 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001630 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001631 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1632 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001633 ); \
1634 lval = (__typeof__(lval)) _res; \
1635 } while (0)
1636
1637#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1638 arg7,arg8,arg9,arg10,arg11,arg12) \
1639 do { \
1640 volatile OrigFn _orig = (orig); \
1641 volatile unsigned long _argvec[13]; \
1642 volatile unsigned long _res; \
1643 _argvec[0] = (unsigned long)_orig.nraddr; \
1644 _argvec[1] = (unsigned long)(arg1); \
1645 _argvec[2] = (unsigned long)(arg2); \
1646 _argvec[3] = (unsigned long)(arg3); \
1647 _argvec[4] = (unsigned long)(arg4); \
1648 _argvec[5] = (unsigned long)(arg5); \
1649 _argvec[6] = (unsigned long)(arg6); \
1650 _argvec[7] = (unsigned long)(arg7); \
1651 _argvec[8] = (unsigned long)(arg8); \
1652 _argvec[9] = (unsigned long)(arg9); \
1653 _argvec[10] = (unsigned long)(arg10); \
1654 _argvec[11] = (unsigned long)(arg11); \
1655 _argvec[12] = (unsigned long)(arg12); \
1656 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001657 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001658 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001659 "pushq 96(%%rax)\n\t" \
1660 "pushq 88(%%rax)\n\t" \
1661 "pushq 80(%%rax)\n\t" \
1662 "pushq 72(%%rax)\n\t" \
1663 "pushq 64(%%rax)\n\t" \
1664 "pushq 56(%%rax)\n\t" \
1665 "movq 48(%%rax), %%r9\n\t" \
1666 "movq 40(%%rax), %%r8\n\t" \
1667 "movq 32(%%rax), %%rcx\n\t" \
1668 "movq 24(%%rax), %%rdx\n\t" \
1669 "movq 16(%%rax), %%rsi\n\t" \
1670 "movq 8(%%rax), %%rdi\n\t" \
1671 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1672 VALGRIND_CALL_NOREDIR_RAX \
1673 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001674 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001675 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001676 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001677 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1678 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001679 ); \
1680 lval = (__typeof__(lval)) _res; \
1681 } while (0)
1682
njnf76d27a2009-05-28 01:53:07 +00001683#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001684
sewardjf5c1a7f2006-10-17 01:32:48 +00001685/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001686
sewardjf5c1a7f2006-10-17 01:32:48 +00001687#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001688
sewardjead61df2006-03-12 13:39:15 +00001689/* This is useful for finding out about the on-stack stuff:
1690
1691 extern int f9 ( int,int,int,int,int,int,int,int,int );
1692 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1693 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1694 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1695
1696 int g9 ( void ) {
1697 return f9(11,22,33,44,55,66,77,88,99);
1698 }
1699 int g10 ( void ) {
1700 return f10(11,22,33,44,55,66,77,88,99,110);
1701 }
1702 int g11 ( void ) {
1703 return f11(11,22,33,44,55,66,77,88,99,110,121);
1704 }
1705 int g12 ( void ) {
1706 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1707 }
1708*/
1709
sewardj0ec07f32006-01-12 12:32:32 +00001710/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1711
1712/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001713#define __CALLER_SAVED_REGS \
1714 "lr", "ctr", "xer", \
1715 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1716 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1717 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001718
sewardjead61df2006-03-12 13:39:15 +00001719/* These CALL_FN_ macros assume that on ppc32-linux,
1720 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001721
sewardj38de0992006-01-20 16:46:34 +00001722#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001723 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001724 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001725 volatile unsigned long _argvec[1]; \
1726 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001727 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001728 __asm__ volatile( \
1729 "mr 11,%1\n\t" \
1730 "lwz 11,0(11)\n\t" /* target->r11 */ \
1731 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1732 "mr %0,3" \
1733 : /*out*/ "=r" (_res) \
1734 : /*in*/ "r" (&_argvec[0]) \
1735 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1736 ); \
1737 lval = (__typeof__(lval)) _res; \
1738 } while (0)
1739
sewardj38de0992006-01-20 16:46:34 +00001740#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001741 do { \
sewardj38de0992006-01-20 16:46:34 +00001742 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001743 volatile unsigned long _argvec[2]; \
1744 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001745 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001746 _argvec[1] = (unsigned long)arg1; \
1747 __asm__ volatile( \
1748 "mr 11,%1\n\t" \
1749 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1750 "lwz 11,0(11)\n\t" /* target->r11 */ \
1751 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1752 "mr %0,3" \
1753 : /*out*/ "=r" (_res) \
1754 : /*in*/ "r" (&_argvec[0]) \
1755 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1756 ); \
1757 lval = (__typeof__(lval)) _res; \
1758 } while (0)
1759
sewardj38de0992006-01-20 16:46:34 +00001760#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001761 do { \
sewardj38de0992006-01-20 16:46:34 +00001762 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001763 volatile unsigned long _argvec[3]; \
1764 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001765 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001766 _argvec[1] = (unsigned long)arg1; \
1767 _argvec[2] = (unsigned long)arg2; \
1768 __asm__ volatile( \
1769 "mr 11,%1\n\t" \
1770 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1771 "lwz 4,8(11)\n\t" \
1772 "lwz 11,0(11)\n\t" /* target->r11 */ \
1773 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1774 "mr %0,3" \
1775 : /*out*/ "=r" (_res) \
1776 : /*in*/ "r" (&_argvec[0]) \
1777 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1778 ); \
1779 lval = (__typeof__(lval)) _res; \
1780 } while (0)
1781
sewardjead61df2006-03-12 13:39:15 +00001782#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1783 do { \
1784 volatile OrigFn _orig = (orig); \
1785 volatile unsigned long _argvec[4]; \
1786 volatile unsigned long _res; \
1787 _argvec[0] = (unsigned long)_orig.nraddr; \
1788 _argvec[1] = (unsigned long)arg1; \
1789 _argvec[2] = (unsigned long)arg2; \
1790 _argvec[3] = (unsigned long)arg3; \
1791 __asm__ volatile( \
1792 "mr 11,%1\n\t" \
1793 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1794 "lwz 4,8(11)\n\t" \
1795 "lwz 5,12(11)\n\t" \
1796 "lwz 11,0(11)\n\t" /* target->r11 */ \
1797 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1798 "mr %0,3" \
1799 : /*out*/ "=r" (_res) \
1800 : /*in*/ "r" (&_argvec[0]) \
1801 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1802 ); \
1803 lval = (__typeof__(lval)) _res; \
1804 } while (0)
1805
1806#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1807 do { \
1808 volatile OrigFn _orig = (orig); \
1809 volatile unsigned long _argvec[5]; \
1810 volatile unsigned long _res; \
1811 _argvec[0] = (unsigned long)_orig.nraddr; \
1812 _argvec[1] = (unsigned long)arg1; \
1813 _argvec[2] = (unsigned long)arg2; \
1814 _argvec[3] = (unsigned long)arg3; \
1815 _argvec[4] = (unsigned long)arg4; \
1816 __asm__ volatile( \
1817 "mr 11,%1\n\t" \
1818 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1819 "lwz 4,8(11)\n\t" \
1820 "lwz 5,12(11)\n\t" \
1821 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1822 "lwz 11,0(11)\n\t" /* target->r11 */ \
1823 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1824 "mr %0,3" \
1825 : /*out*/ "=r" (_res) \
1826 : /*in*/ "r" (&_argvec[0]) \
1827 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1828 ); \
1829 lval = (__typeof__(lval)) _res; \
1830 } while (0)
1831
1832#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1833 do { \
1834 volatile OrigFn _orig = (orig); \
1835 volatile unsigned long _argvec[6]; \
1836 volatile unsigned long _res; \
1837 _argvec[0] = (unsigned long)_orig.nraddr; \
1838 _argvec[1] = (unsigned long)arg1; \
1839 _argvec[2] = (unsigned long)arg2; \
1840 _argvec[3] = (unsigned long)arg3; \
1841 _argvec[4] = (unsigned long)arg4; \
1842 _argvec[5] = (unsigned long)arg5; \
1843 __asm__ volatile( \
1844 "mr 11,%1\n\t" \
1845 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1846 "lwz 4,8(11)\n\t" \
1847 "lwz 5,12(11)\n\t" \
1848 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1849 "lwz 7,20(11)\n\t" \
1850 "lwz 11,0(11)\n\t" /* target->r11 */ \
1851 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1852 "mr %0,3" \
1853 : /*out*/ "=r" (_res) \
1854 : /*in*/ "r" (&_argvec[0]) \
1855 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1856 ); \
1857 lval = (__typeof__(lval)) _res; \
1858 } while (0)
1859
1860#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1861 do { \
1862 volatile OrigFn _orig = (orig); \
1863 volatile unsigned long _argvec[7]; \
1864 volatile unsigned long _res; \
1865 _argvec[0] = (unsigned long)_orig.nraddr; \
1866 _argvec[1] = (unsigned long)arg1; \
1867 _argvec[2] = (unsigned long)arg2; \
1868 _argvec[3] = (unsigned long)arg3; \
1869 _argvec[4] = (unsigned long)arg4; \
1870 _argvec[5] = (unsigned long)arg5; \
1871 _argvec[6] = (unsigned long)arg6; \
1872 __asm__ volatile( \
1873 "mr 11,%1\n\t" \
1874 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1875 "lwz 4,8(11)\n\t" \
1876 "lwz 5,12(11)\n\t" \
1877 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1878 "lwz 7,20(11)\n\t" \
1879 "lwz 8,24(11)\n\t" \
1880 "lwz 11,0(11)\n\t" /* target->r11 */ \
1881 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1882 "mr %0,3" \
1883 : /*out*/ "=r" (_res) \
1884 : /*in*/ "r" (&_argvec[0]) \
1885 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1886 ); \
1887 lval = (__typeof__(lval)) _res; \
1888 } while (0)
1889
1890#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1891 arg7) \
1892 do { \
1893 volatile OrigFn _orig = (orig); \
1894 volatile unsigned long _argvec[8]; \
1895 volatile unsigned long _res; \
1896 _argvec[0] = (unsigned long)_orig.nraddr; \
1897 _argvec[1] = (unsigned long)arg1; \
1898 _argvec[2] = (unsigned long)arg2; \
1899 _argvec[3] = (unsigned long)arg3; \
1900 _argvec[4] = (unsigned long)arg4; \
1901 _argvec[5] = (unsigned long)arg5; \
1902 _argvec[6] = (unsigned long)arg6; \
1903 _argvec[7] = (unsigned long)arg7; \
1904 __asm__ volatile( \
1905 "mr 11,%1\n\t" \
1906 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1907 "lwz 4,8(11)\n\t" \
1908 "lwz 5,12(11)\n\t" \
1909 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1910 "lwz 7,20(11)\n\t" \
1911 "lwz 8,24(11)\n\t" \
1912 "lwz 9,28(11)\n\t" \
1913 "lwz 11,0(11)\n\t" /* target->r11 */ \
1914 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1915 "mr %0,3" \
1916 : /*out*/ "=r" (_res) \
1917 : /*in*/ "r" (&_argvec[0]) \
1918 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1919 ); \
1920 lval = (__typeof__(lval)) _res; \
1921 } while (0)
1922
1923#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1924 arg7,arg8) \
1925 do { \
1926 volatile OrigFn _orig = (orig); \
1927 volatile unsigned long _argvec[9]; \
1928 volatile unsigned long _res; \
1929 _argvec[0] = (unsigned long)_orig.nraddr; \
1930 _argvec[1] = (unsigned long)arg1; \
1931 _argvec[2] = (unsigned long)arg2; \
1932 _argvec[3] = (unsigned long)arg3; \
1933 _argvec[4] = (unsigned long)arg4; \
1934 _argvec[5] = (unsigned long)arg5; \
1935 _argvec[6] = (unsigned long)arg6; \
1936 _argvec[7] = (unsigned long)arg7; \
1937 _argvec[8] = (unsigned long)arg8; \
1938 __asm__ volatile( \
1939 "mr 11,%1\n\t" \
1940 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1941 "lwz 4,8(11)\n\t" \
1942 "lwz 5,12(11)\n\t" \
1943 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1944 "lwz 7,20(11)\n\t" \
1945 "lwz 8,24(11)\n\t" \
1946 "lwz 9,28(11)\n\t" \
1947 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1948 "lwz 11,0(11)\n\t" /* target->r11 */ \
1949 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1950 "mr %0,3" \
1951 : /*out*/ "=r" (_res) \
1952 : /*in*/ "r" (&_argvec[0]) \
1953 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1954 ); \
1955 lval = (__typeof__(lval)) _res; \
1956 } while (0)
1957
1958#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1959 arg7,arg8,arg9) \
1960 do { \
1961 volatile OrigFn _orig = (orig); \
1962 volatile unsigned long _argvec[10]; \
1963 volatile unsigned long _res; \
1964 _argvec[0] = (unsigned long)_orig.nraddr; \
1965 _argvec[1] = (unsigned long)arg1; \
1966 _argvec[2] = (unsigned long)arg2; \
1967 _argvec[3] = (unsigned long)arg3; \
1968 _argvec[4] = (unsigned long)arg4; \
1969 _argvec[5] = (unsigned long)arg5; \
1970 _argvec[6] = (unsigned long)arg6; \
1971 _argvec[7] = (unsigned long)arg7; \
1972 _argvec[8] = (unsigned long)arg8; \
1973 _argvec[9] = (unsigned long)arg9; \
1974 __asm__ volatile( \
1975 "mr 11,%1\n\t" \
1976 "addi 1,1,-16\n\t" \
1977 /* arg9 */ \
1978 "lwz 3,36(11)\n\t" \
1979 "stw 3,8(1)\n\t" \
1980 /* args1-8 */ \
1981 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1982 "lwz 4,8(11)\n\t" \
1983 "lwz 5,12(11)\n\t" \
1984 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1985 "lwz 7,20(11)\n\t" \
1986 "lwz 8,24(11)\n\t" \
1987 "lwz 9,28(11)\n\t" \
1988 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1989 "lwz 11,0(11)\n\t" /* target->r11 */ \
1990 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1991 "addi 1,1,16\n\t" \
1992 "mr %0,3" \
1993 : /*out*/ "=r" (_res) \
1994 : /*in*/ "r" (&_argvec[0]) \
1995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1996 ); \
1997 lval = (__typeof__(lval)) _res; \
1998 } while (0)
1999
2000#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2001 arg7,arg8,arg9,arg10) \
2002 do { \
2003 volatile OrigFn _orig = (orig); \
2004 volatile unsigned long _argvec[11]; \
2005 volatile unsigned long _res; \
2006 _argvec[0] = (unsigned long)_orig.nraddr; \
2007 _argvec[1] = (unsigned long)arg1; \
2008 _argvec[2] = (unsigned long)arg2; \
2009 _argvec[3] = (unsigned long)arg3; \
2010 _argvec[4] = (unsigned long)arg4; \
2011 _argvec[5] = (unsigned long)arg5; \
2012 _argvec[6] = (unsigned long)arg6; \
2013 _argvec[7] = (unsigned long)arg7; \
2014 _argvec[8] = (unsigned long)arg8; \
2015 _argvec[9] = (unsigned long)arg9; \
2016 _argvec[10] = (unsigned long)arg10; \
2017 __asm__ volatile( \
2018 "mr 11,%1\n\t" \
2019 "addi 1,1,-16\n\t" \
2020 /* arg10 */ \
2021 "lwz 3,40(11)\n\t" \
2022 "stw 3,12(1)\n\t" \
2023 /* arg9 */ \
2024 "lwz 3,36(11)\n\t" \
2025 "stw 3,8(1)\n\t" \
2026 /* args1-8 */ \
2027 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2028 "lwz 4,8(11)\n\t" \
2029 "lwz 5,12(11)\n\t" \
2030 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2031 "lwz 7,20(11)\n\t" \
2032 "lwz 8,24(11)\n\t" \
2033 "lwz 9,28(11)\n\t" \
2034 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2035 "lwz 11,0(11)\n\t" /* target->r11 */ \
2036 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2037 "addi 1,1,16\n\t" \
2038 "mr %0,3" \
2039 : /*out*/ "=r" (_res) \
2040 : /*in*/ "r" (&_argvec[0]) \
2041 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2042 ); \
2043 lval = (__typeof__(lval)) _res; \
2044 } while (0)
2045
2046#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2047 arg7,arg8,arg9,arg10,arg11) \
2048 do { \
2049 volatile OrigFn _orig = (orig); \
2050 volatile unsigned long _argvec[12]; \
2051 volatile unsigned long _res; \
2052 _argvec[0] = (unsigned long)_orig.nraddr; \
2053 _argvec[1] = (unsigned long)arg1; \
2054 _argvec[2] = (unsigned long)arg2; \
2055 _argvec[3] = (unsigned long)arg3; \
2056 _argvec[4] = (unsigned long)arg4; \
2057 _argvec[5] = (unsigned long)arg5; \
2058 _argvec[6] = (unsigned long)arg6; \
2059 _argvec[7] = (unsigned long)arg7; \
2060 _argvec[8] = (unsigned long)arg8; \
2061 _argvec[9] = (unsigned long)arg9; \
2062 _argvec[10] = (unsigned long)arg10; \
2063 _argvec[11] = (unsigned long)arg11; \
2064 __asm__ volatile( \
2065 "mr 11,%1\n\t" \
2066 "addi 1,1,-32\n\t" \
2067 /* arg11 */ \
2068 "lwz 3,44(11)\n\t" \
2069 "stw 3,16(1)\n\t" \
2070 /* arg10 */ \
2071 "lwz 3,40(11)\n\t" \
2072 "stw 3,12(1)\n\t" \
2073 /* arg9 */ \
2074 "lwz 3,36(11)\n\t" \
2075 "stw 3,8(1)\n\t" \
2076 /* args1-8 */ \
2077 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2078 "lwz 4,8(11)\n\t" \
2079 "lwz 5,12(11)\n\t" \
2080 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2081 "lwz 7,20(11)\n\t" \
2082 "lwz 8,24(11)\n\t" \
2083 "lwz 9,28(11)\n\t" \
2084 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2085 "lwz 11,0(11)\n\t" /* target->r11 */ \
2086 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2087 "addi 1,1,32\n\t" \
2088 "mr %0,3" \
2089 : /*out*/ "=r" (_res) \
2090 : /*in*/ "r" (&_argvec[0]) \
2091 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2092 ); \
2093 lval = (__typeof__(lval)) _res; \
2094 } while (0)
2095
2096#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2097 arg7,arg8,arg9,arg10,arg11,arg12) \
2098 do { \
2099 volatile OrigFn _orig = (orig); \
2100 volatile unsigned long _argvec[13]; \
2101 volatile unsigned long _res; \
2102 _argvec[0] = (unsigned long)_orig.nraddr; \
2103 _argvec[1] = (unsigned long)arg1; \
2104 _argvec[2] = (unsigned long)arg2; \
2105 _argvec[3] = (unsigned long)arg3; \
2106 _argvec[4] = (unsigned long)arg4; \
2107 _argvec[5] = (unsigned long)arg5; \
2108 _argvec[6] = (unsigned long)arg6; \
2109 _argvec[7] = (unsigned long)arg7; \
2110 _argvec[8] = (unsigned long)arg8; \
2111 _argvec[9] = (unsigned long)arg9; \
2112 _argvec[10] = (unsigned long)arg10; \
2113 _argvec[11] = (unsigned long)arg11; \
2114 _argvec[12] = (unsigned long)arg12; \
2115 __asm__ volatile( \
2116 "mr 11,%1\n\t" \
2117 "addi 1,1,-32\n\t" \
2118 /* arg12 */ \
2119 "lwz 3,48(11)\n\t" \
2120 "stw 3,20(1)\n\t" \
2121 /* arg11 */ \
2122 "lwz 3,44(11)\n\t" \
2123 "stw 3,16(1)\n\t" \
2124 /* arg10 */ \
2125 "lwz 3,40(11)\n\t" \
2126 "stw 3,12(1)\n\t" \
2127 /* arg9 */ \
2128 "lwz 3,36(11)\n\t" \
2129 "stw 3,8(1)\n\t" \
2130 /* args1-8 */ \
2131 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2132 "lwz 4,8(11)\n\t" \
2133 "lwz 5,12(11)\n\t" \
2134 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2135 "lwz 7,20(11)\n\t" \
2136 "lwz 8,24(11)\n\t" \
2137 "lwz 9,28(11)\n\t" \
2138 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2139 "lwz 11,0(11)\n\t" /* target->r11 */ \
2140 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2141 "addi 1,1,32\n\t" \
2142 "mr %0,3" \
2143 : /*out*/ "=r" (_res) \
2144 : /*in*/ "r" (&_argvec[0]) \
2145 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2146 ); \
2147 lval = (__typeof__(lval)) _res; \
2148 } while (0)
2149
sewardjf5c1a7f2006-10-17 01:32:48 +00002150#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002151
sewardjf5c1a7f2006-10-17 01:32:48 +00002152/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002153
sewardjf5c1a7f2006-10-17 01:32:48 +00002154#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002155
2156/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2157
2158/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002159#define __CALLER_SAVED_REGS \
2160 "lr", "ctr", "xer", \
2161 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2162 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2163 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002164
2165/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2166 long) == 8. */
2167
sewardjd68ac3e2006-01-20 14:31:57 +00002168#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002169 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002170 volatile OrigFn _orig = (orig); \
2171 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002172 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002173 /* _argvec[0] holds current r2 across the call */ \
2174 _argvec[1] = (unsigned long)_orig.r2; \
2175 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002176 __asm__ volatile( \
2177 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002178 "std 2,-16(11)\n\t" /* save tocptr */ \
2179 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2180 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002181 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2182 "mr 11,%1\n\t" \
2183 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002184 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002185 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002186 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002187 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2188 ); \
2189 lval = (__typeof__(lval)) _res; \
2190 } while (0)
2191
sewardjd68ac3e2006-01-20 14:31:57 +00002192#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002193 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002194 volatile OrigFn _orig = (orig); \
2195 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002196 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002197 /* _argvec[0] holds current r2 across the call */ \
2198 _argvec[1] = (unsigned long)_orig.r2; \
2199 _argvec[2] = (unsigned long)_orig.nraddr; \
2200 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002201 __asm__ volatile( \
2202 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002203 "std 2,-16(11)\n\t" /* save tocptr */ \
2204 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2205 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2206 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002207 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2208 "mr 11,%1\n\t" \
2209 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002210 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002211 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002212 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002213 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2214 ); \
2215 lval = (__typeof__(lval)) _res; \
2216 } while (0)
2217
sewardjd68ac3e2006-01-20 14:31:57 +00002218#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002219 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002220 volatile OrigFn _orig = (orig); \
2221 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002222 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002223 /* _argvec[0] holds current r2 across the call */ \
2224 _argvec[1] = (unsigned long)_orig.r2; \
2225 _argvec[2] = (unsigned long)_orig.nraddr; \
2226 _argvec[2+1] = (unsigned long)arg1; \
2227 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002228 __asm__ volatile( \
2229 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002230 "std 2,-16(11)\n\t" /* save tocptr */ \
2231 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2232 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002233 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002234 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002235 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2236 "mr 11,%1\n\t" \
2237 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002238 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002239 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002240 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002241 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2242 ); \
2243 lval = (__typeof__(lval)) _res; \
2244 } while (0)
2245
sewardjcd636392006-03-12 16:48:14 +00002246#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2247 do { \
2248 volatile OrigFn _orig = (orig); \
2249 volatile unsigned long _argvec[3+3]; \
2250 volatile unsigned long _res; \
2251 /* _argvec[0] holds current r2 across the call */ \
2252 _argvec[1] = (unsigned long)_orig.r2; \
2253 _argvec[2] = (unsigned long)_orig.nraddr; \
2254 _argvec[2+1] = (unsigned long)arg1; \
2255 _argvec[2+2] = (unsigned long)arg2; \
2256 _argvec[2+3] = (unsigned long)arg3; \
2257 __asm__ volatile( \
2258 "mr 11,%1\n\t" \
2259 "std 2,-16(11)\n\t" /* save tocptr */ \
2260 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2261 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2262 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2263 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2264 "ld 11, 0(11)\n\t" /* target->r11 */ \
2265 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2266 "mr 11,%1\n\t" \
2267 "mr %0,3\n\t" \
2268 "ld 2,-16(11)" /* restore tocptr */ \
2269 : /*out*/ "=r" (_res) \
2270 : /*in*/ "r" (&_argvec[2]) \
2271 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2272 ); \
2273 lval = (__typeof__(lval)) _res; \
2274 } while (0)
2275
2276#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2277 do { \
2278 volatile OrigFn _orig = (orig); \
2279 volatile unsigned long _argvec[3+4]; \
2280 volatile unsigned long _res; \
2281 /* _argvec[0] holds current r2 across the call */ \
2282 _argvec[1] = (unsigned long)_orig.r2; \
2283 _argvec[2] = (unsigned long)_orig.nraddr; \
2284 _argvec[2+1] = (unsigned long)arg1; \
2285 _argvec[2+2] = (unsigned long)arg2; \
2286 _argvec[2+3] = (unsigned long)arg3; \
2287 _argvec[2+4] = (unsigned long)arg4; \
2288 __asm__ volatile( \
2289 "mr 11,%1\n\t" \
2290 "std 2,-16(11)\n\t" /* save tocptr */ \
2291 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2292 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2293 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2294 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2295 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2296 "ld 11, 0(11)\n\t" /* target->r11 */ \
2297 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2298 "mr 11,%1\n\t" \
2299 "mr %0,3\n\t" \
2300 "ld 2,-16(11)" /* restore tocptr */ \
2301 : /*out*/ "=r" (_res) \
2302 : /*in*/ "r" (&_argvec[2]) \
2303 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2304 ); \
2305 lval = (__typeof__(lval)) _res; \
2306 } while (0)
2307
2308#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2309 do { \
2310 volatile OrigFn _orig = (orig); \
2311 volatile unsigned long _argvec[3+5]; \
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 __asm__ volatile( \
2322 "mr 11,%1\n\t" \
2323 "std 2,-16(11)\n\t" /* save tocptr */ \
2324 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2325 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2326 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2327 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2328 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2329 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2330 "ld 11, 0(11)\n\t" /* target->r11 */ \
2331 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2332 "mr 11,%1\n\t" \
2333 "mr %0,3\n\t" \
2334 "ld 2,-16(11)" /* restore tocptr */ \
2335 : /*out*/ "=r" (_res) \
2336 : /*in*/ "r" (&_argvec[2]) \
2337 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2338 ); \
2339 lval = (__typeof__(lval)) _res; \
2340 } while (0)
2341
2342#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2343 do { \
2344 volatile OrigFn _orig = (orig); \
2345 volatile unsigned long _argvec[3+6]; \
2346 volatile unsigned long _res; \
2347 /* _argvec[0] holds current r2 across the call */ \
2348 _argvec[1] = (unsigned long)_orig.r2; \
2349 _argvec[2] = (unsigned long)_orig.nraddr; \
2350 _argvec[2+1] = (unsigned long)arg1; \
2351 _argvec[2+2] = (unsigned long)arg2; \
2352 _argvec[2+3] = (unsigned long)arg3; \
2353 _argvec[2+4] = (unsigned long)arg4; \
2354 _argvec[2+5] = (unsigned long)arg5; \
2355 _argvec[2+6] = (unsigned long)arg6; \
2356 __asm__ volatile( \
2357 "mr 11,%1\n\t" \
2358 "std 2,-16(11)\n\t" /* save tocptr */ \
2359 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2360 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2361 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2362 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2363 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2364 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2365 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2366 "ld 11, 0(11)\n\t" /* target->r11 */ \
2367 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2368 "mr 11,%1\n\t" \
2369 "mr %0,3\n\t" \
2370 "ld 2,-16(11)" /* restore tocptr */ \
2371 : /*out*/ "=r" (_res) \
2372 : /*in*/ "r" (&_argvec[2]) \
2373 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2374 ); \
2375 lval = (__typeof__(lval)) _res; \
2376 } while (0)
2377
2378#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2379 arg7) \
2380 do { \
2381 volatile OrigFn _orig = (orig); \
2382 volatile unsigned long _argvec[3+7]; \
2383 volatile unsigned long _res; \
2384 /* _argvec[0] holds current r2 across the call */ \
2385 _argvec[1] = (unsigned long)_orig.r2; \
2386 _argvec[2] = (unsigned long)_orig.nraddr; \
2387 _argvec[2+1] = (unsigned long)arg1; \
2388 _argvec[2+2] = (unsigned long)arg2; \
2389 _argvec[2+3] = (unsigned long)arg3; \
2390 _argvec[2+4] = (unsigned long)arg4; \
2391 _argvec[2+5] = (unsigned long)arg5; \
2392 _argvec[2+6] = (unsigned long)arg6; \
2393 _argvec[2+7] = (unsigned long)arg7; \
2394 __asm__ volatile( \
2395 "mr 11,%1\n\t" \
2396 "std 2,-16(11)\n\t" /* save tocptr */ \
2397 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2398 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2399 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2400 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2401 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2402 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2403 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2404 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2405 "ld 11, 0(11)\n\t" /* target->r11 */ \
2406 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2407 "mr 11,%1\n\t" \
2408 "mr %0,3\n\t" \
2409 "ld 2,-16(11)" /* restore tocptr */ \
2410 : /*out*/ "=r" (_res) \
2411 : /*in*/ "r" (&_argvec[2]) \
2412 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2413 ); \
2414 lval = (__typeof__(lval)) _res; \
2415 } while (0)
2416
2417#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2418 arg7,arg8) \
2419 do { \
2420 volatile OrigFn _orig = (orig); \
2421 volatile unsigned long _argvec[3+8]; \
2422 volatile unsigned long _res; \
2423 /* _argvec[0] holds current r2 across the call */ \
2424 _argvec[1] = (unsigned long)_orig.r2; \
2425 _argvec[2] = (unsigned long)_orig.nraddr; \
2426 _argvec[2+1] = (unsigned long)arg1; \
2427 _argvec[2+2] = (unsigned long)arg2; \
2428 _argvec[2+3] = (unsigned long)arg3; \
2429 _argvec[2+4] = (unsigned long)arg4; \
2430 _argvec[2+5] = (unsigned long)arg5; \
2431 _argvec[2+6] = (unsigned long)arg6; \
2432 _argvec[2+7] = (unsigned long)arg7; \
2433 _argvec[2+8] = (unsigned long)arg8; \
2434 __asm__ volatile( \
2435 "mr 11,%1\n\t" \
2436 "std 2,-16(11)\n\t" /* save tocptr */ \
2437 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2438 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2439 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2440 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2441 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2442 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2443 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2444 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2445 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2446 "ld 11, 0(11)\n\t" /* target->r11 */ \
2447 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2448 "mr 11,%1\n\t" \
2449 "mr %0,3\n\t" \
2450 "ld 2,-16(11)" /* restore tocptr */ \
2451 : /*out*/ "=r" (_res) \
2452 : /*in*/ "r" (&_argvec[2]) \
2453 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2454 ); \
2455 lval = (__typeof__(lval)) _res; \
2456 } while (0)
2457
2458#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2459 arg7,arg8,arg9) \
2460 do { \
2461 volatile OrigFn _orig = (orig); \
2462 volatile unsigned long _argvec[3+9]; \
2463 volatile unsigned long _res; \
2464 /* _argvec[0] holds current r2 across the call */ \
2465 _argvec[1] = (unsigned long)_orig.r2; \
2466 _argvec[2] = (unsigned long)_orig.nraddr; \
2467 _argvec[2+1] = (unsigned long)arg1; \
2468 _argvec[2+2] = (unsigned long)arg2; \
2469 _argvec[2+3] = (unsigned long)arg3; \
2470 _argvec[2+4] = (unsigned long)arg4; \
2471 _argvec[2+5] = (unsigned long)arg5; \
2472 _argvec[2+6] = (unsigned long)arg6; \
2473 _argvec[2+7] = (unsigned long)arg7; \
2474 _argvec[2+8] = (unsigned long)arg8; \
2475 _argvec[2+9] = (unsigned long)arg9; \
2476 __asm__ volatile( \
2477 "mr 11,%1\n\t" \
2478 "std 2,-16(11)\n\t" /* save tocptr */ \
2479 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2480 "addi 1,1,-128\n\t" /* expand stack frame */ \
2481 /* arg9 */ \
2482 "ld 3,72(11)\n\t" \
2483 "std 3,112(1)\n\t" \
2484 /* args1-8 */ \
2485 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2486 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2487 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2488 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2489 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2490 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2491 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2492 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2493 "ld 11, 0(11)\n\t" /* target->r11 */ \
2494 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2495 "mr 11,%1\n\t" \
2496 "mr %0,3\n\t" \
2497 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2498 "addi 1,1,128" /* restore frame */ \
2499 : /*out*/ "=r" (_res) \
2500 : /*in*/ "r" (&_argvec[2]) \
2501 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2502 ); \
2503 lval = (__typeof__(lval)) _res; \
2504 } while (0)
2505
2506#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2507 arg7,arg8,arg9,arg10) \
2508 do { \
2509 volatile OrigFn _orig = (orig); \
2510 volatile unsigned long _argvec[3+10]; \
2511 volatile unsigned long _res; \
2512 /* _argvec[0] holds current r2 across the call */ \
2513 _argvec[1] = (unsigned long)_orig.r2; \
2514 _argvec[2] = (unsigned long)_orig.nraddr; \
2515 _argvec[2+1] = (unsigned long)arg1; \
2516 _argvec[2+2] = (unsigned long)arg2; \
2517 _argvec[2+3] = (unsigned long)arg3; \
2518 _argvec[2+4] = (unsigned long)arg4; \
2519 _argvec[2+5] = (unsigned long)arg5; \
2520 _argvec[2+6] = (unsigned long)arg6; \
2521 _argvec[2+7] = (unsigned long)arg7; \
2522 _argvec[2+8] = (unsigned long)arg8; \
2523 _argvec[2+9] = (unsigned long)arg9; \
2524 _argvec[2+10] = (unsigned long)arg10; \
2525 __asm__ volatile( \
2526 "mr 11,%1\n\t" \
2527 "std 2,-16(11)\n\t" /* save tocptr */ \
2528 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2529 "addi 1,1,-128\n\t" /* expand stack frame */ \
2530 /* arg10 */ \
2531 "ld 3,80(11)\n\t" \
2532 "std 3,120(1)\n\t" \
2533 /* arg9 */ \
2534 "ld 3,72(11)\n\t" \
2535 "std 3,112(1)\n\t" \
2536 /* args1-8 */ \
2537 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2538 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2539 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2540 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2541 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2542 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2543 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2544 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2545 "ld 11, 0(11)\n\t" /* target->r11 */ \
2546 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2547 "mr 11,%1\n\t" \
2548 "mr %0,3\n\t" \
2549 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2550 "addi 1,1,128" /* restore frame */ \
2551 : /*out*/ "=r" (_res) \
2552 : /*in*/ "r" (&_argvec[2]) \
2553 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2554 ); \
2555 lval = (__typeof__(lval)) _res; \
2556 } while (0)
2557
2558#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2559 arg7,arg8,arg9,arg10,arg11) \
2560 do { \
2561 volatile OrigFn _orig = (orig); \
2562 volatile unsigned long _argvec[3+11]; \
2563 volatile unsigned long _res; \
2564 /* _argvec[0] holds current r2 across the call */ \
2565 _argvec[1] = (unsigned long)_orig.r2; \
2566 _argvec[2] = (unsigned long)_orig.nraddr; \
2567 _argvec[2+1] = (unsigned long)arg1; \
2568 _argvec[2+2] = (unsigned long)arg2; \
2569 _argvec[2+3] = (unsigned long)arg3; \
2570 _argvec[2+4] = (unsigned long)arg4; \
2571 _argvec[2+5] = (unsigned long)arg5; \
2572 _argvec[2+6] = (unsigned long)arg6; \
2573 _argvec[2+7] = (unsigned long)arg7; \
2574 _argvec[2+8] = (unsigned long)arg8; \
2575 _argvec[2+9] = (unsigned long)arg9; \
2576 _argvec[2+10] = (unsigned long)arg10; \
2577 _argvec[2+11] = (unsigned long)arg11; \
2578 __asm__ volatile( \
2579 "mr 11,%1\n\t" \
2580 "std 2,-16(11)\n\t" /* save tocptr */ \
2581 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2582 "addi 1,1,-144\n\t" /* expand stack frame */ \
2583 /* arg11 */ \
2584 "ld 3,88(11)\n\t" \
2585 "std 3,128(1)\n\t" \
2586 /* arg10 */ \
2587 "ld 3,80(11)\n\t" \
2588 "std 3,120(1)\n\t" \
2589 /* arg9 */ \
2590 "ld 3,72(11)\n\t" \
2591 "std 3,112(1)\n\t" \
2592 /* args1-8 */ \
2593 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2594 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2595 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2596 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2597 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2598 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2599 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2600 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2601 "ld 11, 0(11)\n\t" /* target->r11 */ \
2602 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2603 "mr 11,%1\n\t" \
2604 "mr %0,3\n\t" \
2605 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2606 "addi 1,1,144" /* restore frame */ \
2607 : /*out*/ "=r" (_res) \
2608 : /*in*/ "r" (&_argvec[2]) \
2609 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2610 ); \
2611 lval = (__typeof__(lval)) _res; \
2612 } while (0)
2613
2614#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2615 arg7,arg8,arg9,arg10,arg11,arg12) \
2616 do { \
2617 volatile OrigFn _orig = (orig); \
2618 volatile unsigned long _argvec[3+12]; \
2619 volatile unsigned long _res; \
2620 /* _argvec[0] holds current r2 across the call */ \
2621 _argvec[1] = (unsigned long)_orig.r2; \
2622 _argvec[2] = (unsigned long)_orig.nraddr; \
2623 _argvec[2+1] = (unsigned long)arg1; \
2624 _argvec[2+2] = (unsigned long)arg2; \
2625 _argvec[2+3] = (unsigned long)arg3; \
2626 _argvec[2+4] = (unsigned long)arg4; \
2627 _argvec[2+5] = (unsigned long)arg5; \
2628 _argvec[2+6] = (unsigned long)arg6; \
2629 _argvec[2+7] = (unsigned long)arg7; \
2630 _argvec[2+8] = (unsigned long)arg8; \
2631 _argvec[2+9] = (unsigned long)arg9; \
2632 _argvec[2+10] = (unsigned long)arg10; \
2633 _argvec[2+11] = (unsigned long)arg11; \
2634 _argvec[2+12] = (unsigned long)arg12; \
2635 __asm__ volatile( \
2636 "mr 11,%1\n\t" \
2637 "std 2,-16(11)\n\t" /* save tocptr */ \
2638 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2639 "addi 1,1,-144\n\t" /* expand stack frame */ \
2640 /* arg12 */ \
2641 "ld 3,96(11)\n\t" \
2642 "std 3,136(1)\n\t" \
2643 /* arg11 */ \
2644 "ld 3,88(11)\n\t" \
2645 "std 3,128(1)\n\t" \
2646 /* arg10 */ \
2647 "ld 3,80(11)\n\t" \
2648 "std 3,120(1)\n\t" \
2649 /* arg9 */ \
2650 "ld 3,72(11)\n\t" \
2651 "std 3,112(1)\n\t" \
2652 /* args1-8 */ \
2653 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2654 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2655 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2656 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2657 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2658 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2659 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2660 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2661 "ld 11, 0(11)\n\t" /* target->r11 */ \
2662 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2663 "mr 11,%1\n\t" \
2664 "mr %0,3\n\t" \
2665 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2666 "addi 1,1,144" /* restore frame */ \
2667 : /*out*/ "=r" (_res) \
2668 : /*in*/ "r" (&_argvec[2]) \
2669 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2670 ); \
2671 lval = (__typeof__(lval)) _res; \
2672 } while (0)
2673
sewardjf5c1a7f2006-10-17 01:32:48 +00002674#endif /* PLAT_ppc64_linux */
2675
sewardj59570ff2010-01-01 11:59:33 +00002676/* ------------------------- arm-linux ------------------------- */
2677
2678#if defined(PLAT_arm_linux)
2679
2680/* These regs are trashed by the hidden call. */
2681#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2682
2683/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2684 long) == 4. */
2685
2686#define CALL_FN_W_v(lval, orig) \
2687 do { \
2688 volatile OrigFn _orig = (orig); \
2689 volatile unsigned long _argvec[1]; \
2690 volatile unsigned long _res; \
2691 _argvec[0] = (unsigned long)_orig.nraddr; \
2692 __asm__ volatile( \
2693 "ldr r4, [%1] \n\t" /* target->r4 */ \
2694 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2695 "mov %0, r0\n" \
2696 : /*out*/ "=r" (_res) \
2697 : /*in*/ "0" (&_argvec[0]) \
2698 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2699 ); \
2700 lval = (__typeof__(lval)) _res; \
2701 } while (0)
2702
2703#define CALL_FN_W_W(lval, orig, arg1) \
2704 do { \
2705 volatile OrigFn _orig = (orig); \
2706 volatile unsigned long _argvec[2]; \
2707 volatile unsigned long _res; \
2708 _argvec[0] = (unsigned long)_orig.nraddr; \
2709 _argvec[1] = (unsigned long)(arg1); \
2710 __asm__ volatile( \
2711 "ldr r0, [%1, #4] \n\t" \
2712 "ldr r4, [%1] \n\t" /* target->r4 */ \
2713 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2714 "mov %0, r0\n" \
2715 : /*out*/ "=r" (_res) \
2716 : /*in*/ "0" (&_argvec[0]) \
2717 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2718 ); \
2719 lval = (__typeof__(lval)) _res; \
2720 } while (0)
2721
2722#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2723 do { \
2724 volatile OrigFn _orig = (orig); \
2725 volatile unsigned long _argvec[3]; \
2726 volatile unsigned long _res; \
2727 _argvec[0] = (unsigned long)_orig.nraddr; \
2728 _argvec[1] = (unsigned long)(arg1); \
2729 _argvec[2] = (unsigned long)(arg2); \
2730 __asm__ volatile( \
2731 "ldr r0, [%1, #4] \n\t" \
2732 "ldr r1, [%1, #8] \n\t" \
2733 "ldr r4, [%1] \n\t" /* target->r4 */ \
2734 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2735 "mov %0, r0\n" \
2736 : /*out*/ "=r" (_res) \
2737 : /*in*/ "0" (&_argvec[0]) \
2738 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2739 ); \
2740 lval = (__typeof__(lval)) _res; \
2741 } while (0)
2742
2743#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2744 do { \
2745 volatile OrigFn _orig = (orig); \
2746 volatile unsigned long _argvec[4]; \
2747 volatile unsigned long _res; \
2748 _argvec[0] = (unsigned long)_orig.nraddr; \
2749 _argvec[1] = (unsigned long)(arg1); \
2750 _argvec[2] = (unsigned long)(arg2); \
2751 _argvec[3] = (unsigned long)(arg3); \
2752 __asm__ volatile( \
2753 "ldr r0, [%1, #4] \n\t" \
2754 "ldr r1, [%1, #8] \n\t" \
2755 "ldr r2, [%1, #12] \n\t" \
2756 "ldr r4, [%1] \n\t" /* target->r4 */ \
2757 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2758 "mov %0, r0\n" \
2759 : /*out*/ "=r" (_res) \
2760 : /*in*/ "0" (&_argvec[0]) \
2761 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2762 ); \
2763 lval = (__typeof__(lval)) _res; \
2764 } while (0)
2765
2766#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2767 do { \
2768 volatile OrigFn _orig = (orig); \
2769 volatile unsigned long _argvec[5]; \
2770 volatile unsigned long _res; \
2771 _argvec[0] = (unsigned long)_orig.nraddr; \
2772 _argvec[1] = (unsigned long)(arg1); \
2773 _argvec[2] = (unsigned long)(arg2); \
2774 _argvec[3] = (unsigned long)(arg3); \
2775 _argvec[4] = (unsigned long)(arg4); \
2776 __asm__ volatile( \
2777 "ldr r0, [%1, #4] \n\t" \
2778 "ldr r1, [%1, #8] \n\t" \
2779 "ldr r2, [%1, #12] \n\t" \
2780 "ldr r3, [%1, #16] \n\t" \
2781 "ldr r4, [%1] \n\t" /* target->r4 */ \
2782 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2783 "mov %0, r0" \
2784 : /*out*/ "=r" (_res) \
2785 : /*in*/ "0" (&_argvec[0]) \
2786 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2787 ); \
2788 lval = (__typeof__(lval)) _res; \
2789 } while (0)
2790
2791#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2792 do { \
2793 volatile OrigFn _orig = (orig); \
2794 volatile unsigned long _argvec[6]; \
2795 volatile unsigned long _res; \
2796 _argvec[0] = (unsigned long)_orig.nraddr; \
2797 _argvec[1] = (unsigned long)(arg1); \
2798 _argvec[2] = (unsigned long)(arg2); \
2799 _argvec[3] = (unsigned long)(arg3); \
2800 _argvec[4] = (unsigned long)(arg4); \
2801 _argvec[5] = (unsigned long)(arg5); \
2802 __asm__ volatile( \
2803 "ldr r0, [%1, #20] \n\t" \
2804 "push {r0} \n\t" \
2805 "ldr r0, [%1, #4] \n\t" \
2806 "ldr r1, [%1, #8] \n\t" \
2807 "ldr r2, [%1, #12] \n\t" \
2808 "ldr r3, [%1, #16] \n\t" \
2809 "ldr r4, [%1] \n\t" /* target->r4 */ \
2810 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2811 "add sp, sp, #4 \n\t" \
2812 "mov %0, r0" \
2813 : /*out*/ "=r" (_res) \
2814 : /*in*/ "0" (&_argvec[0]) \
2815 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2816 ); \
2817 lval = (__typeof__(lval)) _res; \
2818 } while (0)
2819
2820#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2821 do { \
2822 volatile OrigFn _orig = (orig); \
2823 volatile unsigned long _argvec[7]; \
2824 volatile unsigned long _res; \
2825 _argvec[0] = (unsigned long)_orig.nraddr; \
2826 _argvec[1] = (unsigned long)(arg1); \
2827 _argvec[2] = (unsigned long)(arg2); \
2828 _argvec[3] = (unsigned long)(arg3); \
2829 _argvec[4] = (unsigned long)(arg4); \
2830 _argvec[5] = (unsigned long)(arg5); \
2831 _argvec[6] = (unsigned long)(arg6); \
2832 __asm__ volatile( \
2833 "ldr r0, [%1, #20] \n\t" \
2834 "ldr r1, [%1, #24] \n\t" \
2835 "push {r0, r1} \n\t" \
2836 "ldr r0, [%1, #4] \n\t" \
2837 "ldr r1, [%1, #8] \n\t" \
2838 "ldr r2, [%1, #12] \n\t" \
2839 "ldr r3, [%1, #16] \n\t" \
2840 "ldr r4, [%1] \n\t" /* target->r4 */ \
2841 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2842 "add sp, sp, #8 \n\t" \
2843 "mov %0, r0" \
2844 : /*out*/ "=r" (_res) \
2845 : /*in*/ "0" (&_argvec[0]) \
2846 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2847 ); \
2848 lval = (__typeof__(lval)) _res; \
2849 } while (0)
2850
2851#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2852 arg7) \
2853 do { \
2854 volatile OrigFn _orig = (orig); \
2855 volatile unsigned long _argvec[8]; \
2856 volatile unsigned long _res; \
2857 _argvec[0] = (unsigned long)_orig.nraddr; \
2858 _argvec[1] = (unsigned long)(arg1); \
2859 _argvec[2] = (unsigned long)(arg2); \
2860 _argvec[3] = (unsigned long)(arg3); \
2861 _argvec[4] = (unsigned long)(arg4); \
2862 _argvec[5] = (unsigned long)(arg5); \
2863 _argvec[6] = (unsigned long)(arg6); \
2864 _argvec[7] = (unsigned long)(arg7); \
2865 __asm__ volatile( \
2866 "ldr r0, [%1, #20] \n\t" \
2867 "ldr r1, [%1, #24] \n\t" \
2868 "ldr r2, [%1, #28] \n\t" \
2869 "push {r0, r1, r2} \n\t" \
2870 "ldr r0, [%1, #4] \n\t" \
2871 "ldr r1, [%1, #8] \n\t" \
2872 "ldr r2, [%1, #12] \n\t" \
2873 "ldr r3, [%1, #16] \n\t" \
2874 "ldr r4, [%1] \n\t" /* target->r4 */ \
2875 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2876 "add sp, sp, #12 \n\t" \
2877 "mov %0, r0" \
2878 : /*out*/ "=r" (_res) \
2879 : /*in*/ "0" (&_argvec[0]) \
2880 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2881 ); \
2882 lval = (__typeof__(lval)) _res; \
2883 } while (0)
2884
2885#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2886 arg7,arg8) \
2887 do { \
2888 volatile OrigFn _orig = (orig); \
2889 volatile unsigned long _argvec[9]; \
2890 volatile unsigned long _res; \
2891 _argvec[0] = (unsigned long)_orig.nraddr; \
2892 _argvec[1] = (unsigned long)(arg1); \
2893 _argvec[2] = (unsigned long)(arg2); \
2894 _argvec[3] = (unsigned long)(arg3); \
2895 _argvec[4] = (unsigned long)(arg4); \
2896 _argvec[5] = (unsigned long)(arg5); \
2897 _argvec[6] = (unsigned long)(arg6); \
2898 _argvec[7] = (unsigned long)(arg7); \
2899 _argvec[8] = (unsigned long)(arg8); \
2900 __asm__ volatile( \
2901 "ldr r0, [%1, #20] \n\t" \
2902 "ldr r1, [%1, #24] \n\t" \
2903 "ldr r2, [%1, #28] \n\t" \
2904 "ldr r3, [%1, #32] \n\t" \
2905 "push {r0, r1, r2, r3} \n\t" \
2906 "ldr r0, [%1, #4] \n\t" \
2907 "ldr r1, [%1, #8] \n\t" \
2908 "ldr r2, [%1, #12] \n\t" \
2909 "ldr r3, [%1, #16] \n\t" \
2910 "ldr r4, [%1] \n\t" /* target->r4 */ \
2911 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2912 "add sp, sp, #16 \n\t" \
2913 "mov %0, r0" \
2914 : /*out*/ "=r" (_res) \
2915 : /*in*/ "0" (&_argvec[0]) \
2916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2917 ); \
2918 lval = (__typeof__(lval)) _res; \
2919 } while (0)
2920
2921#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2922 arg7,arg8,arg9) \
2923 do { \
2924 volatile OrigFn _orig = (orig); \
2925 volatile unsigned long _argvec[10]; \
2926 volatile unsigned long _res; \
2927 _argvec[0] = (unsigned long)_orig.nraddr; \
2928 _argvec[1] = (unsigned long)(arg1); \
2929 _argvec[2] = (unsigned long)(arg2); \
2930 _argvec[3] = (unsigned long)(arg3); \
2931 _argvec[4] = (unsigned long)(arg4); \
2932 _argvec[5] = (unsigned long)(arg5); \
2933 _argvec[6] = (unsigned long)(arg6); \
2934 _argvec[7] = (unsigned long)(arg7); \
2935 _argvec[8] = (unsigned long)(arg8); \
2936 _argvec[9] = (unsigned long)(arg9); \
2937 __asm__ volatile( \
2938 "ldr r0, [%1, #20] \n\t" \
2939 "ldr r1, [%1, #24] \n\t" \
2940 "ldr r2, [%1, #28] \n\t" \
2941 "ldr r3, [%1, #32] \n\t" \
2942 "ldr r4, [%1, #36] \n\t" \
2943 "push {r0, r1, r2, r3, r4} \n\t" \
2944 "ldr r0, [%1, #4] \n\t" \
2945 "ldr r1, [%1, #8] \n\t" \
2946 "ldr r2, [%1, #12] \n\t" \
2947 "ldr r3, [%1, #16] \n\t" \
2948 "ldr r4, [%1] \n\t" /* target->r4 */ \
2949 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2950 "add sp, sp, #20 \n\t" \
2951 "mov %0, r0" \
2952 : /*out*/ "=r" (_res) \
2953 : /*in*/ "0" (&_argvec[0]) \
2954 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2955 ); \
2956 lval = (__typeof__(lval)) _res; \
2957 } while (0)
2958
2959#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2960 arg7,arg8,arg9,arg10) \
2961 do { \
2962 volatile OrigFn _orig = (orig); \
2963 volatile unsigned long _argvec[11]; \
2964 volatile unsigned long _res; \
2965 _argvec[0] = (unsigned long)_orig.nraddr; \
2966 _argvec[1] = (unsigned long)(arg1); \
2967 _argvec[2] = (unsigned long)(arg2); \
2968 _argvec[3] = (unsigned long)(arg3); \
2969 _argvec[4] = (unsigned long)(arg4); \
2970 _argvec[5] = (unsigned long)(arg5); \
2971 _argvec[6] = (unsigned long)(arg6); \
2972 _argvec[7] = (unsigned long)(arg7); \
2973 _argvec[8] = (unsigned long)(arg8); \
2974 _argvec[9] = (unsigned long)(arg9); \
2975 _argvec[10] = (unsigned long)(arg10); \
2976 __asm__ volatile( \
2977 "ldr r0, [%1, #40] \n\t" \
2978 "push {r0} \n\t" \
2979 "ldr r0, [%1, #20] \n\t" \
2980 "ldr r1, [%1, #24] \n\t" \
2981 "ldr r2, [%1, #28] \n\t" \
2982 "ldr r3, [%1, #32] \n\t" \
2983 "ldr r4, [%1, #36] \n\t" \
2984 "push {r0, r1, r2, r3, r4} \n\t" \
2985 "ldr r0, [%1, #4] \n\t" \
2986 "ldr r1, [%1, #8] \n\t" \
2987 "ldr r2, [%1, #12] \n\t" \
2988 "ldr r3, [%1, #16] \n\t" \
2989 "ldr r4, [%1] \n\t" /* target->r4 */ \
2990 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2991 "add sp, sp, #24 \n\t" \
2992 "mov %0, r0" \
2993 : /*out*/ "=r" (_res) \
2994 : /*in*/ "0" (&_argvec[0]) \
2995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2996 ); \
2997 lval = (__typeof__(lval)) _res; \
2998 } while (0)
2999
3000#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3001 arg6,arg7,arg8,arg9,arg10, \
3002 arg11) \
3003 do { \
3004 volatile OrigFn _orig = (orig); \
3005 volatile unsigned long _argvec[12]; \
3006 volatile unsigned long _res; \
3007 _argvec[0] = (unsigned long)_orig.nraddr; \
3008 _argvec[1] = (unsigned long)(arg1); \
3009 _argvec[2] = (unsigned long)(arg2); \
3010 _argvec[3] = (unsigned long)(arg3); \
3011 _argvec[4] = (unsigned long)(arg4); \
3012 _argvec[5] = (unsigned long)(arg5); \
3013 _argvec[6] = (unsigned long)(arg6); \
3014 _argvec[7] = (unsigned long)(arg7); \
3015 _argvec[8] = (unsigned long)(arg8); \
3016 _argvec[9] = (unsigned long)(arg9); \
3017 _argvec[10] = (unsigned long)(arg10); \
3018 _argvec[11] = (unsigned long)(arg11); \
3019 __asm__ volatile( \
3020 "ldr r0, [%1, #40] \n\t" \
3021 "ldr r1, [%1, #44] \n\t" \
3022 "push {r0, r1} \n\t" \
3023 "ldr r0, [%1, #20] \n\t" \
3024 "ldr r1, [%1, #24] \n\t" \
3025 "ldr r2, [%1, #28] \n\t" \
3026 "ldr r3, [%1, #32] \n\t" \
3027 "ldr r4, [%1, #36] \n\t" \
3028 "push {r0, r1, r2, r3, r4} \n\t" \
3029 "ldr r0, [%1, #4] \n\t" \
3030 "ldr r1, [%1, #8] \n\t" \
3031 "ldr r2, [%1, #12] \n\t" \
3032 "ldr r3, [%1, #16] \n\t" \
3033 "ldr r4, [%1] \n\t" /* target->r4 */ \
3034 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3035 "add sp, sp, #28 \n\t" \
3036 "mov %0, r0" \
3037 : /*out*/ "=r" (_res) \
3038 : /*in*/ "0" (&_argvec[0]) \
3039 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3040 ); \
3041 lval = (__typeof__(lval)) _res; \
3042 } while (0)
3043
3044#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3045 arg6,arg7,arg8,arg9,arg10, \
3046 arg11,arg12) \
3047 do { \
3048 volatile OrigFn _orig = (orig); \
3049 volatile unsigned long _argvec[13]; \
3050 volatile unsigned long _res; \
3051 _argvec[0] = (unsigned long)_orig.nraddr; \
3052 _argvec[1] = (unsigned long)(arg1); \
3053 _argvec[2] = (unsigned long)(arg2); \
3054 _argvec[3] = (unsigned long)(arg3); \
3055 _argvec[4] = (unsigned long)(arg4); \
3056 _argvec[5] = (unsigned long)(arg5); \
3057 _argvec[6] = (unsigned long)(arg6); \
3058 _argvec[7] = (unsigned long)(arg7); \
3059 _argvec[8] = (unsigned long)(arg8); \
3060 _argvec[9] = (unsigned long)(arg9); \
3061 _argvec[10] = (unsigned long)(arg10); \
3062 _argvec[11] = (unsigned long)(arg11); \
3063 _argvec[12] = (unsigned long)(arg12); \
3064 __asm__ volatile( \
3065 "ldr r0, [%1, #40] \n\t" \
3066 "ldr r1, [%1, #44] \n\t" \
3067 "ldr r2, [%1, #48] \n\t" \
3068 "push {r0, r1, r2} \n\t" \
3069 "ldr r0, [%1, #20] \n\t" \
3070 "ldr r1, [%1, #24] \n\t" \
3071 "ldr r2, [%1, #28] \n\t" \
3072 "ldr r3, [%1, #32] \n\t" \
3073 "ldr r4, [%1, #36] \n\t" \
3074 "push {r0, r1, r2, r3, r4} \n\t" \
3075 "ldr r0, [%1, #4] \n\t" \
3076 "ldr r1, [%1, #8] \n\t" \
3077 "ldr r2, [%1, #12] \n\t" \
3078 "ldr r3, [%1, #16] \n\t" \
3079 "ldr r4, [%1] \n\t" /* target->r4 */ \
3080 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3081 "add sp, sp, #32 \n\t" \
3082 "mov %0, r0" \
3083 : /*out*/ "=r" (_res) \
3084 : /*in*/ "0" (&_argvec[0]) \
3085 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3086 ); \
3087 lval = (__typeof__(lval)) _res; \
3088 } while (0)
3089
3090#endif /* PLAT_arm_linux */
3091
sewardjb5b87402011-03-07 16:05:35 +00003092/* ------------------------- s390x-linux ------------------------- */
3093
3094#if defined(PLAT_s390x_linux)
3095
3096/* Similar workaround as amd64 (see above), but we use r11 as frame
3097 pointer and save the old r11 in r7. r11 might be used for
3098 argvec, therefore we copy argvec in r1 since r1 is clobbered
3099 after the call anyway. */
3100#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
3101# define __FRAME_POINTER \
3102 ,"d"(__builtin_dwarf_cfa())
3103# define VALGRIND_CFI_PROLOGUE \
3104 ".cfi_remember_state\n\t" \
3105 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
3106 "lgr 7,11\n\t" \
3107 "lgr 11,%2\n\t" \
3108 ".cfi_def_cfa r11, 0\n\t"
3109# define VALGRIND_CFI_EPILOGUE \
3110 "lgr 11, 7\n\t" \
3111 ".cfi_restore_state\n\t"
3112#else
3113# define __FRAME_POINTER
3114# define VALGRIND_CFI_PROLOGUE \
3115 "lgr 1,%1\n\t"
3116# define VALGRIND_CFI_EPILOGUE
3117#endif
3118
3119
3120
3121
3122/* These regs are trashed by the hidden call. Note that we overwrite
3123 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
3124 function a proper return address. All others are ABI defined call
3125 clobbers. */
3126#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
3127 "f0","f1","f2","f3","f4","f5","f6","f7"
3128
3129
3130#define CALL_FN_W_v(lval, orig) \
3131 do { \
3132 volatile OrigFn _orig = (orig); \
3133 volatile unsigned long _argvec[1]; \
3134 volatile unsigned long _res; \
3135 _argvec[0] = (unsigned long)_orig.nraddr; \
3136 __asm__ volatile( \
3137 VALGRIND_CFI_PROLOGUE \
3138 "aghi 15,-160\n\t" \
3139 "lg 1, 0(1)\n\t" /* target->r1 */ \
3140 VALGRIND_CALL_NOREDIR_R1 \
3141 "lgr %0, 2\n\t" \
3142 "aghi 15,160\n\t" \
3143 VALGRIND_CFI_EPILOGUE \
3144 : /*out*/ "=d" (_res) \
3145 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
3146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3147 ); \
3148 lval = (__typeof__(lval)) _res; \
3149 } while (0)
3150
3151/* The call abi has the arguments in r2-r6 and stack */
3152#define CALL_FN_W_W(lval, orig, arg1) \
3153 do { \
3154 volatile OrigFn _orig = (orig); \
3155 volatile unsigned long _argvec[2]; \
3156 volatile unsigned long _res; \
3157 _argvec[0] = (unsigned long)_orig.nraddr; \
3158 _argvec[1] = (unsigned long)arg1; \
3159 __asm__ volatile( \
3160 VALGRIND_CFI_PROLOGUE \
3161 "aghi 15,-160\n\t" \
3162 "lg 2, 8(1)\n\t" \
3163 "lg 1, 0(1)\n\t" \
3164 VALGRIND_CALL_NOREDIR_R1 \
3165 "lgr %0, 2\n\t" \
3166 "aghi 15,160\n\t" \
3167 VALGRIND_CFI_EPILOGUE \
3168 : /*out*/ "=d" (_res) \
3169 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3170 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3171 ); \
3172 lval = (__typeof__(lval)) _res; \
3173 } while (0)
3174
3175#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
3176 do { \
3177 volatile OrigFn _orig = (orig); \
3178 volatile unsigned long _argvec[3]; \
3179 volatile unsigned long _res; \
3180 _argvec[0] = (unsigned long)_orig.nraddr; \
3181 _argvec[1] = (unsigned long)arg1; \
3182 _argvec[2] = (unsigned long)arg2; \
3183 __asm__ volatile( \
3184 VALGRIND_CFI_PROLOGUE \
3185 "aghi 15,-160\n\t" \
3186 "lg 2, 8(1)\n\t" \
3187 "lg 3,16(1)\n\t" \
3188 "lg 1, 0(1)\n\t" \
3189 VALGRIND_CALL_NOREDIR_R1 \
3190 "lgr %0, 2\n\t" \
3191 "aghi 15,160\n\t" \
3192 VALGRIND_CFI_EPILOGUE \
3193 : /*out*/ "=d" (_res) \
3194 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3195 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3196 ); \
3197 lval = (__typeof__(lval)) _res; \
3198 } while (0)
3199
3200#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
3201 do { \
3202 volatile OrigFn _orig = (orig); \
3203 volatile unsigned long _argvec[4]; \
3204 volatile unsigned long _res; \
3205 _argvec[0] = (unsigned long)_orig.nraddr; \
3206 _argvec[1] = (unsigned long)arg1; \
3207 _argvec[2] = (unsigned long)arg2; \
3208 _argvec[3] = (unsigned long)arg3; \
3209 __asm__ volatile( \
3210 VALGRIND_CFI_PROLOGUE \
3211 "aghi 15,-160\n\t" \
3212 "lg 2, 8(1)\n\t" \
3213 "lg 3,16(1)\n\t" \
3214 "lg 4,24(1)\n\t" \
3215 "lg 1, 0(1)\n\t" \
3216 VALGRIND_CALL_NOREDIR_R1 \
3217 "lgr %0, 2\n\t" \
3218 "aghi 15,160\n\t" \
3219 VALGRIND_CFI_EPILOGUE \
3220 : /*out*/ "=d" (_res) \
3221 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3222 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3223 ); \
3224 lval = (__typeof__(lval)) _res; \
3225 } while (0)
3226
3227#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
3228 do { \
3229 volatile OrigFn _orig = (orig); \
3230 volatile unsigned long _argvec[5]; \
3231 volatile unsigned long _res; \
3232 _argvec[0] = (unsigned long)_orig.nraddr; \
3233 _argvec[1] = (unsigned long)arg1; \
3234 _argvec[2] = (unsigned long)arg2; \
3235 _argvec[3] = (unsigned long)arg3; \
3236 _argvec[4] = (unsigned long)arg4; \
3237 __asm__ volatile( \
3238 VALGRIND_CFI_PROLOGUE \
3239 "aghi 15,-160\n\t" \
3240 "lg 2, 8(1)\n\t" \
3241 "lg 3,16(1)\n\t" \
3242 "lg 4,24(1)\n\t" \
3243 "lg 5,32(1)\n\t" \
3244 "lg 1, 0(1)\n\t" \
3245 VALGRIND_CALL_NOREDIR_R1 \
3246 "lgr %0, 2\n\t" \
3247 "aghi 15,160\n\t" \
3248 VALGRIND_CFI_EPILOGUE \
3249 : /*out*/ "=d" (_res) \
3250 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3251 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3252 ); \
3253 lval = (__typeof__(lval)) _res; \
3254 } while (0)
3255
3256#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
3257 do { \
3258 volatile OrigFn _orig = (orig); \
3259 volatile unsigned long _argvec[6]; \
3260 volatile unsigned long _res; \
3261 _argvec[0] = (unsigned long)_orig.nraddr; \
3262 _argvec[1] = (unsigned long)arg1; \
3263 _argvec[2] = (unsigned long)arg2; \
3264 _argvec[3] = (unsigned long)arg3; \
3265 _argvec[4] = (unsigned long)arg4; \
3266 _argvec[5] = (unsigned long)arg5; \
3267 __asm__ volatile( \
3268 VALGRIND_CFI_PROLOGUE \
3269 "aghi 15,-160\n\t" \
3270 "lg 2, 8(1)\n\t" \
3271 "lg 3,16(1)\n\t" \
3272 "lg 4,24(1)\n\t" \
3273 "lg 5,32(1)\n\t" \
3274 "lg 6,40(1)\n\t" \
3275 "lg 1, 0(1)\n\t" \
3276 VALGRIND_CALL_NOREDIR_R1 \
3277 "lgr %0, 2\n\t" \
3278 "aghi 15,160\n\t" \
3279 VALGRIND_CFI_EPILOGUE \
3280 : /*out*/ "=d" (_res) \
3281 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3282 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3283 ); \
3284 lval = (__typeof__(lval)) _res; \
3285 } while (0)
3286
3287#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3288 arg6) \
3289 do { \
3290 volatile OrigFn _orig = (orig); \
3291 volatile unsigned long _argvec[7]; \
3292 volatile unsigned long _res; \
3293 _argvec[0] = (unsigned long)_orig.nraddr; \
3294 _argvec[1] = (unsigned long)arg1; \
3295 _argvec[2] = (unsigned long)arg2; \
3296 _argvec[3] = (unsigned long)arg3; \
3297 _argvec[4] = (unsigned long)arg4; \
3298 _argvec[5] = (unsigned long)arg5; \
3299 _argvec[6] = (unsigned long)arg6; \
3300 __asm__ volatile( \
3301 VALGRIND_CFI_PROLOGUE \
3302 "aghi 15,-168\n\t" \
3303 "lg 2, 8(1)\n\t" \
3304 "lg 3,16(1)\n\t" \
3305 "lg 4,24(1)\n\t" \
3306 "lg 5,32(1)\n\t" \
3307 "lg 6,40(1)\n\t" \
3308 "mvc 160(8,15), 48(1)\n\t" \
3309 "lg 1, 0(1)\n\t" \
3310 VALGRIND_CALL_NOREDIR_R1 \
3311 "lgr %0, 2\n\t" \
3312 "aghi 15,168\n\t" \
3313 VALGRIND_CFI_EPILOGUE \
3314 : /*out*/ "=d" (_res) \
3315 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3316 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3317 ); \
3318 lval = (__typeof__(lval)) _res; \
3319 } while (0)
3320
3321#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3322 arg6, arg7) \
3323 do { \
3324 volatile OrigFn _orig = (orig); \
3325 volatile unsigned long _argvec[8]; \
3326 volatile unsigned long _res; \
3327 _argvec[0] = (unsigned long)_orig.nraddr; \
3328 _argvec[1] = (unsigned long)arg1; \
3329 _argvec[2] = (unsigned long)arg2; \
3330 _argvec[3] = (unsigned long)arg3; \
3331 _argvec[4] = (unsigned long)arg4; \
3332 _argvec[5] = (unsigned long)arg5; \
3333 _argvec[6] = (unsigned long)arg6; \
3334 _argvec[7] = (unsigned long)arg7; \
3335 __asm__ volatile( \
3336 VALGRIND_CFI_PROLOGUE \
3337 "aghi 15,-176\n\t" \
3338 "lg 2, 8(1)\n\t" \
3339 "lg 3,16(1)\n\t" \
3340 "lg 4,24(1)\n\t" \
3341 "lg 5,32(1)\n\t" \
3342 "lg 6,40(1)\n\t" \
3343 "mvc 160(8,15), 48(1)\n\t" \
3344 "mvc 168(8,15), 56(1)\n\t" \
3345 "lg 1, 0(1)\n\t" \
3346 VALGRIND_CALL_NOREDIR_R1 \
3347 "lgr %0, 2\n\t" \
3348 "aghi 15,176\n\t" \
3349 VALGRIND_CFI_EPILOGUE \
3350 : /*out*/ "=d" (_res) \
3351 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3352 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3353 ); \
3354 lval = (__typeof__(lval)) _res; \
3355 } while (0)
3356
3357#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3358 arg6, arg7 ,arg8) \
3359 do { \
3360 volatile OrigFn _orig = (orig); \
3361 volatile unsigned long _argvec[9]; \
3362 volatile unsigned long _res; \
3363 _argvec[0] = (unsigned long)_orig.nraddr; \
3364 _argvec[1] = (unsigned long)arg1; \
3365 _argvec[2] = (unsigned long)arg2; \
3366 _argvec[3] = (unsigned long)arg3; \
3367 _argvec[4] = (unsigned long)arg4; \
3368 _argvec[5] = (unsigned long)arg5; \
3369 _argvec[6] = (unsigned long)arg6; \
3370 _argvec[7] = (unsigned long)arg7; \
3371 _argvec[8] = (unsigned long)arg8; \
3372 __asm__ volatile( \
3373 VALGRIND_CFI_PROLOGUE \
3374 "aghi 15,-184\n\t" \
3375 "lg 2, 8(1)\n\t" \
3376 "lg 3,16(1)\n\t" \
3377 "lg 4,24(1)\n\t" \
3378 "lg 5,32(1)\n\t" \
3379 "lg 6,40(1)\n\t" \
3380 "mvc 160(8,15), 48(1)\n\t" \
3381 "mvc 168(8,15), 56(1)\n\t" \
3382 "mvc 176(8,15), 64(1)\n\t" \
3383 "lg 1, 0(1)\n\t" \
3384 VALGRIND_CALL_NOREDIR_R1 \
3385 "lgr %0, 2\n\t" \
3386 "aghi 15,184\n\t" \
3387 VALGRIND_CFI_EPILOGUE \
3388 : /*out*/ "=d" (_res) \
3389 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3390 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3391 ); \
3392 lval = (__typeof__(lval)) _res; \
3393 } while (0)
3394
3395#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3396 arg6, arg7 ,arg8, arg9) \
3397 do { \
3398 volatile OrigFn _orig = (orig); \
3399 volatile unsigned long _argvec[10]; \
3400 volatile unsigned long _res; \
3401 _argvec[0] = (unsigned long)_orig.nraddr; \
3402 _argvec[1] = (unsigned long)arg1; \
3403 _argvec[2] = (unsigned long)arg2; \
3404 _argvec[3] = (unsigned long)arg3; \
3405 _argvec[4] = (unsigned long)arg4; \
3406 _argvec[5] = (unsigned long)arg5; \
3407 _argvec[6] = (unsigned long)arg6; \
3408 _argvec[7] = (unsigned long)arg7; \
3409 _argvec[8] = (unsigned long)arg8; \
3410 _argvec[9] = (unsigned long)arg9; \
3411 __asm__ volatile( \
3412 VALGRIND_CFI_PROLOGUE \
3413 "aghi 15,-192\n\t" \
3414 "lg 2, 8(1)\n\t" \
3415 "lg 3,16(1)\n\t" \
3416 "lg 4,24(1)\n\t" \
3417 "lg 5,32(1)\n\t" \
3418 "lg 6,40(1)\n\t" \
3419 "mvc 160(8,15), 48(1)\n\t" \
3420 "mvc 168(8,15), 56(1)\n\t" \
3421 "mvc 176(8,15), 64(1)\n\t" \
3422 "mvc 184(8,15), 72(1)\n\t" \
3423 "lg 1, 0(1)\n\t" \
3424 VALGRIND_CALL_NOREDIR_R1 \
3425 "lgr %0, 2\n\t" \
3426 "aghi 15,192\n\t" \
3427 VALGRIND_CFI_EPILOGUE \
3428 : /*out*/ "=d" (_res) \
3429 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3430 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3431 ); \
3432 lval = (__typeof__(lval)) _res; \
3433 } while (0)
3434
3435#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3436 arg6, arg7 ,arg8, arg9, arg10) \
3437 do { \
3438 volatile OrigFn _orig = (orig); \
3439 volatile unsigned long _argvec[11]; \
3440 volatile unsigned long _res; \
3441 _argvec[0] = (unsigned long)_orig.nraddr; \
3442 _argvec[1] = (unsigned long)arg1; \
3443 _argvec[2] = (unsigned long)arg2; \
3444 _argvec[3] = (unsigned long)arg3; \
3445 _argvec[4] = (unsigned long)arg4; \
3446 _argvec[5] = (unsigned long)arg5; \
3447 _argvec[6] = (unsigned long)arg6; \
3448 _argvec[7] = (unsigned long)arg7; \
3449 _argvec[8] = (unsigned long)arg8; \
3450 _argvec[9] = (unsigned long)arg9; \
3451 _argvec[10] = (unsigned long)arg10; \
3452 __asm__ volatile( \
3453 VALGRIND_CFI_PROLOGUE \
3454 "aghi 15,-200\n\t" \
3455 "lg 2, 8(1)\n\t" \
3456 "lg 3,16(1)\n\t" \
3457 "lg 4,24(1)\n\t" \
3458 "lg 5,32(1)\n\t" \
3459 "lg 6,40(1)\n\t" \
3460 "mvc 160(8,15), 48(1)\n\t" \
3461 "mvc 168(8,15), 56(1)\n\t" \
3462 "mvc 176(8,15), 64(1)\n\t" \
3463 "mvc 184(8,15), 72(1)\n\t" \
3464 "mvc 192(8,15), 80(1)\n\t" \
3465 "lg 1, 0(1)\n\t" \
3466 VALGRIND_CALL_NOREDIR_R1 \
3467 "lgr %0, 2\n\t" \
3468 "aghi 15,200\n\t" \
3469 VALGRIND_CFI_EPILOGUE \
3470 : /*out*/ "=d" (_res) \
3471 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3472 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3473 ); \
3474 lval = (__typeof__(lval)) _res; \
3475 } while (0)
3476
3477#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3478 arg6, arg7 ,arg8, arg9, arg10, arg11) \
3479 do { \
3480 volatile OrigFn _orig = (orig); \
3481 volatile unsigned long _argvec[12]; \
3482 volatile unsigned long _res; \
3483 _argvec[0] = (unsigned long)_orig.nraddr; \
3484 _argvec[1] = (unsigned long)arg1; \
3485 _argvec[2] = (unsigned long)arg2; \
3486 _argvec[3] = (unsigned long)arg3; \
3487 _argvec[4] = (unsigned long)arg4; \
3488 _argvec[5] = (unsigned long)arg5; \
3489 _argvec[6] = (unsigned long)arg6; \
3490 _argvec[7] = (unsigned long)arg7; \
3491 _argvec[8] = (unsigned long)arg8; \
3492 _argvec[9] = (unsigned long)arg9; \
3493 _argvec[10] = (unsigned long)arg10; \
3494 _argvec[11] = (unsigned long)arg11; \
3495 __asm__ volatile( \
3496 VALGRIND_CFI_PROLOGUE \
3497 "aghi 15,-208\n\t" \
3498 "lg 2, 8(1)\n\t" \
3499 "lg 3,16(1)\n\t" \
3500 "lg 4,24(1)\n\t" \
3501 "lg 5,32(1)\n\t" \
3502 "lg 6,40(1)\n\t" \
3503 "mvc 160(8,15), 48(1)\n\t" \
3504 "mvc 168(8,15), 56(1)\n\t" \
3505 "mvc 176(8,15), 64(1)\n\t" \
3506 "mvc 184(8,15), 72(1)\n\t" \
3507 "mvc 192(8,15), 80(1)\n\t" \
3508 "mvc 200(8,15), 88(1)\n\t" \
3509 "lg 1, 0(1)\n\t" \
3510 VALGRIND_CALL_NOREDIR_R1 \
3511 "lgr %0, 2\n\t" \
3512 "aghi 15,208\n\t" \
3513 VALGRIND_CFI_EPILOGUE \
3514 : /*out*/ "=d" (_res) \
3515 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3516 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3517 ); \
3518 lval = (__typeof__(lval)) _res; \
3519 } while (0)
3520
3521#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3522 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
3523 do { \
3524 volatile OrigFn _orig = (orig); \
3525 volatile unsigned long _argvec[13]; \
3526 volatile unsigned long _res; \
3527 _argvec[0] = (unsigned long)_orig.nraddr; \
3528 _argvec[1] = (unsigned long)arg1; \
3529 _argvec[2] = (unsigned long)arg2; \
3530 _argvec[3] = (unsigned long)arg3; \
3531 _argvec[4] = (unsigned long)arg4; \
3532 _argvec[5] = (unsigned long)arg5; \
3533 _argvec[6] = (unsigned long)arg6; \
3534 _argvec[7] = (unsigned long)arg7; \
3535 _argvec[8] = (unsigned long)arg8; \
3536 _argvec[9] = (unsigned long)arg9; \
3537 _argvec[10] = (unsigned long)arg10; \
3538 _argvec[11] = (unsigned long)arg11; \
3539 _argvec[12] = (unsigned long)arg12; \
3540 __asm__ volatile( \
3541 VALGRIND_CFI_PROLOGUE \
3542 "aghi 15,-216\n\t" \
3543 "lg 2, 8(1)\n\t" \
3544 "lg 3,16(1)\n\t" \
3545 "lg 4,24(1)\n\t" \
3546 "lg 5,32(1)\n\t" \
3547 "lg 6,40(1)\n\t" \
3548 "mvc 160(8,15), 48(1)\n\t" \
3549 "mvc 168(8,15), 56(1)\n\t" \
3550 "mvc 176(8,15), 64(1)\n\t" \
3551 "mvc 184(8,15), 72(1)\n\t" \
3552 "mvc 192(8,15), 80(1)\n\t" \
3553 "mvc 200(8,15), 88(1)\n\t" \
3554 "mvc 208(8,15), 96(1)\n\t" \
3555 "lg 1, 0(1)\n\t" \
3556 VALGRIND_CALL_NOREDIR_R1 \
3557 "lgr %0, 2\n\t" \
3558 "aghi 15,216\n\t" \
3559 VALGRIND_CFI_EPILOGUE \
3560 : /*out*/ "=d" (_res) \
3561 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3562 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3563 ); \
3564 lval = (__typeof__(lval)) _res; \
3565 } while (0)
3566
3567
3568#endif /* PLAT_s390x_linux */
3569
sewardj0ec07f32006-01-12 12:32:32 +00003570
3571/* ------------------------------------------------------------------ */
3572/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
3573/* */
njn30d76c62005-06-18 15:07:39 +00003574/* ------------------------------------------------------------------ */
3575
sewardj2e93c502002-04-12 11:12:52 +00003576/* Some request codes. There are many more of these, but most are not
3577 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00003578 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00003579
sewardj0ec07f32006-01-12 12:32:32 +00003580 Core ones are in the range 0x00000000--0x0000ffff. The non-public
3581 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00003582*/
3583
sewardj0ec07f32006-01-12 12:32:32 +00003584/* These macros are used by tools -- they must be public, but don't
3585 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00003586#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00003587 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00003588#define VG_IS_TOOL_USERREQ(a, b, v) \
3589 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00003590
sewardj5ce4b152006-03-11 12:57:41 +00003591/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3592 This enum comprises an ABI exported by Valgrind to programs
3593 which use client requests. DO NOT CHANGE THE ORDER OF THESE
3594 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00003595typedef
njn4c791212003-05-02 17:53:54 +00003596 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
3597 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00003598
sewardj0ec07f32006-01-12 12:32:32 +00003599 /* These allow any function to be called from the simulated
3600 CPU but run on the real CPU. Nb: the first arg passed to
3601 the function is always the ThreadId of the running
3602 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00003603 function, etc. */
njn4c791212003-05-02 17:53:54 +00003604 VG_USERREQ__CLIENT_CALL0 = 0x1101,
3605 VG_USERREQ__CLIENT_CALL1 = 0x1102,
3606 VG_USERREQ__CLIENT_CALL2 = 0x1103,
3607 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00003608
sewardj0ec07f32006-01-12 12:32:32 +00003609 /* Can be useful in regression testing suites -- eg. can
3610 send Valgrind's output to /dev/null and still count
3611 errors. */
njn4c791212003-05-02 17:53:54 +00003612 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00003613
sewardj3b290482011-05-06 21:02:55 +00003614 /* Allows a string (gdb monitor command) to be passed to the tool
3615 Used for interaction with vgdb/gdb */
3616 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
3617
sewardj0ec07f32006-01-12 12:32:32 +00003618 /* These are useful and can be interpreted by any tool that
3619 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00003620 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00003621 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00003622 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00003623 /* Memory pool support. */
3624 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
3625 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
3626 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
3627 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00003628 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00003629 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
3630 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
3631 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00003632
fitzhardinge39de4b42003-10-31 07:12:21 +00003633 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00003634 /* The first two pass the va_list argument by value, which
3635 assumes it is the same size as or smaller than a UWord,
3636 which generally isn't the case. Hence are deprecated.
3637 The second two pass the vargs by reference and so are
3638 immune to this problem. */
3639 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00003640 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00003641 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00003642 /* both :: char* fmt, va_list* vargs */
3643 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
3644 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00003645
3646 /* Stack support. */
3647 VG_USERREQ__STACK_REGISTER = 0x1501,
3648 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00003649 VG_USERREQ__STACK_CHANGE = 0x1503,
3650
3651 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00003652 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
3653
3654 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00003655 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
3656
3657 /* Disable/enable error reporting level. Takes a single
3658 Word arg which is the delta to this thread's error
3659 disablement indicator. Hence 1 disables or further
3660 disables errors, and -1 moves back towards enablement.
3661 Other values are not allowed. */
3662 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801
njn25e49d8e72002-09-23 09:36:25 +00003663 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00003664
sewardj0ec07f32006-01-12 12:32:32 +00003665#if !defined(__GNUC__)
3666# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00003667#endif
sewardj2e93c502002-04-12 11:12:52 +00003668
bartfa5115a2010-09-02 09:33:02 +00003669
sewardj0ec07f32006-01-12 12:32:32 +00003670/* Returns the number of Valgrinds this code is running under. That
3671 is, 0 if running natively, 1 if running under Valgrind, 2 if
3672 running under Valgrind which is running under another Valgrind,
3673 etc. */
bartfa5115a2010-09-02 09:33:02 +00003674#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00003675 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00003676 VG_USERREQ__RUNNING_ON_VALGRIND, \
3677 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00003678
3679
sewardj18d75132002-05-16 11:06:21 +00003680/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3681 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
3682 since it provides a way to make sure valgrind will retranslate the
3683 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00003684#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
bart575ce8e2011-05-15 07:04:03 +00003685 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003686 VG_USERREQ__DISCARD_TRANSLATIONS, \
bart575ce8e2011-05-15 07:04:03 +00003687 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00003688
njn26aba4d2005-05-16 13:31:23 +00003689
sewardj0ec07f32006-01-12 12:32:32 +00003690/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00003691 Possibly with a backtrace. This is a really ugly hack. The return value
3692 is the number of characters printed, excluding the "**<pid>** " part at the
3693 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00003694
bart8c7e25f2011-03-04 16:55:56 +00003695#if defined(__GNUC__) || defined(__INTEL_COMPILER)
sewardj7eca0cc2006-04-12 17:15:35 +00003696/* Modern GCC will optimize the static routine out if unused,
3697 and unused attribute will shut down warnings about it. */
3698static int VALGRIND_PRINTF(const char *format, ...)
3699 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00003700#endif
sewardj7eca0cc2006-04-12 17:15:35 +00003701static int
bart0da2c772010-09-01 10:18:36 +00003702#if defined(_MSC_VER)
3703__inline
3704#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00003705VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003706{
bart8c7e25f2011-03-04 16:55:56 +00003707#if defined(NVALGRIND)
3708 return 0;
3709#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00003710#if defined(_MSC_VER)
3711 uintptr_t _qzz_res;
3712#else
njnc6168192004-11-29 13:54:10 +00003713 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00003714#endif
sewardjc560fb32010-01-28 15:23:54 +00003715 va_list vargs;
3716 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00003717#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00003718 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00003719 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00003720 (uintptr_t)format,
3721 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00003722 0, 0, 0);
3723#else
bart575ce8e2011-05-15 07:04:03 +00003724 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00003725 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00003726 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00003727 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00003728 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00003729#endif
sewardjc560fb32010-01-28 15:23:54 +00003730 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003731 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00003732#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00003733}
3734
bart8c7e25f2011-03-04 16:55:56 +00003735#if defined(__GNUC__) || defined(__INTEL_COMPILER)
sewardj7eca0cc2006-04-12 17:15:35 +00003736static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3737 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00003738#endif
sewardj7eca0cc2006-04-12 17:15:35 +00003739static int
bart0da2c772010-09-01 10:18:36 +00003740#if defined(_MSC_VER)
3741__inline
3742#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00003743VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003744{
bart8c7e25f2011-03-04 16:55:56 +00003745#if defined(NVALGRIND)
3746 return 0;
3747#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00003748#if defined(_MSC_VER)
3749 uintptr_t _qzz_res;
3750#else
njnc6168192004-11-29 13:54:10 +00003751 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00003752#endif
sewardjc560fb32010-01-28 15:23:54 +00003753 va_list vargs;
3754 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00003755#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00003756 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00003757 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00003758 (uintptr_t)format,
3759 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00003760 0, 0, 0);
3761#else
bart575ce8e2011-05-15 07:04:03 +00003762 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00003763 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00003764 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00003765 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00003766 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00003767#endif
sewardjc560fb32010-01-28 15:23:54 +00003768 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003769 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003770#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00003771}
sewardj18d75132002-05-16 11:06:21 +00003772
sewardj0ec07f32006-01-12 12:32:32 +00003773
njn3e884182003-04-15 13:03:23 +00003774/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00003775 real CPU, calling an arbitary function.
3776
3777 Note that the current ThreadId is inserted as the first argument.
3778 So this call:
3779
3780 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3781
3782 requires f to have this signature:
3783
3784 Word f(Word tid, Word arg1, Word arg2)
3785
3786 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00003787
3788 Note that these client requests are not entirely reliable. For example,
3789 if you call a function with them that subsequently calls printf(),
3790 there's a high chance Valgrind will crash. Generally, your prospects of
3791 these working are made higher if the called function does not refer to
3792 any global variables, and does not refer to any libc or other functions
3793 (printf et al). Any kind of entanglement with libc or dynamic linking is
3794 likely to have a bad outcome, for tricky reasons which we've grappled
3795 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00003796*/
sewardj0ec07f32006-01-12 12:32:32 +00003797#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00003798 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3799 VG_USERREQ__CLIENT_CALL0, \
3800 _qyy_fn, \
3801 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00003802
bart575ce8e2011-05-15 07:04:03 +00003803#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
3804 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3805 VG_USERREQ__CLIENT_CALL1, \
3806 _qyy_fn, \
3807 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00003808
bart575ce8e2011-05-15 07:04:03 +00003809#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
3810 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3811 VG_USERREQ__CLIENT_CALL2, \
3812 _qyy_fn, \
3813 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00003814
sewardj0ec07f32006-01-12 12:32:32 +00003815#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00003816 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3817 VG_USERREQ__CLIENT_CALL3, \
3818 _qyy_fn, \
3819 _qyy_arg1, _qyy_arg2, \
3820 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00003821
3822
nethercote7cc9c232004-01-21 15:08:04 +00003823/* Counts the number of errors that have been recorded by a tool. Nb:
3824 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00003825 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00003826#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00003827 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
3828 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00003829 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00003830 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00003831
njn3ac96952009-07-09 23:35:44 +00003832/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
3833 when heap blocks are allocated in order to give accurate results. This
3834 happens automatically for the standard allocator functions such as
3835 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
3836 delete[], etc.
njnd7994182003-10-02 13:44:04 +00003837
njn3ac96952009-07-09 23:35:44 +00003838 But if your program uses a custom allocator, this doesn't automatically
3839 happen, and Valgrind will not do as well. For example, if you allocate
3840 superblocks with mmap() and then allocates chunks of the superblocks, all
3841 Valgrind's observations will be at the mmap() level and it won't know that
3842 the chunks should be considered separate entities. In Memcheck's case,
3843 that means you probably won't get heap block overrun detection (because
3844 there won't be redzones marked as unaddressable) and you definitely won't
3845 get any leak detection.
3846
3847 The following client requests allow a custom allocator to be annotated so
3848 that it can be handled accurately by Valgrind.
3849
3850 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
3851 by a malloc()-like function. For Memcheck (an illustrative case), this
3852 does two things:
3853
3854 - It records that the block has been allocated. This means any addresses
3855 within the block mentioned in error messages will be
3856 identified as belonging to the block. It also means that if the block
3857 isn't freed it will be detected by the leak checker.
3858
3859 - It marks the block as being addressable and undefined (if 'is_zeroed' is
3860 not set), or addressable and defined (if 'is_zeroed' is set). This
3861 controls how accesses to the block by the program are handled.
3862
3863 'addr' is the start of the usable block (ie. after any
3864 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
3865 can apply redzones -- these are blocks of padding at the start and end of
3866 each block. Adding redzones is recommended as it makes it much more likely
3867 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
3868 zeroed (or filled with another predictable value), as is the case for
3869 calloc().
3870
3871 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
3872 heap block -- that will be used by the client program -- is allocated.
3873 It's best to put it at the outermost level of the allocator if possible;
3874 for example, if you have a function my_alloc() which calls
3875 internal_alloc(), and the client request is put inside internal_alloc(),
3876 stack traces relating to the heap block will contain entries for both
3877 my_alloc() and internal_alloc(), which is probably not what you want.
3878
njnb965efb2009-08-10 07:36:54 +00003879 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
3880 custom blocks from within a heap block, B, that has been allocated with
3881 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
3882 -- the custom blocks will take precedence.
3883
njn3ac96952009-07-09 23:35:44 +00003884 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
3885 Memcheck, it does two things:
3886
3887 - It records that the block has been deallocated. This assumes that the
3888 block was annotated as having been allocated via
3889 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3890
3891 - It marks the block as being unaddressable.
3892
3893 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
3894 heap block is deallocated.
3895
bart91347382011-03-25 20:07:25 +00003896 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
3897 Memcheck, it does four things:
3898
3899 - It records that the size of a block has been changed. This assumes that
3900 the block was annotated as having been allocated via
3901 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3902
3903 - If the block shrunk, it marks the freed memory as being unaddressable.
3904
3905 - If the block grew, it marks the new area as undefined and defines a red
3906 zone past the end of the new block.
3907
3908 - The V-bits of the overlap between the old and the new block are preserved.
3909
3910 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
3911 and before deallocation of the old block.
3912
3913 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00003914 allocator working well with Memcheck. More specifically, if your allocator
3915 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
3916 will be necessary to mark the memory as addressable just before the zeroing
3917 occurs, otherwise you'll get a lot of invalid write errors. For example,
3918 you'll need to do this if your allocator recycles freed blocks, but it
3919 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
3920 Alternatively, if your allocator reuses freed blocks for allocator-internal
3921 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
3922
3923 Really, what's happening is a blurring of the lines between the client
3924 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
3925 memory should be considered unaddressable to the client program, but the
3926 allocator knows more than the rest of the client program and so may be able
3927 to safely access it. Extra client requests are necessary for Valgrind to
3928 understand the distinction between the allocator and the rest of the
3929 program.
3930
njn32f8d8c2009-07-15 02:31:45 +00003931 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00003932*/
sewardj0ec07f32006-01-12 12:32:32 +00003933#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
bart575ce8e2011-05-15 07:04:03 +00003934 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003935 VG_USERREQ__MALLOCLIKE_BLOCK, \
bart575ce8e2011-05-15 07:04:03 +00003936 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00003937
njn32f8d8c2009-07-15 02:31:45 +00003938/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3939 Ignored if addr == 0.
3940*/
sewardj66304e22011-03-28 21:19:00 +00003941#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
bart575ce8e2011-05-15 07:04:03 +00003942 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj66304e22011-03-28 21:19:00 +00003943 VG_USERREQ__RESIZEINPLACE_BLOCK, \
bart575ce8e2011-05-15 07:04:03 +00003944 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00003945
3946/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3947 Ignored if addr == 0.
3948*/
sewardj0ec07f32006-01-12 12:32:32 +00003949#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
bart575ce8e2011-05-15 07:04:03 +00003950 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003951 VG_USERREQ__FREELIKE_BLOCK, \
bart575ce8e2011-05-15 07:04:03 +00003952 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00003953
rjwalshbc0bb832004-06-19 18:12:36 +00003954/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003955#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
bart575ce8e2011-05-15 07:04:03 +00003956 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003957 VG_USERREQ__CREATE_MEMPOOL, \
bart575ce8e2011-05-15 07:04:03 +00003958 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003959
3960/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003961#define VALGRIND_DESTROY_MEMPOOL(pool) \
bart575ce8e2011-05-15 07:04:03 +00003962 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003963 VG_USERREQ__DESTROY_MEMPOOL, \
bart575ce8e2011-05-15 07:04:03 +00003964 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003965
3966/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003967#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
bart575ce8e2011-05-15 07:04:03 +00003968 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003969 VG_USERREQ__MEMPOOL_ALLOC, \
bart575ce8e2011-05-15 07:04:03 +00003970 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003971
3972/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003973#define VALGRIND_MEMPOOL_FREE(pool, addr) \
bart575ce8e2011-05-15 07:04:03 +00003974 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003975 VG_USERREQ__MEMPOOL_FREE, \
bart575ce8e2011-05-15 07:04:03 +00003976 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003977
sewardj2c1c9df2006-07-28 00:06:37 +00003978/* Disassociate any pieces outside a particular range. */
3979#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
bart575ce8e2011-05-15 07:04:03 +00003980 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj2c1c9df2006-07-28 00:06:37 +00003981 VG_USERREQ__MEMPOOL_TRIM, \
bart575ce8e2011-05-15 07:04:03 +00003982 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00003983
sewardjc740d762006-10-05 17:59:23 +00003984/* Resize and/or move a piece associated with a memory pool. */
3985#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
bart575ce8e2011-05-15 07:04:03 +00003986 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00003987 VG_USERREQ__MOVE_MEMPOOL, \
bart575ce8e2011-05-15 07:04:03 +00003988 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00003989
3990/* Resize and/or move a piece associated with a memory pool. */
3991#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
bart575ce8e2011-05-15 07:04:03 +00003992 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00003993 VG_USERREQ__MEMPOOL_CHANGE, \
bart575ce8e2011-05-15 07:04:03 +00003994 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00003995
3996/* Return 1 if a mempool exists, else 0. */
3997#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00003998 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00003999 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00004000 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00004001
rjwalsh0140af52005-06-04 20:42:33 +00004002/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004003#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00004004 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004005 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00004006 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004007
4008/* Unmark the piece of memory associated with a stack id as being a
4009 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004010#define VALGRIND_STACK_DEREGISTER(id) \
bart0d03bd42011-07-25 08:45:45 +00004011 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004012 VG_USERREQ__STACK_DEREGISTER, \
bart575ce8e2011-05-15 07:04:03 +00004013 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004014
4015/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004016#define VALGRIND_STACK_CHANGE(id, start, end) \
bart575ce8e2011-05-15 07:04:03 +00004017 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004018 VG_USERREQ__STACK_CHANGE, \
bart575ce8e2011-05-15 07:04:03 +00004019 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004020
sewardjc8259b82009-04-22 22:42:10 +00004021/* Load PDB debug info for Wine PE image_map. */
4022#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
bart575ce8e2011-05-15 07:04:03 +00004023 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc8259b82009-04-22 22:42:10 +00004024 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
bart575ce8e2011-05-15 07:04:03 +00004025 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00004026
sewardj5c659622010-08-20 18:22:07 +00004027/* Map a code address to a source file name and line number. buf64
4028 must point to a 64-byte buffer in the caller's address space. The
4029 result will be dumped in there and is guaranteed to be zero
4030 terminated. If no info is found, the first byte is set to zero. */
4031#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00004032 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00004033 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00004034 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00004035
sewardjdc873c02011-07-24 16:02:33 +00004036/* Disable error reporting for this thread. Behaves in a stack like
4037 way, so you can safely call this multiple times provided that
4038 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
4039 to re-enable reporting. The first call of this macro disables
4040 reporting. Subsequent calls have no effect except to increase the
4041 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
4042 reporting. Child threads do not inherit this setting from their
4043 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00004044#define VALGRIND_DISABLE_ERROR_REPORTING \
4045 do { \
4046 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
4047 VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4048 1, 0, 0, 0, 0); \
4049 } while (0)
sewardjdc873c02011-07-24 16:02:33 +00004050
4051/* Re-enable error reporting, as per comments on
4052 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00004053#define VALGRIND_ENABLE_ERROR_REPORTING \
4054 do { \
4055 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
4056 VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4057 -1, 0, 0, 0, 0); \
4058 } while (0)
sewardj0ec07f32006-01-12 12:32:32 +00004059
sewardjc112c8e2011-06-24 18:26:11 +00004060#undef PLAT_x86_darwin
4061#undef PLAT_amd64_darwin
4062#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +00004063#undef PLAT_x86_linux
4064#undef PLAT_amd64_linux
4065#undef PLAT_ppc32_linux
4066#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004067#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00004068#undef PLAT_s390x_linux
sewardj0ec07f32006-01-12 12:32:32 +00004069
njn3e884182003-04-15 13:03:23 +00004070#endif /* __VALGRIND_H */