blob: d10a5132f7f177ac42cad64a3994a4f25a1d8455 [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
sewardjec062e82011-10-23 07:32:08 +000015 Copyright (C) 2000-2011 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
sewardj7d79e0b2012-05-21 21:57:05 +000092#define __VALGRIND_MINOR__ 8
sewardj71044162010-03-03 22:57:47 +000093
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 *
sewardj4b3a7422011-10-24 13:21:57 +0000159 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
160 * client request that does not return a value.
161
bart575ce8e2011-05-15 07:04:03 +0000162 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000163 * client request and whose value equals the client request result. Accepts
164 * both pointers and integers as arguments. Note that such calls are not
165 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000166 */
167
168#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
169 _zzq_request, _zzq_arg1, _zzq_arg2, \
170 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000171 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000172 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000173 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000174
sewardj4b3a7422011-10-24 13:21:57 +0000175#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
176 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
177 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
178 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
179 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
180
sewardj0ec07f32006-01-12 12:32:32 +0000181#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000182
183/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000184 from the compiled code (analogous to NDEBUG's effects on
185 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000186#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
187 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000188 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000189 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000190
sewardj0ec07f32006-01-12 12:32:32 +0000191#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000192
sewardj0ec07f32006-01-12 12:32:32 +0000193/* The following defines the magic code sequences which the JITter
194 spots and handles magically. Don't look too closely at them as
195 they will rot your brain.
196
197 The assembly code sequences for all architectures is in this one
198 file. This is because this file must be stand-alone, and we don't
199 want to have multiple files.
200
201 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
202 value gets put in the return slot, so that everything works when
203 this is executed not under Valgrind. Args are passed in a memory
204 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000205 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000206
nethercote54265442004-10-26 12:56:58 +0000207 The macro args are:
208 _zzq_rlval result lvalue
209 _zzq_default default value (result returned when running on real CPU)
210 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000211 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000212
sewardj0ec07f32006-01-12 12:32:32 +0000213 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000214 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
215 guest's NRADDR pseudo-register and whatever other information is
216 needed to safely run the call original from the wrapper: on
217 ppc64-linux, the R2 value at the divert point is also needed. This
218 information is abstracted into a user-visible type, OrigFn.
219
220 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
221 guest, but guarantees that the branch instruction will not be
222 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
223 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
224 complete inline asm, since it needs to be combined with more magic
225 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000226*/
227
njnf76d27a2009-05-28 01:53:07 +0000228/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000229
sewardj520a03a2010-10-07 10:46:15 +0000230#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000231 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000232
233typedef
234 struct {
235 unsigned int nraddr; /* where's the code? */
236 }
237 OrigFn;
238
sewardj0ec07f32006-01-12 12:32:32 +0000239#define __SPECIAL_INSTRUCTION_PREAMBLE \
240 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000241 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000242
bart575ce8e2011-05-15 07:04:03 +0000243#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
244 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000245 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000246 __extension__ \
247 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000248 volatile unsigned int _zzq_result; \
249 _zzq_args[0] = (unsigned int)(_zzq_request); \
250 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
251 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
252 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
253 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000254 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000255 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
256 /* %EDX = client_request ( %EAX ) */ \
257 "xchgl %%ebx,%%ebx" \
258 : "=d" (_zzq_result) \
259 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
260 : "cc", "memory" \
261 ); \
bart575ce8e2011-05-15 07:04:03 +0000262 _zzq_result; \
263 })
sewardj2c48c7b2005-11-29 13:05:56 +0000264
sewardjc8858442006-01-20 15:17:20 +0000265#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
266 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
267 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000268 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
269 /* %EAX = guest_NRADDR */ \
270 "xchgl %%ecx,%%ecx" \
271 : "=a" (__addr) \
272 : \
273 : "cc", "memory" \
274 ); \
sewardjc8858442006-01-20 15:17:20 +0000275 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000276 }
sewardj0ec07f32006-01-12 12:32:32 +0000277
278#define VALGRIND_CALL_NOREDIR_EAX \
279 __SPECIAL_INSTRUCTION_PREAMBLE \
280 /* call-noredir *%EAX */ \
281 "xchgl %%edx,%%edx\n\t"
sewardj60227842010-10-07 10:00:56 +0000282#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000283
284/* ------------------------- x86-Win32 ------------------------- */
285
286#if defined(PLAT_x86_win32) && !defined(__GNUC__)
287
288typedef
289 struct {
290 unsigned int nraddr; /* where's the code? */
291 }
292 OrigFn;
293
294#if defined(_MSC_VER)
295
296#define __SPECIAL_INSTRUCTION_PREAMBLE \
297 __asm rol edi, 3 __asm rol edi, 13 \
298 __asm rol edi, 29 __asm rol edi, 19
299
bart575ce8e2011-05-15 07:04:03 +0000300#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
301 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000302 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000303 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
304 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
305 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
306 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
307
308static __inline uintptr_t
309valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
310 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
311 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
312 uintptr_t _zzq_arg5)
313{
314 volatile uintptr_t _zzq_args[6];
315 volatile unsigned int _zzq_result;
316 _zzq_args[0] = (uintptr_t)(_zzq_request);
317 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
318 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
319 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
320 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
321 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
322 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
323 __SPECIAL_INSTRUCTION_PREAMBLE
324 /* %EDX = client_request ( %EAX ) */
325 __asm xchg ebx,ebx
326 __asm mov _zzq_result, edx
327 }
328 return _zzq_result;
329}
bart7f489812010-08-27 10:05:27 +0000330
331#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
332 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
333 volatile unsigned int __addr; \
334 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
335 /* %EAX = guest_NRADDR */ \
336 __asm xchg ecx,ecx \
337 __asm mov __addr, eax \
338 } \
339 _zzq_orig->nraddr = __addr; \
340 }
341
342#define VALGRIND_CALL_NOREDIR_EAX ERROR
343
344#else
345#error Unsupported compiler.
346#endif
347
348#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000349
njnf76d27a2009-05-28 01:53:07 +0000350/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000351
njnf76d27a2009-05-28 01:53:07 +0000352#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000353
354typedef
355 struct {
356 unsigned long long int nraddr; /* where's the code? */
357 }
358 OrigFn;
359
sewardj0ec07f32006-01-12 12:32:32 +0000360#define __SPECIAL_INSTRUCTION_PREAMBLE \
361 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000362 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000363
bart575ce8e2011-05-15 07:04:03 +0000364#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
365 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000366 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000367 __extension__ \
368 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000369 volatile unsigned long long int _zzq_result; \
370 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
371 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
372 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
373 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
374 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000375 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000376 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
377 /* %RDX = client_request ( %RAX ) */ \
378 "xchgq %%rbx,%%rbx" \
379 : "=d" (_zzq_result) \
380 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
381 : "cc", "memory" \
382 ); \
bart575ce8e2011-05-15 07:04:03 +0000383 _zzq_result; \
384 })
sewardj0ec07f32006-01-12 12:32:32 +0000385
sewardjc8858442006-01-20 15:17:20 +0000386#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
387 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
388 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000389 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
390 /* %RAX = guest_NRADDR */ \
391 "xchgq %%rcx,%%rcx" \
392 : "=a" (__addr) \
393 : \
394 : "cc", "memory" \
395 ); \
sewardjc8858442006-01-20 15:17:20 +0000396 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000397 }
398
399#define VALGRIND_CALL_NOREDIR_RAX \
400 __SPECIAL_INSTRUCTION_PREAMBLE \
401 /* call-noredir *%RAX */ \
402 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000403#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000404
sewardjf5c1a7f2006-10-17 01:32:48 +0000405/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000406
sewardjf5c1a7f2006-10-17 01:32:48 +0000407#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000408
409typedef
410 struct {
sewardjc8858442006-01-20 15:17:20 +0000411 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000412 }
413 OrigFn;
414
sewardj0ec07f32006-01-12 12:32:32 +0000415#define __SPECIAL_INSTRUCTION_PREAMBLE \
416 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000417 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000418
bart575ce8e2011-05-15 07:04:03 +0000419#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
420 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000421 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000422 \
bart575ce8e2011-05-15 07:04:03 +0000423 __extension__ \
424 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000425 unsigned int _zzq_result; \
426 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000427 _zzq_args[0] = (unsigned int)(_zzq_request); \
428 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
429 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
430 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
431 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000432 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000433 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000434 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
435 "mr 4,%2\n\t" /*ptr*/ \
436 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000437 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000438 "or 1,1,1\n\t" \
439 "mr %0,3" /*result*/ \
440 : "=b" (_zzq_result) \
441 : "b" (_zzq_default), "b" (_zzq_ptr) \
442 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000443 _zzq_result; \
444 })
sewardj0ec07f32006-01-12 12:32:32 +0000445
sewardjd68ac3e2006-01-20 14:31:57 +0000446#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
447 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000448 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000449 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
450 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000451 "or 2,2,2\n\t" \
452 "mr %0,3" \
453 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000454 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000455 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000456 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000457 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000458 }
459
460#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
461 __SPECIAL_INSTRUCTION_PREAMBLE \
462 /* branch-and-link-to-noredir *%R11 */ \
463 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000464#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000465
sewardjf5c1a7f2006-10-17 01:32:48 +0000466/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000467
sewardjf5c1a7f2006-10-17 01:32:48 +0000468#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000469
470typedef
471 struct {
472 unsigned long long int nraddr; /* where's the code? */
473 unsigned long long int r2; /* what tocptr do we need? */
474 }
475 OrigFn;
476
sewardj1a85f4f2006-01-12 21:15:35 +0000477#define __SPECIAL_INSTRUCTION_PREAMBLE \
478 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
479 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
480
bart575ce8e2011-05-15 07:04:03 +0000481#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
482 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000483 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000484 \
bart575ce8e2011-05-15 07:04:03 +0000485 __extension__ \
486 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000487 unsigned long long int _zzq_result; \
488 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000489 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
490 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
491 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
492 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
493 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000494 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000495 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000496 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
497 "mr 4,%2\n\t" /*ptr*/ \
498 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000499 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000500 "or 1,1,1\n\t" \
501 "mr %0,3" /*result*/ \
502 : "=b" (_zzq_result) \
503 : "b" (_zzq_default), "b" (_zzq_ptr) \
504 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000505 _zzq_result; \
506 })
sewardj1a85f4f2006-01-12 21:15:35 +0000507
sewardjd68ac3e2006-01-20 14:31:57 +0000508#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
509 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000510 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000511 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
512 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000513 "or 2,2,2\n\t" \
514 "mr %0,3" \
515 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000516 : \
sewardj8258a3a2011-10-05 07:39:07 +0000517 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000518 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000519 _zzq_orig->nraddr = __addr; \
520 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
521 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000522 "or 4,4,4\n\t" \
523 "mr %0,3" \
524 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000525 : \
sewardj8258a3a2011-10-05 07:39:07 +0000526 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000527 ); \
528 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000529 }
530
531#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
532 __SPECIAL_INSTRUCTION_PREAMBLE \
533 /* branch-and-link-to-noredir *%R11 */ \
534 "or 3,3,3\n\t"
535
sewardjf5c1a7f2006-10-17 01:32:48 +0000536#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000537
sewardj59570ff2010-01-01 11:59:33 +0000538/* ------------------------- arm-linux ------------------------- */
539
540#if defined(PLAT_arm_linux)
541
542typedef
543 struct {
544 unsigned int nraddr; /* where's the code? */
545 }
546 OrigFn;
547
548#define __SPECIAL_INSTRUCTION_PREAMBLE \
549 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
550 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
551
bart575ce8e2011-05-15 07:04:03 +0000552#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
553 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000554 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
555 \
bart575ce8e2011-05-15 07:04:03 +0000556 __extension__ \
557 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000558 volatile unsigned int _zzq_result; \
559 _zzq_args[0] = (unsigned int)(_zzq_request); \
560 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
561 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
562 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
563 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
564 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
565 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
566 "mov r4, %2\n\t" /*ptr*/ \
567 __SPECIAL_INSTRUCTION_PREAMBLE \
568 /* R3 = client_request ( R4 ) */ \
569 "orr r10, r10, r10\n\t" \
570 "mov %0, r3" /*result*/ \
571 : "=r" (_zzq_result) \
572 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
573 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000574 _zzq_result; \
575 })
sewardj59570ff2010-01-01 11:59:33 +0000576
577#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
578 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
579 unsigned int __addr; \
580 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
581 /* R3 = guest_NRADDR */ \
582 "orr r11, r11, r11\n\t" \
583 "mov %0, r3" \
584 : "=r" (__addr) \
585 : \
586 : "cc", "memory", "r3" \
587 ); \
588 _zzq_orig->nraddr = __addr; \
589 }
590
591#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
592 __SPECIAL_INSTRUCTION_PREAMBLE \
593 /* branch-and-link-to-noredir *%R4 */ \
594 "orr r12, r12, r12\n\t"
595
596#endif /* PLAT_arm_linux */
597
sewardjb5b87402011-03-07 16:05:35 +0000598/* ------------------------ s390x-linux ------------------------ */
599
600#if defined(PLAT_s390x_linux)
601
602typedef
603 struct {
604 unsigned long long int nraddr; /* where's the code? */
605 }
606 OrigFn;
607
608/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
609 * code. This detection is implemented in platform specific toIR.c
610 * (e.g. VEX/priv/guest_s390_decoder.c).
611 */
612#define __SPECIAL_INSTRUCTION_PREAMBLE \
613 "lr 15,15\n\t" \
614 "lr 1,1\n\t" \
615 "lr 2,2\n\t" \
616 "lr 3,3\n\t"
617
618#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
619#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
620#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
621
bart575ce8e2011-05-15 07:04:03 +0000622#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
623 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000624 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000625 __extension__ \
626 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000627 volatile unsigned long long int _zzq_result; \
628 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
629 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
630 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
631 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
632 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
633 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
634 __asm__ volatile(/* r2 = args */ \
635 "lgr 2,%1\n\t" \
636 /* r3 = default */ \
637 "lgr 3,%2\n\t" \
638 __SPECIAL_INSTRUCTION_PREAMBLE \
639 __CLIENT_REQUEST_CODE \
640 /* results = r3 */ \
641 "lgr %0, 3\n\t" \
642 : "=d" (_zzq_result) \
643 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
644 : "cc", "2", "3", "memory" \
645 ); \
bart575ce8e2011-05-15 07:04:03 +0000646 _zzq_result; \
647 })
sewardjb5b87402011-03-07 16:05:35 +0000648
649#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
650 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
651 volatile unsigned long long int __addr; \
652 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
653 __GET_NR_CONTEXT_CODE \
654 "lgr %0, 3\n\t" \
655 : "=a" (__addr) \
656 : \
657 : "cc", "3", "memory" \
658 ); \
659 _zzq_orig->nraddr = __addr; \
660 }
661
662#define VALGRIND_CALL_NOREDIR_R1 \
663 __SPECIAL_INSTRUCTION_PREAMBLE \
664 __CALL_NO_REDIR_CODE
665
666#endif /* PLAT_s390x_linux */
667
sewardjf5c1a7f2006-10-17 01:32:48 +0000668/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000669
sewardj37091fb2002-11-16 11:06:50 +0000670#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000671
nethercote69d9c462004-10-26 13:00:12 +0000672
njn30d76c62005-06-18 15:07:39 +0000673/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000674/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000675/* ugly. It's the least-worst tradeoff I can think of. */
676/* ------------------------------------------------------------------ */
677
678/* This section defines magic (a.k.a appalling-hack) macros for doing
679 guaranteed-no-redirection macros, so as to get from function
680 wrappers to the functions they are wrapping. The whole point is to
681 construct standard call sequences, but to do the call itself with a
682 special no-redirect call pseudo-instruction that the JIT
683 understands and handles specially. This section is long and
684 repetitious, and I can't see a way to make it shorter.
685
686 The naming scheme is as follows:
687
688 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
689
690 'W' stands for "word" and 'v' for "void". Hence there are
691 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
692 and for each, the possibility of returning a word-typed result, or
693 no result.
694*/
695
696/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +0000697 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
698 the default behaviour equivalance class tag "0000" into the name.
699 See pub_tool_redir.h for details -- normally you don't need to
700 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +0000701
njn5f5ef2a2009-05-11 08:01:09 +0000702/* Use an extra level of macroisation so as to ensure the soname/fnname
703 args are fully macro-expanded before pasting them together. */
704#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
705
sewardj0ec07f32006-01-12 12:32:32 +0000706#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000707 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000708
709#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000710 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000711
sewardjd68ac3e2006-01-20 14:31:57 +0000712/* Use this macro from within a wrapper function to collect the
713 context (address and possibly other info) of the original function.
714 Once you have that you can then use it in one of the CALL_FN_
715 macros. The type of the argument _lval is OrigFn. */
716#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000717
sewardj573f8bc2012-06-05 07:12:15 +0000718/* Also provide end-user facilities for function replacement, rather
719 than wrapping. A replacement function differs from a wrapper in
720 that it has no way to get hold of the original function being
721 called, and hence no way to call onwards to it. In a replacement
722 function, VALGRIND_GET_ORIG_FN always returns zero. */
723
724#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
725 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
726
727#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
728 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
729
sewardj0ec07f32006-01-12 12:32:32 +0000730/* Derivatives of the main macros below, for calling functions
731 returning void. */
732
733#define CALL_FN_v_v(fnptr) \
734 do { volatile unsigned long _junk; \
735 CALL_FN_W_v(_junk,fnptr); } while (0)
736
737#define CALL_FN_v_W(fnptr, arg1) \
738 do { volatile unsigned long _junk; \
739 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
740
741#define CALL_FN_v_WW(fnptr, arg1,arg2) \
742 do { volatile unsigned long _junk; \
743 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
744
sewardj5ce4b152006-03-11 12:57:41 +0000745#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
746 do { volatile unsigned long _junk; \
747 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
748
njn2b5f0a92009-05-19 01:24:50 +0000749#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
750 do { volatile unsigned long _junk; \
751 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
752
753#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
754 do { volatile unsigned long _junk; \
755 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
756
757#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
758 do { volatile unsigned long _junk; \
759 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
760
761#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
762 do { volatile unsigned long _junk; \
763 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
764
njnf76d27a2009-05-28 01:53:07 +0000765/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000766
njnf76d27a2009-05-28 01:53:07 +0000767#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000768
769/* These regs are trashed by the hidden call. No need to mention eax
770 as gcc can already see that, plus causes gcc to bomb. */
771#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
772
773/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
774 long) == 4. */
775
sewardj66226cc2006-01-20 15:46:46 +0000776#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000777 do { \
sewardj66226cc2006-01-20 15:46:46 +0000778 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000779 volatile unsigned long _argvec[1]; \
780 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000781 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000782 __asm__ volatile( \
783 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
784 VALGRIND_CALL_NOREDIR_EAX \
785 : /*out*/ "=a" (_res) \
786 : /*in*/ "a" (&_argvec[0]) \
787 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
788 ); \
789 lval = (__typeof__(lval)) _res; \
790 } while (0)
791
sewardj66226cc2006-01-20 15:46:46 +0000792#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000793 do { \
sewardj66226cc2006-01-20 15:46:46 +0000794 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000795 volatile unsigned long _argvec[2]; \
796 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000797 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000798 _argvec[1] = (unsigned long)(arg1); \
799 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000800 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000801 "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
sewardj66226cc2006-01-20 15:46:46 +0000812#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000813 do { \
sewardj66226cc2006-01-20 15:46:46 +0000814 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000815 volatile unsigned long _argvec[3]; \
816 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000817 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000818 _argvec[1] = (unsigned long)(arg1); \
819 _argvec[2] = (unsigned long)(arg2); \
820 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000821 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000822 "pushl 8(%%eax)\n\t" \
823 "pushl 4(%%eax)\n\t" \
824 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
825 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000826 "addl $16, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000827 : /*out*/ "=a" (_res) \
828 : /*in*/ "a" (&_argvec[0]) \
829 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
830 ); \
831 lval = (__typeof__(lval)) _res; \
832 } while (0)
833
sewardj9e8b07a2006-02-18 21:13:29 +0000834#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
835 do { \
836 volatile OrigFn _orig = (orig); \
837 volatile unsigned long _argvec[4]; \
838 volatile unsigned long _res; \
839 _argvec[0] = (unsigned long)_orig.nraddr; \
840 _argvec[1] = (unsigned long)(arg1); \
841 _argvec[2] = (unsigned long)(arg2); \
842 _argvec[3] = (unsigned long)(arg3); \
843 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000844 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +0000845 "pushl 12(%%eax)\n\t" \
846 "pushl 8(%%eax)\n\t" \
847 "pushl 4(%%eax)\n\t" \
848 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
849 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000850 "addl $16, %%esp\n" \
sewardj9e8b07a2006-02-18 21:13:29 +0000851 : /*out*/ "=a" (_res) \
852 : /*in*/ "a" (&_argvec[0]) \
853 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
854 ); \
855 lval = (__typeof__(lval)) _res; \
856 } while (0)
857
sewardj66226cc2006-01-20 15:46:46 +0000858#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000859 do { \
sewardj66226cc2006-01-20 15:46:46 +0000860 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000861 volatile unsigned long _argvec[5]; \
862 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000863 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000864 _argvec[1] = (unsigned long)(arg1); \
865 _argvec[2] = (unsigned long)(arg2); \
866 _argvec[3] = (unsigned long)(arg3); \
867 _argvec[4] = (unsigned long)(arg4); \
868 __asm__ volatile( \
869 "pushl 16(%%eax)\n\t" \
870 "pushl 12(%%eax)\n\t" \
871 "pushl 8(%%eax)\n\t" \
872 "pushl 4(%%eax)\n\t" \
873 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
874 VALGRIND_CALL_NOREDIR_EAX \
875 "addl $16, %%esp\n" \
876 : /*out*/ "=a" (_res) \
877 : /*in*/ "a" (&_argvec[0]) \
878 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
879 ); \
880 lval = (__typeof__(lval)) _res; \
881 } while (0)
882
sewardj66226cc2006-01-20 15:46:46 +0000883#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000884 do { \
sewardj66226cc2006-01-20 15:46:46 +0000885 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000886 volatile unsigned long _argvec[6]; \
887 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000888 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000889 _argvec[1] = (unsigned long)(arg1); \
890 _argvec[2] = (unsigned long)(arg2); \
891 _argvec[3] = (unsigned long)(arg3); \
892 _argvec[4] = (unsigned long)(arg4); \
893 _argvec[5] = (unsigned long)(arg5); \
894 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000895 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000896 "pushl 20(%%eax)\n\t" \
897 "pushl 16(%%eax)\n\t" \
898 "pushl 12(%%eax)\n\t" \
899 "pushl 8(%%eax)\n\t" \
900 "pushl 4(%%eax)\n\t" \
901 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
902 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000903 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000904 : /*out*/ "=a" (_res) \
905 : /*in*/ "a" (&_argvec[0]) \
906 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
907 ); \
908 lval = (__typeof__(lval)) _res; \
909 } while (0)
910
sewardj66226cc2006-01-20 15:46:46 +0000911#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000912 do { \
sewardj66226cc2006-01-20 15:46:46 +0000913 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000914 volatile unsigned long _argvec[7]; \
915 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000916 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000917 _argvec[1] = (unsigned long)(arg1); \
918 _argvec[2] = (unsigned long)(arg2); \
919 _argvec[3] = (unsigned long)(arg3); \
920 _argvec[4] = (unsigned long)(arg4); \
921 _argvec[5] = (unsigned long)(arg5); \
922 _argvec[6] = (unsigned long)(arg6); \
923 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000924 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000925 "pushl 24(%%eax)\n\t" \
926 "pushl 20(%%eax)\n\t" \
927 "pushl 16(%%eax)\n\t" \
928 "pushl 12(%%eax)\n\t" \
929 "pushl 8(%%eax)\n\t" \
930 "pushl 4(%%eax)\n\t" \
931 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
932 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000933 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000934 : /*out*/ "=a" (_res) \
935 : /*in*/ "a" (&_argvec[0]) \
936 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
937 ); \
938 lval = (__typeof__(lval)) _res; \
939 } while (0)
940
sewardj66226cc2006-01-20 15:46:46 +0000941#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
942 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000943 do { \
sewardj66226cc2006-01-20 15:46:46 +0000944 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000945 volatile unsigned long _argvec[8]; \
946 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000947 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000948 _argvec[1] = (unsigned long)(arg1); \
949 _argvec[2] = (unsigned long)(arg2); \
950 _argvec[3] = (unsigned long)(arg3); \
951 _argvec[4] = (unsigned long)(arg4); \
952 _argvec[5] = (unsigned long)(arg5); \
953 _argvec[6] = (unsigned long)(arg6); \
954 _argvec[7] = (unsigned long)(arg7); \
955 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000956 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000957 "pushl 28(%%eax)\n\t" \
958 "pushl 24(%%eax)\n\t" \
959 "pushl 20(%%eax)\n\t" \
960 "pushl 16(%%eax)\n\t" \
961 "pushl 12(%%eax)\n\t" \
962 "pushl 8(%%eax)\n\t" \
963 "pushl 4(%%eax)\n\t" \
964 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
965 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000966 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000967 : /*out*/ "=a" (_res) \
968 : /*in*/ "a" (&_argvec[0]) \
969 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
970 ); \
971 lval = (__typeof__(lval)) _res; \
972 } while (0)
973
sewardj66226cc2006-01-20 15:46:46 +0000974#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
975 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000976 do { \
sewardj66226cc2006-01-20 15:46:46 +0000977 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000978 volatile unsigned long _argvec[9]; \
979 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000980 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000981 _argvec[1] = (unsigned long)(arg1); \
982 _argvec[2] = (unsigned long)(arg2); \
983 _argvec[3] = (unsigned long)(arg3); \
984 _argvec[4] = (unsigned long)(arg4); \
985 _argvec[5] = (unsigned long)(arg5); \
986 _argvec[6] = (unsigned long)(arg6); \
987 _argvec[7] = (unsigned long)(arg7); \
988 _argvec[8] = (unsigned long)(arg8); \
989 __asm__ volatile( \
990 "pushl 32(%%eax)\n\t" \
991 "pushl 28(%%eax)\n\t" \
992 "pushl 24(%%eax)\n\t" \
993 "pushl 20(%%eax)\n\t" \
994 "pushl 16(%%eax)\n\t" \
995 "pushl 12(%%eax)\n\t" \
996 "pushl 8(%%eax)\n\t" \
997 "pushl 4(%%eax)\n\t" \
998 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
999 VALGRIND_CALL_NOREDIR_EAX \
1000 "addl $32, %%esp\n" \
1001 : /*out*/ "=a" (_res) \
1002 : /*in*/ "a" (&_argvec[0]) \
1003 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1004 ); \
1005 lval = (__typeof__(lval)) _res; \
1006 } while (0)
1007
sewardj45fa5b02006-03-09 19:06:23 +00001008#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1009 arg7,arg8,arg9) \
1010 do { \
1011 volatile OrigFn _orig = (orig); \
1012 volatile unsigned long _argvec[10]; \
1013 volatile unsigned long _res; \
1014 _argvec[0] = (unsigned long)_orig.nraddr; \
1015 _argvec[1] = (unsigned long)(arg1); \
1016 _argvec[2] = (unsigned long)(arg2); \
1017 _argvec[3] = (unsigned long)(arg3); \
1018 _argvec[4] = (unsigned long)(arg4); \
1019 _argvec[5] = (unsigned long)(arg5); \
1020 _argvec[6] = (unsigned long)(arg6); \
1021 _argvec[7] = (unsigned long)(arg7); \
1022 _argvec[8] = (unsigned long)(arg8); \
1023 _argvec[9] = (unsigned long)(arg9); \
1024 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001025 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001026 "pushl 36(%%eax)\n\t" \
1027 "pushl 32(%%eax)\n\t" \
1028 "pushl 28(%%eax)\n\t" \
1029 "pushl 24(%%eax)\n\t" \
1030 "pushl 20(%%eax)\n\t" \
1031 "pushl 16(%%eax)\n\t" \
1032 "pushl 12(%%eax)\n\t" \
1033 "pushl 8(%%eax)\n\t" \
1034 "pushl 4(%%eax)\n\t" \
1035 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1036 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001037 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001038 : /*out*/ "=a" (_res) \
1039 : /*in*/ "a" (&_argvec[0]) \
1040 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1041 ); \
1042 lval = (__typeof__(lval)) _res; \
1043 } while (0)
1044
1045#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1046 arg7,arg8,arg9,arg10) \
1047 do { \
1048 volatile OrigFn _orig = (orig); \
1049 volatile unsigned long _argvec[11]; \
1050 volatile unsigned long _res; \
1051 _argvec[0] = (unsigned long)_orig.nraddr; \
1052 _argvec[1] = (unsigned long)(arg1); \
1053 _argvec[2] = (unsigned long)(arg2); \
1054 _argvec[3] = (unsigned long)(arg3); \
1055 _argvec[4] = (unsigned long)(arg4); \
1056 _argvec[5] = (unsigned long)(arg5); \
1057 _argvec[6] = (unsigned long)(arg6); \
1058 _argvec[7] = (unsigned long)(arg7); \
1059 _argvec[8] = (unsigned long)(arg8); \
1060 _argvec[9] = (unsigned long)(arg9); \
1061 _argvec[10] = (unsigned long)(arg10); \
1062 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001063 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001064 "pushl 40(%%eax)\n\t" \
1065 "pushl 36(%%eax)\n\t" \
1066 "pushl 32(%%eax)\n\t" \
1067 "pushl 28(%%eax)\n\t" \
1068 "pushl 24(%%eax)\n\t" \
1069 "pushl 20(%%eax)\n\t" \
1070 "pushl 16(%%eax)\n\t" \
1071 "pushl 12(%%eax)\n\t" \
1072 "pushl 8(%%eax)\n\t" \
1073 "pushl 4(%%eax)\n\t" \
1074 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1075 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001076 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001077 : /*out*/ "=a" (_res) \
1078 : /*in*/ "a" (&_argvec[0]) \
1079 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1080 ); \
1081 lval = (__typeof__(lval)) _res; \
1082 } while (0)
1083
sewardj5ce4b152006-03-11 12:57:41 +00001084#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1085 arg6,arg7,arg8,arg9,arg10, \
1086 arg11) \
1087 do { \
1088 volatile OrigFn _orig = (orig); \
1089 volatile unsigned long _argvec[12]; \
1090 volatile unsigned long _res; \
1091 _argvec[0] = (unsigned long)_orig.nraddr; \
1092 _argvec[1] = (unsigned long)(arg1); \
1093 _argvec[2] = (unsigned long)(arg2); \
1094 _argvec[3] = (unsigned long)(arg3); \
1095 _argvec[4] = (unsigned long)(arg4); \
1096 _argvec[5] = (unsigned long)(arg5); \
1097 _argvec[6] = (unsigned long)(arg6); \
1098 _argvec[7] = (unsigned long)(arg7); \
1099 _argvec[8] = (unsigned long)(arg8); \
1100 _argvec[9] = (unsigned long)(arg9); \
1101 _argvec[10] = (unsigned long)(arg10); \
1102 _argvec[11] = (unsigned long)(arg11); \
1103 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001104 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001105 "pushl 44(%%eax)\n\t" \
1106 "pushl 40(%%eax)\n\t" \
1107 "pushl 36(%%eax)\n\t" \
1108 "pushl 32(%%eax)\n\t" \
1109 "pushl 28(%%eax)\n\t" \
1110 "pushl 24(%%eax)\n\t" \
1111 "pushl 20(%%eax)\n\t" \
1112 "pushl 16(%%eax)\n\t" \
1113 "pushl 12(%%eax)\n\t" \
1114 "pushl 8(%%eax)\n\t" \
1115 "pushl 4(%%eax)\n\t" \
1116 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1117 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001118 "addl $48, %%esp\n" \
sewardj5ce4b152006-03-11 12:57:41 +00001119 : /*out*/ "=a" (_res) \
1120 : /*in*/ "a" (&_argvec[0]) \
1121 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1122 ); \
1123 lval = (__typeof__(lval)) _res; \
1124 } while (0)
1125
sewardj66226cc2006-01-20 15:46:46 +00001126#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1127 arg6,arg7,arg8,arg9,arg10, \
1128 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001129 do { \
sewardj66226cc2006-01-20 15:46:46 +00001130 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001131 volatile unsigned long _argvec[13]; \
1132 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001133 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001134 _argvec[1] = (unsigned long)(arg1); \
1135 _argvec[2] = (unsigned long)(arg2); \
1136 _argvec[3] = (unsigned long)(arg3); \
1137 _argvec[4] = (unsigned long)(arg4); \
1138 _argvec[5] = (unsigned long)(arg5); \
1139 _argvec[6] = (unsigned long)(arg6); \
1140 _argvec[7] = (unsigned long)(arg7); \
1141 _argvec[8] = (unsigned long)(arg8); \
1142 _argvec[9] = (unsigned long)(arg9); \
1143 _argvec[10] = (unsigned long)(arg10); \
1144 _argvec[11] = (unsigned long)(arg11); \
1145 _argvec[12] = (unsigned long)(arg12); \
1146 __asm__ volatile( \
1147 "pushl 48(%%eax)\n\t" \
1148 "pushl 44(%%eax)\n\t" \
1149 "pushl 40(%%eax)\n\t" \
1150 "pushl 36(%%eax)\n\t" \
1151 "pushl 32(%%eax)\n\t" \
1152 "pushl 28(%%eax)\n\t" \
1153 "pushl 24(%%eax)\n\t" \
1154 "pushl 20(%%eax)\n\t" \
1155 "pushl 16(%%eax)\n\t" \
1156 "pushl 12(%%eax)\n\t" \
1157 "pushl 8(%%eax)\n\t" \
1158 "pushl 4(%%eax)\n\t" \
1159 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1160 VALGRIND_CALL_NOREDIR_EAX \
1161 "addl $48, %%esp\n" \
1162 : /*out*/ "=a" (_res) \
1163 : /*in*/ "a" (&_argvec[0]) \
1164 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1165 ); \
1166 lval = (__typeof__(lval)) _res; \
1167 } while (0)
1168
njnf76d27a2009-05-28 01:53:07 +00001169#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001170
njnf76d27a2009-05-28 01:53:07 +00001171/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001172
njnf76d27a2009-05-28 01:53:07 +00001173#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001174
1175/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1176
1177/* These regs are trashed by the hidden call. */
1178#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1179 "rdi", "r8", "r9", "r10", "r11"
1180
sewardjdfa55cf2010-10-06 22:07:06 +00001181/* This is all pretty complex. It's so as to make stack unwinding
1182 work reliably. See bug 243270. The basic problem is the sub and
1183 add of 128 of %rsp in all of the following macros. If gcc believes
1184 the CFA is in %rsp, then unwinding may fail, because what's at the
1185 CFA is not what gcc "expected" when it constructs the CFIs for the
1186 places where the macros are instantiated.
1187
1188 But we can't just add a CFI annotation to increase the CFA offset
1189 by 128, to match the sub of 128 from %rsp, because we don't know
1190 whether gcc has chosen %rsp as the CFA at that point, or whether it
1191 has chosen some other register (eg, %rbp). In the latter case,
1192 adding a CFI annotation to change the CFA offset is simply wrong.
1193
1194 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001195 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001196 CFI annotation to say what the register is. We choose %rbp for
1197 this (perhaps perversely), because:
1198
1199 (1) %rbp is already subject to unwinding. If a new register was
1200 chosen then the unwinder would have to unwind it in all stack
1201 traces, which is expensive, and
1202
1203 (2) %rbp is already subject to precise exception updates in the
1204 JIT. If a new register was chosen, we'd have to have precise
1205 exceptions for it too, which reduces performance of the
1206 generated code.
1207
1208 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001209 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001210 list of trashed registers at the end of the inline assembly
1211 fragments; gcc won't allow %rbp to appear in that list. Hence
1212 instead we need to stash %rbp in %r15 for the duration of the asm,
1213 and say that %r15 is trashed instead. gcc seems happy to go with
1214 that.
1215
1216 Oh .. and this all needs to be conditionalised so that it is
1217 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001218 that don't support __builtin_dwarf_cfa. Furthermore, since
1219 this header file is freestanding, it has to be independent of
1220 config.h, and so the following conditionalisation cannot depend on
1221 configure time checks.
1222
1223 Although it's not clear from
1224 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1225 this expression excludes Darwin.
1226 .cfi directives in Darwin assembly appear to be completely
1227 different and I haven't investigated how they work.
1228
1229 For even more entertainment value, note we have to use the
1230 completely undocumented __builtin_dwarf_cfa(), which appears to
1231 really compute the CFA, whereas __builtin_frame_address(0) claims
1232 to but actually doesn't. See
1233 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001234*/
sewardj8d1dc152010-10-08 17:43:26 +00001235#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001236# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001237 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001238# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001239 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001240 "movq %2, %%rbp\n\t" \
1241 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001242 ".cfi_def_cfa rbp, 0\n\t"
1243# define VALGRIND_CFI_EPILOGUE \
1244 "movq %%r15, %%rbp\n\t" \
1245 ".cfi_restore_state\n\t"
1246#else
1247# define __FRAME_POINTER
1248# define VALGRIND_CFI_PROLOGUE
1249# define VALGRIND_CFI_EPILOGUE
1250#endif
1251
1252
sewardj0ec07f32006-01-12 12:32:32 +00001253/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1254 long) == 8. */
1255
sewardja07c2e12007-11-09 23:09:50 +00001256/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1257 macros. In order not to trash the stack redzone, we need to drop
1258 %rsp by 128 before the hidden call, and restore afterwards. The
1259 nastyness is that it is only by luck that the stack still appears
1260 to be unwindable during the hidden call - since then the behaviour
1261 of any routine using this macro does not match what the CFI data
1262 says. Sigh.
1263
1264 Why is this important? Imagine that a wrapper has a stack
1265 allocated local, and passes to the hidden call, a pointer to it.
1266 Because gcc does not know about the hidden call, it may allocate
1267 that local in the redzone. Unfortunately the hidden call may then
1268 trash it before it comes to use it. So we must step clear of the
1269 redzone, for the duration of the hidden call, to make it safe.
1270
1271 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001272 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001273 self describing (none of this CFI nonsense) so at least messing
1274 with the stack pointer doesn't give a danger of non-unwindable
1275 stack. */
1276
sewardjc8858442006-01-20 15:17:20 +00001277#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001278 do { \
sewardjc8858442006-01-20 15:17:20 +00001279 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001280 volatile unsigned long _argvec[1]; \
1281 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001282 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001283 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001284 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001285 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001286 "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_W(lval, orig, arg1) \
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[2]; \
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 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001305 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001306 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001307 "movq 8(%%rax), %%rdi\n\t" \
1308 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1309 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001310 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001311 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001312 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001313 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1314 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001315 ); \
1316 lval = (__typeof__(lval)) _res; \
1317 } while (0)
1318
sewardjc8858442006-01-20 15:17:20 +00001319#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001320 do { \
sewardjc8858442006-01-20 15:17:20 +00001321 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001322 volatile unsigned long _argvec[3]; \
1323 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001324 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001325 _argvec[1] = (unsigned long)(arg1); \
1326 _argvec[2] = (unsigned long)(arg2); \
1327 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001328 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001329 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001330 "movq 16(%%rax), %%rsi\n\t" \
1331 "movq 8(%%rax), %%rdi\n\t" \
1332 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1333 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001334 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001335 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001336 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001337 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1338 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001339 ); \
1340 lval = (__typeof__(lval)) _res; \
1341 } while (0)
1342
sewardja50f9dc2006-03-11 16:19:14 +00001343#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1344 do { \
1345 volatile OrigFn _orig = (orig); \
1346 volatile unsigned long _argvec[4]; \
1347 volatile unsigned long _res; \
1348 _argvec[0] = (unsigned long)_orig.nraddr; \
1349 _argvec[1] = (unsigned long)(arg1); \
1350 _argvec[2] = (unsigned long)(arg2); \
1351 _argvec[3] = (unsigned long)(arg3); \
1352 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001353 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001354 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001355 "movq 24(%%rax), %%rdx\n\t" \
1356 "movq 16(%%rax), %%rsi\n\t" \
1357 "movq 8(%%rax), %%rdi\n\t" \
1358 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1359 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001360 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001361 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001362 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001363 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1364 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001365 ); \
1366 lval = (__typeof__(lval)) _res; \
1367 } while (0)
1368
1369#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1370 do { \
1371 volatile OrigFn _orig = (orig); \
1372 volatile unsigned long _argvec[5]; \
1373 volatile unsigned long _res; \
1374 _argvec[0] = (unsigned long)_orig.nraddr; \
1375 _argvec[1] = (unsigned long)(arg1); \
1376 _argvec[2] = (unsigned long)(arg2); \
1377 _argvec[3] = (unsigned long)(arg3); \
1378 _argvec[4] = (unsigned long)(arg4); \
1379 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001380 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001381 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001382 "movq 32(%%rax), %%rcx\n\t" \
1383 "movq 24(%%rax), %%rdx\n\t" \
1384 "movq 16(%%rax), %%rsi\n\t" \
1385 "movq 8(%%rax), %%rdi\n\t" \
1386 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1387 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001388 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001389 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001390 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001391 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1392 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001393 ); \
1394 lval = (__typeof__(lval)) _res; \
1395 } while (0)
1396
1397#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1398 do { \
1399 volatile OrigFn _orig = (orig); \
1400 volatile unsigned long _argvec[6]; \
1401 volatile unsigned long _res; \
1402 _argvec[0] = (unsigned long)_orig.nraddr; \
1403 _argvec[1] = (unsigned long)(arg1); \
1404 _argvec[2] = (unsigned long)(arg2); \
1405 _argvec[3] = (unsigned long)(arg3); \
1406 _argvec[4] = (unsigned long)(arg4); \
1407 _argvec[5] = (unsigned long)(arg5); \
1408 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001409 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001410 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001411 "movq 40(%%rax), %%r8\n\t" \
1412 "movq 32(%%rax), %%rcx\n\t" \
1413 "movq 24(%%rax), %%rdx\n\t" \
1414 "movq 16(%%rax), %%rsi\n\t" \
1415 "movq 8(%%rax), %%rdi\n\t" \
1416 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1417 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001418 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001419 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001420 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001421 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1422 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001423 ); \
1424 lval = (__typeof__(lval)) _res; \
1425 } while (0)
1426
1427#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1428 do { \
1429 volatile OrigFn _orig = (orig); \
1430 volatile unsigned long _argvec[7]; \
1431 volatile unsigned long _res; \
1432 _argvec[0] = (unsigned long)_orig.nraddr; \
1433 _argvec[1] = (unsigned long)(arg1); \
1434 _argvec[2] = (unsigned long)(arg2); \
1435 _argvec[3] = (unsigned long)(arg3); \
1436 _argvec[4] = (unsigned long)(arg4); \
1437 _argvec[5] = (unsigned long)(arg5); \
1438 _argvec[6] = (unsigned long)(arg6); \
1439 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001440 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001441 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001442 "movq 48(%%rax), %%r9\n\t" \
1443 "movq 40(%%rax), %%r8\n\t" \
1444 "movq 32(%%rax), %%rcx\n\t" \
1445 "movq 24(%%rax), %%rdx\n\t" \
1446 "movq 16(%%rax), %%rsi\n\t" \
1447 "movq 8(%%rax), %%rdi\n\t" \
1448 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1449 VALGRIND_CALL_NOREDIR_RAX \
bart2823aac2010-09-05 12:10:25 +00001450 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001451 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001452 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001453 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1454 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001455 ); \
1456 lval = (__typeof__(lval)) _res; \
1457 } while (0)
1458
1459#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1460 arg7) \
1461 do { \
1462 volatile OrigFn _orig = (orig); \
1463 volatile unsigned long _argvec[8]; \
1464 volatile unsigned long _res; \
1465 _argvec[0] = (unsigned long)_orig.nraddr; \
1466 _argvec[1] = (unsigned long)(arg1); \
1467 _argvec[2] = (unsigned long)(arg2); \
1468 _argvec[3] = (unsigned long)(arg3); \
1469 _argvec[4] = (unsigned long)(arg4); \
1470 _argvec[5] = (unsigned long)(arg5); \
1471 _argvec[6] = (unsigned long)(arg6); \
1472 _argvec[7] = (unsigned long)(arg7); \
1473 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001474 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001475 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001476 "pushq 56(%%rax)\n\t" \
1477 "movq 48(%%rax), %%r9\n\t" \
1478 "movq 40(%%rax), %%r8\n\t" \
1479 "movq 32(%%rax), %%rcx\n\t" \
1480 "movq 24(%%rax), %%rdx\n\t" \
1481 "movq 16(%%rax), %%rsi\n\t" \
1482 "movq 8(%%rax), %%rdi\n\t" \
1483 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1484 VALGRIND_CALL_NOREDIR_RAX \
1485 "addq $8, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001486 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001487 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001488 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001489 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1490 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001491 ); \
1492 lval = (__typeof__(lval)) _res; \
1493 } while (0)
1494
1495#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1496 arg7,arg8) \
1497 do { \
1498 volatile OrigFn _orig = (orig); \
1499 volatile unsigned long _argvec[9]; \
1500 volatile unsigned long _res; \
1501 _argvec[0] = (unsigned long)_orig.nraddr; \
1502 _argvec[1] = (unsigned long)(arg1); \
1503 _argvec[2] = (unsigned long)(arg2); \
1504 _argvec[3] = (unsigned long)(arg3); \
1505 _argvec[4] = (unsigned long)(arg4); \
1506 _argvec[5] = (unsigned long)(arg5); \
1507 _argvec[6] = (unsigned long)(arg6); \
1508 _argvec[7] = (unsigned long)(arg7); \
1509 _argvec[8] = (unsigned long)(arg8); \
1510 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001511 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001512 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001513 "pushq 64(%%rax)\n\t" \
1514 "pushq 56(%%rax)\n\t" \
1515 "movq 48(%%rax), %%r9\n\t" \
1516 "movq 40(%%rax), %%r8\n\t" \
1517 "movq 32(%%rax), %%rcx\n\t" \
1518 "movq 24(%%rax), %%rdx\n\t" \
1519 "movq 16(%%rax), %%rsi\n\t" \
1520 "movq 8(%%rax), %%rdi\n\t" \
1521 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1522 VALGRIND_CALL_NOREDIR_RAX \
1523 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001524 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001525 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001526 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001527 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1528 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001529 ); \
1530 lval = (__typeof__(lval)) _res; \
1531 } while (0)
1532
1533#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1534 arg7,arg8,arg9) \
1535 do { \
1536 volatile OrigFn _orig = (orig); \
1537 volatile unsigned long _argvec[10]; \
1538 volatile unsigned long _res; \
1539 _argvec[0] = (unsigned long)_orig.nraddr; \
1540 _argvec[1] = (unsigned long)(arg1); \
1541 _argvec[2] = (unsigned long)(arg2); \
1542 _argvec[3] = (unsigned long)(arg3); \
1543 _argvec[4] = (unsigned long)(arg4); \
1544 _argvec[5] = (unsigned long)(arg5); \
1545 _argvec[6] = (unsigned long)(arg6); \
1546 _argvec[7] = (unsigned long)(arg7); \
1547 _argvec[8] = (unsigned long)(arg8); \
1548 _argvec[9] = (unsigned long)(arg9); \
1549 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001550 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001551 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001552 "pushq 72(%%rax)\n\t" \
1553 "pushq 64(%%rax)\n\t" \
1554 "pushq 56(%%rax)\n\t" \
1555 "movq 48(%%rax), %%r9\n\t" \
1556 "movq 40(%%rax), %%r8\n\t" \
1557 "movq 32(%%rax), %%rcx\n\t" \
1558 "movq 24(%%rax), %%rdx\n\t" \
1559 "movq 16(%%rax), %%rsi\n\t" \
1560 "movq 8(%%rax), %%rdi\n\t" \
1561 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1562 VALGRIND_CALL_NOREDIR_RAX \
1563 "addq $24, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001564 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001565 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001566 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001567 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1568 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001569 ); \
1570 lval = (__typeof__(lval)) _res; \
1571 } while (0)
1572
1573#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1574 arg7,arg8,arg9,arg10) \
1575 do { \
1576 volatile OrigFn _orig = (orig); \
1577 volatile unsigned long _argvec[11]; \
1578 volatile unsigned long _res; \
1579 _argvec[0] = (unsigned long)_orig.nraddr; \
1580 _argvec[1] = (unsigned long)(arg1); \
1581 _argvec[2] = (unsigned long)(arg2); \
1582 _argvec[3] = (unsigned long)(arg3); \
1583 _argvec[4] = (unsigned long)(arg4); \
1584 _argvec[5] = (unsigned long)(arg5); \
1585 _argvec[6] = (unsigned long)(arg6); \
1586 _argvec[7] = (unsigned long)(arg7); \
1587 _argvec[8] = (unsigned long)(arg8); \
1588 _argvec[9] = (unsigned long)(arg9); \
1589 _argvec[10] = (unsigned long)(arg10); \
1590 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001591 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001592 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001593 "pushq 80(%%rax)\n\t" \
1594 "pushq 72(%%rax)\n\t" \
1595 "pushq 64(%%rax)\n\t" \
1596 "pushq 56(%%rax)\n\t" \
1597 "movq 48(%%rax), %%r9\n\t" \
1598 "movq 40(%%rax), %%r8\n\t" \
1599 "movq 32(%%rax), %%rcx\n\t" \
1600 "movq 24(%%rax), %%rdx\n\t" \
1601 "movq 16(%%rax), %%rsi\n\t" \
1602 "movq 8(%%rax), %%rdi\n\t" \
1603 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1604 VALGRIND_CALL_NOREDIR_RAX \
1605 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001606 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001607 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001608 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001609 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1610 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001611 ); \
1612 lval = (__typeof__(lval)) _res; \
1613 } while (0)
1614
1615#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1616 arg7,arg8,arg9,arg10,arg11) \
1617 do { \
1618 volatile OrigFn _orig = (orig); \
1619 volatile unsigned long _argvec[12]; \
1620 volatile unsigned long _res; \
1621 _argvec[0] = (unsigned long)_orig.nraddr; \
1622 _argvec[1] = (unsigned long)(arg1); \
1623 _argvec[2] = (unsigned long)(arg2); \
1624 _argvec[3] = (unsigned long)(arg3); \
1625 _argvec[4] = (unsigned long)(arg4); \
1626 _argvec[5] = (unsigned long)(arg5); \
1627 _argvec[6] = (unsigned long)(arg6); \
1628 _argvec[7] = (unsigned long)(arg7); \
1629 _argvec[8] = (unsigned long)(arg8); \
1630 _argvec[9] = (unsigned long)(arg9); \
1631 _argvec[10] = (unsigned long)(arg10); \
1632 _argvec[11] = (unsigned long)(arg11); \
1633 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001634 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001635 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001636 "pushq 88(%%rax)\n\t" \
1637 "pushq 80(%%rax)\n\t" \
1638 "pushq 72(%%rax)\n\t" \
1639 "pushq 64(%%rax)\n\t" \
1640 "pushq 56(%%rax)\n\t" \
1641 "movq 48(%%rax), %%r9\n\t" \
1642 "movq 40(%%rax), %%r8\n\t" \
1643 "movq 32(%%rax), %%rcx\n\t" \
1644 "movq 24(%%rax), %%rdx\n\t" \
1645 "movq 16(%%rax), %%rsi\n\t" \
1646 "movq 8(%%rax), %%rdi\n\t" \
1647 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1648 VALGRIND_CALL_NOREDIR_RAX \
1649 "addq $40, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001650 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001651 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001652 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001653 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1654 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001655 ); \
1656 lval = (__typeof__(lval)) _res; \
1657 } while (0)
1658
1659#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1660 arg7,arg8,arg9,arg10,arg11,arg12) \
1661 do { \
1662 volatile OrigFn _orig = (orig); \
1663 volatile unsigned long _argvec[13]; \
1664 volatile unsigned long _res; \
1665 _argvec[0] = (unsigned long)_orig.nraddr; \
1666 _argvec[1] = (unsigned long)(arg1); \
1667 _argvec[2] = (unsigned long)(arg2); \
1668 _argvec[3] = (unsigned long)(arg3); \
1669 _argvec[4] = (unsigned long)(arg4); \
1670 _argvec[5] = (unsigned long)(arg5); \
1671 _argvec[6] = (unsigned long)(arg6); \
1672 _argvec[7] = (unsigned long)(arg7); \
1673 _argvec[8] = (unsigned long)(arg8); \
1674 _argvec[9] = (unsigned long)(arg9); \
1675 _argvec[10] = (unsigned long)(arg10); \
1676 _argvec[11] = (unsigned long)(arg11); \
1677 _argvec[12] = (unsigned long)(arg12); \
1678 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001679 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001680 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001681 "pushq 96(%%rax)\n\t" \
1682 "pushq 88(%%rax)\n\t" \
1683 "pushq 80(%%rax)\n\t" \
1684 "pushq 72(%%rax)\n\t" \
1685 "pushq 64(%%rax)\n\t" \
1686 "pushq 56(%%rax)\n\t" \
1687 "movq 48(%%rax), %%r9\n\t" \
1688 "movq 40(%%rax), %%r8\n\t" \
1689 "movq 32(%%rax), %%rcx\n\t" \
1690 "movq 24(%%rax), %%rdx\n\t" \
1691 "movq 16(%%rax), %%rsi\n\t" \
1692 "movq 8(%%rax), %%rdi\n\t" \
1693 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1694 VALGRIND_CALL_NOREDIR_RAX \
1695 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001696 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001697 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001698 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001699 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1700 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001701 ); \
1702 lval = (__typeof__(lval)) _res; \
1703 } while (0)
1704
njnf76d27a2009-05-28 01:53:07 +00001705#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001706
sewardjf5c1a7f2006-10-17 01:32:48 +00001707/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001708
sewardjf5c1a7f2006-10-17 01:32:48 +00001709#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001710
sewardjead61df2006-03-12 13:39:15 +00001711/* This is useful for finding out about the on-stack stuff:
1712
1713 extern int f9 ( int,int,int,int,int,int,int,int,int );
1714 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1715 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1716 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1717
1718 int g9 ( void ) {
1719 return f9(11,22,33,44,55,66,77,88,99);
1720 }
1721 int g10 ( void ) {
1722 return f10(11,22,33,44,55,66,77,88,99,110);
1723 }
1724 int g11 ( void ) {
1725 return f11(11,22,33,44,55,66,77,88,99,110,121);
1726 }
1727 int g12 ( void ) {
1728 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1729 }
1730*/
1731
sewardj0ec07f32006-01-12 12:32:32 +00001732/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1733
1734/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001735#define __CALLER_SAVED_REGS \
1736 "lr", "ctr", "xer", \
1737 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1738 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1739 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001740
sewardjead61df2006-03-12 13:39:15 +00001741/* These CALL_FN_ macros assume that on ppc32-linux,
1742 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001743
sewardj38de0992006-01-20 16:46:34 +00001744#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001745 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001746 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001747 volatile unsigned long _argvec[1]; \
1748 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001749 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001750 __asm__ volatile( \
1751 "mr 11,%1\n\t" \
1752 "lwz 11,0(11)\n\t" /* target->r11 */ \
1753 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1754 "mr %0,3" \
1755 : /*out*/ "=r" (_res) \
1756 : /*in*/ "r" (&_argvec[0]) \
1757 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1758 ); \
1759 lval = (__typeof__(lval)) _res; \
1760 } while (0)
1761
sewardj38de0992006-01-20 16:46:34 +00001762#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001763 do { \
sewardj38de0992006-01-20 16:46:34 +00001764 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001765 volatile unsigned long _argvec[2]; \
1766 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001767 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001768 _argvec[1] = (unsigned long)arg1; \
1769 __asm__ volatile( \
1770 "mr 11,%1\n\t" \
1771 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
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
sewardj38de0992006-01-20 16:46:34 +00001782#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001783 do { \
sewardj38de0992006-01-20 16:46:34 +00001784 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001785 volatile unsigned long _argvec[3]; \
1786 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001787 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001788 _argvec[1] = (unsigned long)arg1; \
1789 _argvec[2] = (unsigned long)arg2; \
1790 __asm__ volatile( \
1791 "mr 11,%1\n\t" \
1792 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1793 "lwz 4,8(11)\n\t" \
1794 "lwz 11,0(11)\n\t" /* target->r11 */ \
1795 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1796 "mr %0,3" \
1797 : /*out*/ "=r" (_res) \
1798 : /*in*/ "r" (&_argvec[0]) \
1799 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1800 ); \
1801 lval = (__typeof__(lval)) _res; \
1802 } while (0)
1803
sewardjead61df2006-03-12 13:39:15 +00001804#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1805 do { \
1806 volatile OrigFn _orig = (orig); \
1807 volatile unsigned long _argvec[4]; \
1808 volatile unsigned long _res; \
1809 _argvec[0] = (unsigned long)_orig.nraddr; \
1810 _argvec[1] = (unsigned long)arg1; \
1811 _argvec[2] = (unsigned long)arg2; \
1812 _argvec[3] = (unsigned long)arg3; \
1813 __asm__ volatile( \
1814 "mr 11,%1\n\t" \
1815 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1816 "lwz 4,8(11)\n\t" \
1817 "lwz 5,12(11)\n\t" \
1818 "lwz 11,0(11)\n\t" /* target->r11 */ \
1819 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1820 "mr %0,3" \
1821 : /*out*/ "=r" (_res) \
1822 : /*in*/ "r" (&_argvec[0]) \
1823 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1824 ); \
1825 lval = (__typeof__(lval)) _res; \
1826 } while (0)
1827
1828#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1829 do { \
1830 volatile OrigFn _orig = (orig); \
1831 volatile unsigned long _argvec[5]; \
1832 volatile unsigned long _res; \
1833 _argvec[0] = (unsigned long)_orig.nraddr; \
1834 _argvec[1] = (unsigned long)arg1; \
1835 _argvec[2] = (unsigned long)arg2; \
1836 _argvec[3] = (unsigned long)arg3; \
1837 _argvec[4] = (unsigned long)arg4; \
1838 __asm__ volatile( \
1839 "mr 11,%1\n\t" \
1840 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1841 "lwz 4,8(11)\n\t" \
1842 "lwz 5,12(11)\n\t" \
1843 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1844 "lwz 11,0(11)\n\t" /* target->r11 */ \
1845 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1846 "mr %0,3" \
1847 : /*out*/ "=r" (_res) \
1848 : /*in*/ "r" (&_argvec[0]) \
1849 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1850 ); \
1851 lval = (__typeof__(lval)) _res; \
1852 } while (0)
1853
1854#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1855 do { \
1856 volatile OrigFn _orig = (orig); \
1857 volatile unsigned long _argvec[6]; \
1858 volatile unsigned long _res; \
1859 _argvec[0] = (unsigned long)_orig.nraddr; \
1860 _argvec[1] = (unsigned long)arg1; \
1861 _argvec[2] = (unsigned long)arg2; \
1862 _argvec[3] = (unsigned long)arg3; \
1863 _argvec[4] = (unsigned long)arg4; \
1864 _argvec[5] = (unsigned long)arg5; \
1865 __asm__ volatile( \
1866 "mr 11,%1\n\t" \
1867 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1868 "lwz 4,8(11)\n\t" \
1869 "lwz 5,12(11)\n\t" \
1870 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1871 "lwz 7,20(11)\n\t" \
1872 "lwz 11,0(11)\n\t" /* target->r11 */ \
1873 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1874 "mr %0,3" \
1875 : /*out*/ "=r" (_res) \
1876 : /*in*/ "r" (&_argvec[0]) \
1877 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1878 ); \
1879 lval = (__typeof__(lval)) _res; \
1880 } while (0)
1881
1882#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1883 do { \
1884 volatile OrigFn _orig = (orig); \
1885 volatile unsigned long _argvec[7]; \
1886 volatile unsigned long _res; \
1887 _argvec[0] = (unsigned long)_orig.nraddr; \
1888 _argvec[1] = (unsigned long)arg1; \
1889 _argvec[2] = (unsigned long)arg2; \
1890 _argvec[3] = (unsigned long)arg3; \
1891 _argvec[4] = (unsigned long)arg4; \
1892 _argvec[5] = (unsigned long)arg5; \
1893 _argvec[6] = (unsigned long)arg6; \
1894 __asm__ volatile( \
1895 "mr 11,%1\n\t" \
1896 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1897 "lwz 4,8(11)\n\t" \
1898 "lwz 5,12(11)\n\t" \
1899 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1900 "lwz 7,20(11)\n\t" \
1901 "lwz 8,24(11)\n\t" \
1902 "lwz 11,0(11)\n\t" /* target->r11 */ \
1903 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1904 "mr %0,3" \
1905 : /*out*/ "=r" (_res) \
1906 : /*in*/ "r" (&_argvec[0]) \
1907 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1908 ); \
1909 lval = (__typeof__(lval)) _res; \
1910 } while (0)
1911
1912#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1913 arg7) \
1914 do { \
1915 volatile OrigFn _orig = (orig); \
1916 volatile unsigned long _argvec[8]; \
1917 volatile unsigned long _res; \
1918 _argvec[0] = (unsigned long)_orig.nraddr; \
1919 _argvec[1] = (unsigned long)arg1; \
1920 _argvec[2] = (unsigned long)arg2; \
1921 _argvec[3] = (unsigned long)arg3; \
1922 _argvec[4] = (unsigned long)arg4; \
1923 _argvec[5] = (unsigned long)arg5; \
1924 _argvec[6] = (unsigned long)arg6; \
1925 _argvec[7] = (unsigned long)arg7; \
1926 __asm__ volatile( \
1927 "mr 11,%1\n\t" \
1928 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1929 "lwz 4,8(11)\n\t" \
1930 "lwz 5,12(11)\n\t" \
1931 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1932 "lwz 7,20(11)\n\t" \
1933 "lwz 8,24(11)\n\t" \
1934 "lwz 9,28(11)\n\t" \
1935 "lwz 11,0(11)\n\t" /* target->r11 */ \
1936 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1937 "mr %0,3" \
1938 : /*out*/ "=r" (_res) \
1939 : /*in*/ "r" (&_argvec[0]) \
1940 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1941 ); \
1942 lval = (__typeof__(lval)) _res; \
1943 } while (0)
1944
1945#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1946 arg7,arg8) \
1947 do { \
1948 volatile OrigFn _orig = (orig); \
1949 volatile unsigned long _argvec[9]; \
1950 volatile unsigned long _res; \
1951 _argvec[0] = (unsigned long)_orig.nraddr; \
1952 _argvec[1] = (unsigned long)arg1; \
1953 _argvec[2] = (unsigned long)arg2; \
1954 _argvec[3] = (unsigned long)arg3; \
1955 _argvec[4] = (unsigned long)arg4; \
1956 _argvec[5] = (unsigned long)arg5; \
1957 _argvec[6] = (unsigned long)arg6; \
1958 _argvec[7] = (unsigned long)arg7; \
1959 _argvec[8] = (unsigned long)arg8; \
1960 __asm__ volatile( \
1961 "mr 11,%1\n\t" \
1962 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1963 "lwz 4,8(11)\n\t" \
1964 "lwz 5,12(11)\n\t" \
1965 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1966 "lwz 7,20(11)\n\t" \
1967 "lwz 8,24(11)\n\t" \
1968 "lwz 9,28(11)\n\t" \
1969 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1970 "lwz 11,0(11)\n\t" /* target->r11 */ \
1971 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1972 "mr %0,3" \
1973 : /*out*/ "=r" (_res) \
1974 : /*in*/ "r" (&_argvec[0]) \
1975 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1976 ); \
1977 lval = (__typeof__(lval)) _res; \
1978 } while (0)
1979
1980#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1981 arg7,arg8,arg9) \
1982 do { \
1983 volatile OrigFn _orig = (orig); \
1984 volatile unsigned long _argvec[10]; \
1985 volatile unsigned long _res; \
1986 _argvec[0] = (unsigned long)_orig.nraddr; \
1987 _argvec[1] = (unsigned long)arg1; \
1988 _argvec[2] = (unsigned long)arg2; \
1989 _argvec[3] = (unsigned long)arg3; \
1990 _argvec[4] = (unsigned long)arg4; \
1991 _argvec[5] = (unsigned long)arg5; \
1992 _argvec[6] = (unsigned long)arg6; \
1993 _argvec[7] = (unsigned long)arg7; \
1994 _argvec[8] = (unsigned long)arg8; \
1995 _argvec[9] = (unsigned long)arg9; \
1996 __asm__ volatile( \
1997 "mr 11,%1\n\t" \
1998 "addi 1,1,-16\n\t" \
1999 /* arg9 */ \
2000 "lwz 3,36(11)\n\t" \
2001 "stw 3,8(1)\n\t" \
2002 /* args1-8 */ \
2003 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2004 "lwz 4,8(11)\n\t" \
2005 "lwz 5,12(11)\n\t" \
2006 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2007 "lwz 7,20(11)\n\t" \
2008 "lwz 8,24(11)\n\t" \
2009 "lwz 9,28(11)\n\t" \
2010 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2011 "lwz 11,0(11)\n\t" /* target->r11 */ \
2012 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2013 "addi 1,1,16\n\t" \
2014 "mr %0,3" \
2015 : /*out*/ "=r" (_res) \
2016 : /*in*/ "r" (&_argvec[0]) \
2017 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2018 ); \
2019 lval = (__typeof__(lval)) _res; \
2020 } while (0)
2021
2022#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2023 arg7,arg8,arg9,arg10) \
2024 do { \
2025 volatile OrigFn _orig = (orig); \
2026 volatile unsigned long _argvec[11]; \
2027 volatile unsigned long _res; \
2028 _argvec[0] = (unsigned long)_orig.nraddr; \
2029 _argvec[1] = (unsigned long)arg1; \
2030 _argvec[2] = (unsigned long)arg2; \
2031 _argvec[3] = (unsigned long)arg3; \
2032 _argvec[4] = (unsigned long)arg4; \
2033 _argvec[5] = (unsigned long)arg5; \
2034 _argvec[6] = (unsigned long)arg6; \
2035 _argvec[7] = (unsigned long)arg7; \
2036 _argvec[8] = (unsigned long)arg8; \
2037 _argvec[9] = (unsigned long)arg9; \
2038 _argvec[10] = (unsigned long)arg10; \
2039 __asm__ volatile( \
2040 "mr 11,%1\n\t" \
2041 "addi 1,1,-16\n\t" \
2042 /* arg10 */ \
2043 "lwz 3,40(11)\n\t" \
2044 "stw 3,12(1)\n\t" \
2045 /* arg9 */ \
2046 "lwz 3,36(11)\n\t" \
2047 "stw 3,8(1)\n\t" \
2048 /* args1-8 */ \
2049 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2050 "lwz 4,8(11)\n\t" \
2051 "lwz 5,12(11)\n\t" \
2052 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2053 "lwz 7,20(11)\n\t" \
2054 "lwz 8,24(11)\n\t" \
2055 "lwz 9,28(11)\n\t" \
2056 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2057 "lwz 11,0(11)\n\t" /* target->r11 */ \
2058 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2059 "addi 1,1,16\n\t" \
2060 "mr %0,3" \
2061 : /*out*/ "=r" (_res) \
2062 : /*in*/ "r" (&_argvec[0]) \
2063 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2064 ); \
2065 lval = (__typeof__(lval)) _res; \
2066 } while (0)
2067
2068#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2069 arg7,arg8,arg9,arg10,arg11) \
2070 do { \
2071 volatile OrigFn _orig = (orig); \
2072 volatile unsigned long _argvec[12]; \
2073 volatile unsigned long _res; \
2074 _argvec[0] = (unsigned long)_orig.nraddr; \
2075 _argvec[1] = (unsigned long)arg1; \
2076 _argvec[2] = (unsigned long)arg2; \
2077 _argvec[3] = (unsigned long)arg3; \
2078 _argvec[4] = (unsigned long)arg4; \
2079 _argvec[5] = (unsigned long)arg5; \
2080 _argvec[6] = (unsigned long)arg6; \
2081 _argvec[7] = (unsigned long)arg7; \
2082 _argvec[8] = (unsigned long)arg8; \
2083 _argvec[9] = (unsigned long)arg9; \
2084 _argvec[10] = (unsigned long)arg10; \
2085 _argvec[11] = (unsigned long)arg11; \
2086 __asm__ volatile( \
2087 "mr 11,%1\n\t" \
2088 "addi 1,1,-32\n\t" \
2089 /* arg11 */ \
2090 "lwz 3,44(11)\n\t" \
2091 "stw 3,16(1)\n\t" \
2092 /* arg10 */ \
2093 "lwz 3,40(11)\n\t" \
2094 "stw 3,12(1)\n\t" \
2095 /* arg9 */ \
2096 "lwz 3,36(11)\n\t" \
2097 "stw 3,8(1)\n\t" \
2098 /* args1-8 */ \
2099 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2100 "lwz 4,8(11)\n\t" \
2101 "lwz 5,12(11)\n\t" \
2102 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2103 "lwz 7,20(11)\n\t" \
2104 "lwz 8,24(11)\n\t" \
2105 "lwz 9,28(11)\n\t" \
2106 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2107 "lwz 11,0(11)\n\t" /* target->r11 */ \
2108 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2109 "addi 1,1,32\n\t" \
2110 "mr %0,3" \
2111 : /*out*/ "=r" (_res) \
2112 : /*in*/ "r" (&_argvec[0]) \
2113 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2114 ); \
2115 lval = (__typeof__(lval)) _res; \
2116 } while (0)
2117
2118#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2119 arg7,arg8,arg9,arg10,arg11,arg12) \
2120 do { \
2121 volatile OrigFn _orig = (orig); \
2122 volatile unsigned long _argvec[13]; \
2123 volatile unsigned long _res; \
2124 _argvec[0] = (unsigned long)_orig.nraddr; \
2125 _argvec[1] = (unsigned long)arg1; \
2126 _argvec[2] = (unsigned long)arg2; \
2127 _argvec[3] = (unsigned long)arg3; \
2128 _argvec[4] = (unsigned long)arg4; \
2129 _argvec[5] = (unsigned long)arg5; \
2130 _argvec[6] = (unsigned long)arg6; \
2131 _argvec[7] = (unsigned long)arg7; \
2132 _argvec[8] = (unsigned long)arg8; \
2133 _argvec[9] = (unsigned long)arg9; \
2134 _argvec[10] = (unsigned long)arg10; \
2135 _argvec[11] = (unsigned long)arg11; \
2136 _argvec[12] = (unsigned long)arg12; \
2137 __asm__ volatile( \
2138 "mr 11,%1\n\t" \
2139 "addi 1,1,-32\n\t" \
2140 /* arg12 */ \
2141 "lwz 3,48(11)\n\t" \
2142 "stw 3,20(1)\n\t" \
2143 /* arg11 */ \
2144 "lwz 3,44(11)\n\t" \
2145 "stw 3,16(1)\n\t" \
2146 /* arg10 */ \
2147 "lwz 3,40(11)\n\t" \
2148 "stw 3,12(1)\n\t" \
2149 /* arg9 */ \
2150 "lwz 3,36(11)\n\t" \
2151 "stw 3,8(1)\n\t" \
2152 /* args1-8 */ \
2153 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2154 "lwz 4,8(11)\n\t" \
2155 "lwz 5,12(11)\n\t" \
2156 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2157 "lwz 7,20(11)\n\t" \
2158 "lwz 8,24(11)\n\t" \
2159 "lwz 9,28(11)\n\t" \
2160 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2161 "lwz 11,0(11)\n\t" /* target->r11 */ \
2162 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2163 "addi 1,1,32\n\t" \
2164 "mr %0,3" \
2165 : /*out*/ "=r" (_res) \
2166 : /*in*/ "r" (&_argvec[0]) \
2167 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2168 ); \
2169 lval = (__typeof__(lval)) _res; \
2170 } while (0)
2171
sewardjf5c1a7f2006-10-17 01:32:48 +00002172#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002173
sewardjf5c1a7f2006-10-17 01:32:48 +00002174/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002175
sewardjf5c1a7f2006-10-17 01:32:48 +00002176#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002177
2178/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2179
2180/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002181#define __CALLER_SAVED_REGS \
2182 "lr", "ctr", "xer", \
2183 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2184 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2185 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002186
2187/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2188 long) == 8. */
2189
sewardjd68ac3e2006-01-20 14:31:57 +00002190#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002191 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002192 volatile OrigFn _orig = (orig); \
2193 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002194 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002195 /* _argvec[0] holds current r2 across the call */ \
2196 _argvec[1] = (unsigned long)_orig.r2; \
2197 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002198 __asm__ volatile( \
2199 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002200 "std 2,-16(11)\n\t" /* save tocptr */ \
2201 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2202 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002203 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2204 "mr 11,%1\n\t" \
2205 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002206 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002207 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002208 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002209 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2210 ); \
2211 lval = (__typeof__(lval)) _res; \
2212 } while (0)
2213
sewardjd68ac3e2006-01-20 14:31:57 +00002214#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002215 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002216 volatile OrigFn _orig = (orig); \
2217 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002218 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002219 /* _argvec[0] holds current r2 across the call */ \
2220 _argvec[1] = (unsigned long)_orig.r2; \
2221 _argvec[2] = (unsigned long)_orig.nraddr; \
2222 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002223 __asm__ volatile( \
2224 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002225 "std 2,-16(11)\n\t" /* save tocptr */ \
2226 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2227 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2228 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002229 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2230 "mr 11,%1\n\t" \
2231 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002232 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002233 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002234 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002235 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2236 ); \
2237 lval = (__typeof__(lval)) _res; \
2238 } while (0)
2239
sewardjd68ac3e2006-01-20 14:31:57 +00002240#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002241 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002242 volatile OrigFn _orig = (orig); \
2243 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002244 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002245 /* _argvec[0] holds current r2 across the call */ \
2246 _argvec[1] = (unsigned long)_orig.r2; \
2247 _argvec[2] = (unsigned long)_orig.nraddr; \
2248 _argvec[2+1] = (unsigned long)arg1; \
2249 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002250 __asm__ volatile( \
2251 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002252 "std 2,-16(11)\n\t" /* save tocptr */ \
2253 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2254 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002255 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002256 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002257 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2258 "mr 11,%1\n\t" \
2259 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002260 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002261 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002262 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2264 ); \
2265 lval = (__typeof__(lval)) _res; \
2266 } while (0)
2267
sewardjcd636392006-03-12 16:48:14 +00002268#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2269 do { \
2270 volatile OrigFn _orig = (orig); \
2271 volatile unsigned long _argvec[3+3]; \
2272 volatile unsigned long _res; \
2273 /* _argvec[0] holds current r2 across the call */ \
2274 _argvec[1] = (unsigned long)_orig.r2; \
2275 _argvec[2] = (unsigned long)_orig.nraddr; \
2276 _argvec[2+1] = (unsigned long)arg1; \
2277 _argvec[2+2] = (unsigned long)arg2; \
2278 _argvec[2+3] = (unsigned long)arg3; \
2279 __asm__ volatile( \
2280 "mr 11,%1\n\t" \
2281 "std 2,-16(11)\n\t" /* save tocptr */ \
2282 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2283 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2284 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2285 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2286 "ld 11, 0(11)\n\t" /* target->r11 */ \
2287 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2288 "mr 11,%1\n\t" \
2289 "mr %0,3\n\t" \
2290 "ld 2,-16(11)" /* restore tocptr */ \
2291 : /*out*/ "=r" (_res) \
2292 : /*in*/ "r" (&_argvec[2]) \
2293 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2294 ); \
2295 lval = (__typeof__(lval)) _res; \
2296 } while (0)
2297
2298#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2299 do { \
2300 volatile OrigFn _orig = (orig); \
2301 volatile unsigned long _argvec[3+4]; \
2302 volatile unsigned long _res; \
2303 /* _argvec[0] holds current r2 across the call */ \
2304 _argvec[1] = (unsigned long)_orig.r2; \
2305 _argvec[2] = (unsigned long)_orig.nraddr; \
2306 _argvec[2+1] = (unsigned long)arg1; \
2307 _argvec[2+2] = (unsigned long)arg2; \
2308 _argvec[2+3] = (unsigned long)arg3; \
2309 _argvec[2+4] = (unsigned long)arg4; \
2310 __asm__ volatile( \
2311 "mr 11,%1\n\t" \
2312 "std 2,-16(11)\n\t" /* save tocptr */ \
2313 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2314 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2315 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2316 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2317 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2318 "ld 11, 0(11)\n\t" /* target->r11 */ \
2319 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2320 "mr 11,%1\n\t" \
2321 "mr %0,3\n\t" \
2322 "ld 2,-16(11)" /* restore tocptr */ \
2323 : /*out*/ "=r" (_res) \
2324 : /*in*/ "r" (&_argvec[2]) \
2325 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2326 ); \
2327 lval = (__typeof__(lval)) _res; \
2328 } while (0)
2329
2330#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2331 do { \
2332 volatile OrigFn _orig = (orig); \
2333 volatile unsigned long _argvec[3+5]; \
2334 volatile unsigned long _res; \
2335 /* _argvec[0] holds current r2 across the call */ \
2336 _argvec[1] = (unsigned long)_orig.r2; \
2337 _argvec[2] = (unsigned long)_orig.nraddr; \
2338 _argvec[2+1] = (unsigned long)arg1; \
2339 _argvec[2+2] = (unsigned long)arg2; \
2340 _argvec[2+3] = (unsigned long)arg3; \
2341 _argvec[2+4] = (unsigned long)arg4; \
2342 _argvec[2+5] = (unsigned long)arg5; \
2343 __asm__ volatile( \
2344 "mr 11,%1\n\t" \
2345 "std 2,-16(11)\n\t" /* save tocptr */ \
2346 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2347 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2348 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2349 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2350 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2351 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2352 "ld 11, 0(11)\n\t" /* target->r11 */ \
2353 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2354 "mr 11,%1\n\t" \
2355 "mr %0,3\n\t" \
2356 "ld 2,-16(11)" /* restore tocptr */ \
2357 : /*out*/ "=r" (_res) \
2358 : /*in*/ "r" (&_argvec[2]) \
2359 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2360 ); \
2361 lval = (__typeof__(lval)) _res; \
2362 } while (0)
2363
2364#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2365 do { \
2366 volatile OrigFn _orig = (orig); \
2367 volatile unsigned long _argvec[3+6]; \
2368 volatile unsigned long _res; \
2369 /* _argvec[0] holds current r2 across the call */ \
2370 _argvec[1] = (unsigned long)_orig.r2; \
2371 _argvec[2] = (unsigned long)_orig.nraddr; \
2372 _argvec[2+1] = (unsigned long)arg1; \
2373 _argvec[2+2] = (unsigned long)arg2; \
2374 _argvec[2+3] = (unsigned long)arg3; \
2375 _argvec[2+4] = (unsigned long)arg4; \
2376 _argvec[2+5] = (unsigned long)arg5; \
2377 _argvec[2+6] = (unsigned long)arg6; \
2378 __asm__ volatile( \
2379 "mr 11,%1\n\t" \
2380 "std 2,-16(11)\n\t" /* save tocptr */ \
2381 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2382 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2383 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2384 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2385 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2386 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2387 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2388 "ld 11, 0(11)\n\t" /* target->r11 */ \
2389 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2390 "mr 11,%1\n\t" \
2391 "mr %0,3\n\t" \
2392 "ld 2,-16(11)" /* restore tocptr */ \
2393 : /*out*/ "=r" (_res) \
2394 : /*in*/ "r" (&_argvec[2]) \
2395 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2396 ); \
2397 lval = (__typeof__(lval)) _res; \
2398 } while (0)
2399
2400#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2401 arg7) \
2402 do { \
2403 volatile OrigFn _orig = (orig); \
2404 volatile unsigned long _argvec[3+7]; \
2405 volatile unsigned long _res; \
2406 /* _argvec[0] holds current r2 across the call */ \
2407 _argvec[1] = (unsigned long)_orig.r2; \
2408 _argvec[2] = (unsigned long)_orig.nraddr; \
2409 _argvec[2+1] = (unsigned long)arg1; \
2410 _argvec[2+2] = (unsigned long)arg2; \
2411 _argvec[2+3] = (unsigned long)arg3; \
2412 _argvec[2+4] = (unsigned long)arg4; \
2413 _argvec[2+5] = (unsigned long)arg5; \
2414 _argvec[2+6] = (unsigned long)arg6; \
2415 _argvec[2+7] = (unsigned long)arg7; \
2416 __asm__ volatile( \
2417 "mr 11,%1\n\t" \
2418 "std 2,-16(11)\n\t" /* save tocptr */ \
2419 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2420 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2421 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2422 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2423 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2424 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2425 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2426 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2427 "ld 11, 0(11)\n\t" /* target->r11 */ \
2428 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2429 "mr 11,%1\n\t" \
2430 "mr %0,3\n\t" \
2431 "ld 2,-16(11)" /* restore tocptr */ \
2432 : /*out*/ "=r" (_res) \
2433 : /*in*/ "r" (&_argvec[2]) \
2434 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2435 ); \
2436 lval = (__typeof__(lval)) _res; \
2437 } while (0)
2438
2439#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2440 arg7,arg8) \
2441 do { \
2442 volatile OrigFn _orig = (orig); \
2443 volatile unsigned long _argvec[3+8]; \
2444 volatile unsigned long _res; \
2445 /* _argvec[0] holds current r2 across the call */ \
2446 _argvec[1] = (unsigned long)_orig.r2; \
2447 _argvec[2] = (unsigned long)_orig.nraddr; \
2448 _argvec[2+1] = (unsigned long)arg1; \
2449 _argvec[2+2] = (unsigned long)arg2; \
2450 _argvec[2+3] = (unsigned long)arg3; \
2451 _argvec[2+4] = (unsigned long)arg4; \
2452 _argvec[2+5] = (unsigned long)arg5; \
2453 _argvec[2+6] = (unsigned long)arg6; \
2454 _argvec[2+7] = (unsigned long)arg7; \
2455 _argvec[2+8] = (unsigned long)arg8; \
2456 __asm__ volatile( \
2457 "mr 11,%1\n\t" \
2458 "std 2,-16(11)\n\t" /* save tocptr */ \
2459 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2460 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2461 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2462 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2463 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2464 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2465 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2466 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2467 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2468 "ld 11, 0(11)\n\t" /* target->r11 */ \
2469 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2470 "mr 11,%1\n\t" \
2471 "mr %0,3\n\t" \
2472 "ld 2,-16(11)" /* restore tocptr */ \
2473 : /*out*/ "=r" (_res) \
2474 : /*in*/ "r" (&_argvec[2]) \
2475 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2476 ); \
2477 lval = (__typeof__(lval)) _res; \
2478 } while (0)
2479
2480#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2481 arg7,arg8,arg9) \
2482 do { \
2483 volatile OrigFn _orig = (orig); \
2484 volatile unsigned long _argvec[3+9]; \
2485 volatile unsigned long _res; \
2486 /* _argvec[0] holds current r2 across the call */ \
2487 _argvec[1] = (unsigned long)_orig.r2; \
2488 _argvec[2] = (unsigned long)_orig.nraddr; \
2489 _argvec[2+1] = (unsigned long)arg1; \
2490 _argvec[2+2] = (unsigned long)arg2; \
2491 _argvec[2+3] = (unsigned long)arg3; \
2492 _argvec[2+4] = (unsigned long)arg4; \
2493 _argvec[2+5] = (unsigned long)arg5; \
2494 _argvec[2+6] = (unsigned long)arg6; \
2495 _argvec[2+7] = (unsigned long)arg7; \
2496 _argvec[2+8] = (unsigned long)arg8; \
2497 _argvec[2+9] = (unsigned long)arg9; \
2498 __asm__ volatile( \
2499 "mr 11,%1\n\t" \
2500 "std 2,-16(11)\n\t" /* save tocptr */ \
2501 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2502 "addi 1,1,-128\n\t" /* expand stack frame */ \
2503 /* arg9 */ \
2504 "ld 3,72(11)\n\t" \
2505 "std 3,112(1)\n\t" \
2506 /* args1-8 */ \
2507 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2508 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2509 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2510 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2511 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2512 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2513 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2514 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2515 "ld 11, 0(11)\n\t" /* target->r11 */ \
2516 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2517 "mr 11,%1\n\t" \
2518 "mr %0,3\n\t" \
2519 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2520 "addi 1,1,128" /* restore frame */ \
2521 : /*out*/ "=r" (_res) \
2522 : /*in*/ "r" (&_argvec[2]) \
2523 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2524 ); \
2525 lval = (__typeof__(lval)) _res; \
2526 } while (0)
2527
2528#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2529 arg7,arg8,arg9,arg10) \
2530 do { \
2531 volatile OrigFn _orig = (orig); \
2532 volatile unsigned long _argvec[3+10]; \
2533 volatile unsigned long _res; \
2534 /* _argvec[0] holds current r2 across the call */ \
2535 _argvec[1] = (unsigned long)_orig.r2; \
2536 _argvec[2] = (unsigned long)_orig.nraddr; \
2537 _argvec[2+1] = (unsigned long)arg1; \
2538 _argvec[2+2] = (unsigned long)arg2; \
2539 _argvec[2+3] = (unsigned long)arg3; \
2540 _argvec[2+4] = (unsigned long)arg4; \
2541 _argvec[2+5] = (unsigned long)arg5; \
2542 _argvec[2+6] = (unsigned long)arg6; \
2543 _argvec[2+7] = (unsigned long)arg7; \
2544 _argvec[2+8] = (unsigned long)arg8; \
2545 _argvec[2+9] = (unsigned long)arg9; \
2546 _argvec[2+10] = (unsigned long)arg10; \
2547 __asm__ volatile( \
2548 "mr 11,%1\n\t" \
2549 "std 2,-16(11)\n\t" /* save tocptr */ \
2550 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2551 "addi 1,1,-128\n\t" /* expand stack frame */ \
2552 /* arg10 */ \
2553 "ld 3,80(11)\n\t" \
2554 "std 3,120(1)\n\t" \
2555 /* arg9 */ \
2556 "ld 3,72(11)\n\t" \
2557 "std 3,112(1)\n\t" \
2558 /* args1-8 */ \
2559 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2560 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2561 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2562 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2563 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2564 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2565 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2566 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2567 "ld 11, 0(11)\n\t" /* target->r11 */ \
2568 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2569 "mr 11,%1\n\t" \
2570 "mr %0,3\n\t" \
2571 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2572 "addi 1,1,128" /* restore frame */ \
2573 : /*out*/ "=r" (_res) \
2574 : /*in*/ "r" (&_argvec[2]) \
2575 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2576 ); \
2577 lval = (__typeof__(lval)) _res; \
2578 } while (0)
2579
2580#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2581 arg7,arg8,arg9,arg10,arg11) \
2582 do { \
2583 volatile OrigFn _orig = (orig); \
2584 volatile unsigned long _argvec[3+11]; \
2585 volatile unsigned long _res; \
2586 /* _argvec[0] holds current r2 across the call */ \
2587 _argvec[1] = (unsigned long)_orig.r2; \
2588 _argvec[2] = (unsigned long)_orig.nraddr; \
2589 _argvec[2+1] = (unsigned long)arg1; \
2590 _argvec[2+2] = (unsigned long)arg2; \
2591 _argvec[2+3] = (unsigned long)arg3; \
2592 _argvec[2+4] = (unsigned long)arg4; \
2593 _argvec[2+5] = (unsigned long)arg5; \
2594 _argvec[2+6] = (unsigned long)arg6; \
2595 _argvec[2+7] = (unsigned long)arg7; \
2596 _argvec[2+8] = (unsigned long)arg8; \
2597 _argvec[2+9] = (unsigned long)arg9; \
2598 _argvec[2+10] = (unsigned long)arg10; \
2599 _argvec[2+11] = (unsigned long)arg11; \
2600 __asm__ volatile( \
2601 "mr 11,%1\n\t" \
2602 "std 2,-16(11)\n\t" /* save tocptr */ \
2603 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2604 "addi 1,1,-144\n\t" /* expand stack frame */ \
2605 /* arg11 */ \
2606 "ld 3,88(11)\n\t" \
2607 "std 3,128(1)\n\t" \
2608 /* arg10 */ \
2609 "ld 3,80(11)\n\t" \
2610 "std 3,120(1)\n\t" \
2611 /* arg9 */ \
2612 "ld 3,72(11)\n\t" \
2613 "std 3,112(1)\n\t" \
2614 /* args1-8 */ \
2615 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2616 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2617 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2618 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2619 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2620 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2621 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2622 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2623 "ld 11, 0(11)\n\t" /* target->r11 */ \
2624 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2625 "mr 11,%1\n\t" \
2626 "mr %0,3\n\t" \
2627 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2628 "addi 1,1,144" /* restore frame */ \
2629 : /*out*/ "=r" (_res) \
2630 : /*in*/ "r" (&_argvec[2]) \
2631 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2632 ); \
2633 lval = (__typeof__(lval)) _res; \
2634 } while (0)
2635
2636#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2637 arg7,arg8,arg9,arg10,arg11,arg12) \
2638 do { \
2639 volatile OrigFn _orig = (orig); \
2640 volatile unsigned long _argvec[3+12]; \
2641 volatile unsigned long _res; \
2642 /* _argvec[0] holds current r2 across the call */ \
2643 _argvec[1] = (unsigned long)_orig.r2; \
2644 _argvec[2] = (unsigned long)_orig.nraddr; \
2645 _argvec[2+1] = (unsigned long)arg1; \
2646 _argvec[2+2] = (unsigned long)arg2; \
2647 _argvec[2+3] = (unsigned long)arg3; \
2648 _argvec[2+4] = (unsigned long)arg4; \
2649 _argvec[2+5] = (unsigned long)arg5; \
2650 _argvec[2+6] = (unsigned long)arg6; \
2651 _argvec[2+7] = (unsigned long)arg7; \
2652 _argvec[2+8] = (unsigned long)arg8; \
2653 _argvec[2+9] = (unsigned long)arg9; \
2654 _argvec[2+10] = (unsigned long)arg10; \
2655 _argvec[2+11] = (unsigned long)arg11; \
2656 _argvec[2+12] = (unsigned long)arg12; \
2657 __asm__ volatile( \
2658 "mr 11,%1\n\t" \
2659 "std 2,-16(11)\n\t" /* save tocptr */ \
2660 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2661 "addi 1,1,-144\n\t" /* expand stack frame */ \
2662 /* arg12 */ \
2663 "ld 3,96(11)\n\t" \
2664 "std 3,136(1)\n\t" \
2665 /* arg11 */ \
2666 "ld 3,88(11)\n\t" \
2667 "std 3,128(1)\n\t" \
2668 /* arg10 */ \
2669 "ld 3,80(11)\n\t" \
2670 "std 3,120(1)\n\t" \
2671 /* arg9 */ \
2672 "ld 3,72(11)\n\t" \
2673 "std 3,112(1)\n\t" \
2674 /* args1-8 */ \
2675 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2676 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2677 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2678 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2679 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2680 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2681 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2682 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2683 "ld 11, 0(11)\n\t" /* target->r11 */ \
2684 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2685 "mr 11,%1\n\t" \
2686 "mr %0,3\n\t" \
2687 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2688 "addi 1,1,144" /* restore frame */ \
2689 : /*out*/ "=r" (_res) \
2690 : /*in*/ "r" (&_argvec[2]) \
2691 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2692 ); \
2693 lval = (__typeof__(lval)) _res; \
2694 } while (0)
2695
sewardjf5c1a7f2006-10-17 01:32:48 +00002696#endif /* PLAT_ppc64_linux */
2697
sewardj59570ff2010-01-01 11:59:33 +00002698/* ------------------------- arm-linux ------------------------- */
2699
2700#if defined(PLAT_arm_linux)
2701
2702/* These regs are trashed by the hidden call. */
2703#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2704
2705/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2706 long) == 4. */
2707
2708#define CALL_FN_W_v(lval, orig) \
2709 do { \
2710 volatile OrigFn _orig = (orig); \
2711 volatile unsigned long _argvec[1]; \
2712 volatile unsigned long _res; \
2713 _argvec[0] = (unsigned long)_orig.nraddr; \
2714 __asm__ volatile( \
2715 "ldr r4, [%1] \n\t" /* target->r4 */ \
2716 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2717 "mov %0, r0\n" \
2718 : /*out*/ "=r" (_res) \
2719 : /*in*/ "0" (&_argvec[0]) \
2720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2721 ); \
2722 lval = (__typeof__(lval)) _res; \
2723 } while (0)
2724
2725#define CALL_FN_W_W(lval, orig, arg1) \
2726 do { \
2727 volatile OrigFn _orig = (orig); \
2728 volatile unsigned long _argvec[2]; \
2729 volatile unsigned long _res; \
2730 _argvec[0] = (unsigned long)_orig.nraddr; \
2731 _argvec[1] = (unsigned long)(arg1); \
2732 __asm__ volatile( \
2733 "ldr r0, [%1, #4] \n\t" \
2734 "ldr r4, [%1] \n\t" /* target->r4 */ \
2735 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2736 "mov %0, r0\n" \
2737 : /*out*/ "=r" (_res) \
2738 : /*in*/ "0" (&_argvec[0]) \
2739 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2740 ); \
2741 lval = (__typeof__(lval)) _res; \
2742 } while (0)
2743
2744#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2745 do { \
2746 volatile OrigFn _orig = (orig); \
2747 volatile unsigned long _argvec[3]; \
2748 volatile unsigned long _res; \
2749 _argvec[0] = (unsigned long)_orig.nraddr; \
2750 _argvec[1] = (unsigned long)(arg1); \
2751 _argvec[2] = (unsigned long)(arg2); \
2752 __asm__ volatile( \
2753 "ldr r0, [%1, #4] \n\t" \
2754 "ldr r1, [%1, #8] \n\t" \
2755 "ldr r4, [%1] \n\t" /* target->r4 */ \
2756 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2757 "mov %0, r0\n" \
2758 : /*out*/ "=r" (_res) \
2759 : /*in*/ "0" (&_argvec[0]) \
2760 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2761 ); \
2762 lval = (__typeof__(lval)) _res; \
2763 } while (0)
2764
2765#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2766 do { \
2767 volatile OrigFn _orig = (orig); \
2768 volatile unsigned long _argvec[4]; \
2769 volatile unsigned long _res; \
2770 _argvec[0] = (unsigned long)_orig.nraddr; \
2771 _argvec[1] = (unsigned long)(arg1); \
2772 _argvec[2] = (unsigned long)(arg2); \
2773 _argvec[3] = (unsigned long)(arg3); \
2774 __asm__ volatile( \
2775 "ldr r0, [%1, #4] \n\t" \
2776 "ldr r1, [%1, #8] \n\t" \
2777 "ldr r2, [%1, #12] \n\t" \
2778 "ldr r4, [%1] \n\t" /* target->r4 */ \
2779 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2780 "mov %0, r0\n" \
2781 : /*out*/ "=r" (_res) \
2782 : /*in*/ "0" (&_argvec[0]) \
2783 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2784 ); \
2785 lval = (__typeof__(lval)) _res; \
2786 } while (0)
2787
2788#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2789 do { \
2790 volatile OrigFn _orig = (orig); \
2791 volatile unsigned long _argvec[5]; \
2792 volatile unsigned long _res; \
2793 _argvec[0] = (unsigned long)_orig.nraddr; \
2794 _argvec[1] = (unsigned long)(arg1); \
2795 _argvec[2] = (unsigned long)(arg2); \
2796 _argvec[3] = (unsigned long)(arg3); \
2797 _argvec[4] = (unsigned long)(arg4); \
2798 __asm__ volatile( \
2799 "ldr r0, [%1, #4] \n\t" \
2800 "ldr r1, [%1, #8] \n\t" \
2801 "ldr r2, [%1, #12] \n\t" \
2802 "ldr r3, [%1, #16] \n\t" \
2803 "ldr r4, [%1] \n\t" /* target->r4 */ \
2804 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2805 "mov %0, r0" \
2806 : /*out*/ "=r" (_res) \
2807 : /*in*/ "0" (&_argvec[0]) \
2808 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2809 ); \
2810 lval = (__typeof__(lval)) _res; \
2811 } while (0)
2812
2813#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2814 do { \
2815 volatile OrigFn _orig = (orig); \
2816 volatile unsigned long _argvec[6]; \
2817 volatile unsigned long _res; \
2818 _argvec[0] = (unsigned long)_orig.nraddr; \
2819 _argvec[1] = (unsigned long)(arg1); \
2820 _argvec[2] = (unsigned long)(arg2); \
2821 _argvec[3] = (unsigned long)(arg3); \
2822 _argvec[4] = (unsigned long)(arg4); \
2823 _argvec[5] = (unsigned long)(arg5); \
2824 __asm__ volatile( \
2825 "ldr r0, [%1, #20] \n\t" \
2826 "push {r0} \n\t" \
2827 "ldr r0, [%1, #4] \n\t" \
2828 "ldr r1, [%1, #8] \n\t" \
2829 "ldr r2, [%1, #12] \n\t" \
2830 "ldr r3, [%1, #16] \n\t" \
2831 "ldr r4, [%1] \n\t" /* target->r4 */ \
2832 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2833 "add sp, sp, #4 \n\t" \
2834 "mov %0, r0" \
2835 : /*out*/ "=r" (_res) \
2836 : /*in*/ "0" (&_argvec[0]) \
2837 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2838 ); \
2839 lval = (__typeof__(lval)) _res; \
2840 } while (0)
2841
2842#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2843 do { \
2844 volatile OrigFn _orig = (orig); \
2845 volatile unsigned long _argvec[7]; \
2846 volatile unsigned long _res; \
2847 _argvec[0] = (unsigned long)_orig.nraddr; \
2848 _argvec[1] = (unsigned long)(arg1); \
2849 _argvec[2] = (unsigned long)(arg2); \
2850 _argvec[3] = (unsigned long)(arg3); \
2851 _argvec[4] = (unsigned long)(arg4); \
2852 _argvec[5] = (unsigned long)(arg5); \
2853 _argvec[6] = (unsigned long)(arg6); \
2854 __asm__ volatile( \
2855 "ldr r0, [%1, #20] \n\t" \
2856 "ldr r1, [%1, #24] \n\t" \
2857 "push {r0, r1} \n\t" \
2858 "ldr r0, [%1, #4] \n\t" \
2859 "ldr r1, [%1, #8] \n\t" \
2860 "ldr r2, [%1, #12] \n\t" \
2861 "ldr r3, [%1, #16] \n\t" \
2862 "ldr r4, [%1] \n\t" /* target->r4 */ \
2863 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2864 "add sp, sp, #8 \n\t" \
2865 "mov %0, r0" \
2866 : /*out*/ "=r" (_res) \
2867 : /*in*/ "0" (&_argvec[0]) \
2868 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2869 ); \
2870 lval = (__typeof__(lval)) _res; \
2871 } while (0)
2872
2873#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2874 arg7) \
2875 do { \
2876 volatile OrigFn _orig = (orig); \
2877 volatile unsigned long _argvec[8]; \
2878 volatile unsigned long _res; \
2879 _argvec[0] = (unsigned long)_orig.nraddr; \
2880 _argvec[1] = (unsigned long)(arg1); \
2881 _argvec[2] = (unsigned long)(arg2); \
2882 _argvec[3] = (unsigned long)(arg3); \
2883 _argvec[4] = (unsigned long)(arg4); \
2884 _argvec[5] = (unsigned long)(arg5); \
2885 _argvec[6] = (unsigned long)(arg6); \
2886 _argvec[7] = (unsigned long)(arg7); \
2887 __asm__ volatile( \
2888 "ldr r0, [%1, #20] \n\t" \
2889 "ldr r1, [%1, #24] \n\t" \
2890 "ldr r2, [%1, #28] \n\t" \
2891 "push {r0, r1, r2} \n\t" \
2892 "ldr r0, [%1, #4] \n\t" \
2893 "ldr r1, [%1, #8] \n\t" \
2894 "ldr r2, [%1, #12] \n\t" \
2895 "ldr r3, [%1, #16] \n\t" \
2896 "ldr r4, [%1] \n\t" /* target->r4 */ \
2897 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2898 "add sp, sp, #12 \n\t" \
2899 "mov %0, r0" \
2900 : /*out*/ "=r" (_res) \
2901 : /*in*/ "0" (&_argvec[0]) \
2902 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2903 ); \
2904 lval = (__typeof__(lval)) _res; \
2905 } while (0)
2906
2907#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2908 arg7,arg8) \
2909 do { \
2910 volatile OrigFn _orig = (orig); \
2911 volatile unsigned long _argvec[9]; \
2912 volatile unsigned long _res; \
2913 _argvec[0] = (unsigned long)_orig.nraddr; \
2914 _argvec[1] = (unsigned long)(arg1); \
2915 _argvec[2] = (unsigned long)(arg2); \
2916 _argvec[3] = (unsigned long)(arg3); \
2917 _argvec[4] = (unsigned long)(arg4); \
2918 _argvec[5] = (unsigned long)(arg5); \
2919 _argvec[6] = (unsigned long)(arg6); \
2920 _argvec[7] = (unsigned long)(arg7); \
2921 _argvec[8] = (unsigned long)(arg8); \
2922 __asm__ volatile( \
2923 "ldr r0, [%1, #20] \n\t" \
2924 "ldr r1, [%1, #24] \n\t" \
2925 "ldr r2, [%1, #28] \n\t" \
2926 "ldr r3, [%1, #32] \n\t" \
2927 "push {r0, r1, r2, r3} \n\t" \
2928 "ldr r0, [%1, #4] \n\t" \
2929 "ldr r1, [%1, #8] \n\t" \
2930 "ldr r2, [%1, #12] \n\t" \
2931 "ldr r3, [%1, #16] \n\t" \
2932 "ldr r4, [%1] \n\t" /* target->r4 */ \
2933 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2934 "add sp, sp, #16 \n\t" \
2935 "mov %0, r0" \
2936 : /*out*/ "=r" (_res) \
2937 : /*in*/ "0" (&_argvec[0]) \
2938 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2939 ); \
2940 lval = (__typeof__(lval)) _res; \
2941 } while (0)
2942
2943#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2944 arg7,arg8,arg9) \
2945 do { \
2946 volatile OrigFn _orig = (orig); \
2947 volatile unsigned long _argvec[10]; \
2948 volatile unsigned long _res; \
2949 _argvec[0] = (unsigned long)_orig.nraddr; \
2950 _argvec[1] = (unsigned long)(arg1); \
2951 _argvec[2] = (unsigned long)(arg2); \
2952 _argvec[3] = (unsigned long)(arg3); \
2953 _argvec[4] = (unsigned long)(arg4); \
2954 _argvec[5] = (unsigned long)(arg5); \
2955 _argvec[6] = (unsigned long)(arg6); \
2956 _argvec[7] = (unsigned long)(arg7); \
2957 _argvec[8] = (unsigned long)(arg8); \
2958 _argvec[9] = (unsigned long)(arg9); \
2959 __asm__ volatile( \
2960 "ldr r0, [%1, #20] \n\t" \
2961 "ldr r1, [%1, #24] \n\t" \
2962 "ldr r2, [%1, #28] \n\t" \
2963 "ldr r3, [%1, #32] \n\t" \
2964 "ldr r4, [%1, #36] \n\t" \
2965 "push {r0, r1, r2, r3, r4} \n\t" \
2966 "ldr r0, [%1, #4] \n\t" \
2967 "ldr r1, [%1, #8] \n\t" \
2968 "ldr r2, [%1, #12] \n\t" \
2969 "ldr r3, [%1, #16] \n\t" \
2970 "ldr r4, [%1] \n\t" /* target->r4 */ \
2971 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2972 "add sp, sp, #20 \n\t" \
2973 "mov %0, r0" \
2974 : /*out*/ "=r" (_res) \
2975 : /*in*/ "0" (&_argvec[0]) \
2976 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2977 ); \
2978 lval = (__typeof__(lval)) _res; \
2979 } while (0)
2980
2981#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2982 arg7,arg8,arg9,arg10) \
2983 do { \
2984 volatile OrigFn _orig = (orig); \
2985 volatile unsigned long _argvec[11]; \
2986 volatile unsigned long _res; \
2987 _argvec[0] = (unsigned long)_orig.nraddr; \
2988 _argvec[1] = (unsigned long)(arg1); \
2989 _argvec[2] = (unsigned long)(arg2); \
2990 _argvec[3] = (unsigned long)(arg3); \
2991 _argvec[4] = (unsigned long)(arg4); \
2992 _argvec[5] = (unsigned long)(arg5); \
2993 _argvec[6] = (unsigned long)(arg6); \
2994 _argvec[7] = (unsigned long)(arg7); \
2995 _argvec[8] = (unsigned long)(arg8); \
2996 _argvec[9] = (unsigned long)(arg9); \
2997 _argvec[10] = (unsigned long)(arg10); \
2998 __asm__ volatile( \
2999 "ldr r0, [%1, #40] \n\t" \
3000 "push {r0} \n\t" \
3001 "ldr r0, [%1, #20] \n\t" \
3002 "ldr r1, [%1, #24] \n\t" \
3003 "ldr r2, [%1, #28] \n\t" \
3004 "ldr r3, [%1, #32] \n\t" \
3005 "ldr r4, [%1, #36] \n\t" \
3006 "push {r0, r1, r2, r3, r4} \n\t" \
3007 "ldr r0, [%1, #4] \n\t" \
3008 "ldr r1, [%1, #8] \n\t" \
3009 "ldr r2, [%1, #12] \n\t" \
3010 "ldr r3, [%1, #16] \n\t" \
3011 "ldr r4, [%1] \n\t" /* target->r4 */ \
3012 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3013 "add sp, sp, #24 \n\t" \
3014 "mov %0, r0" \
3015 : /*out*/ "=r" (_res) \
3016 : /*in*/ "0" (&_argvec[0]) \
3017 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3018 ); \
3019 lval = (__typeof__(lval)) _res; \
3020 } while (0)
3021
3022#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3023 arg6,arg7,arg8,arg9,arg10, \
3024 arg11) \
3025 do { \
3026 volatile OrigFn _orig = (orig); \
3027 volatile unsigned long _argvec[12]; \
3028 volatile unsigned long _res; \
3029 _argvec[0] = (unsigned long)_orig.nraddr; \
3030 _argvec[1] = (unsigned long)(arg1); \
3031 _argvec[2] = (unsigned long)(arg2); \
3032 _argvec[3] = (unsigned long)(arg3); \
3033 _argvec[4] = (unsigned long)(arg4); \
3034 _argvec[5] = (unsigned long)(arg5); \
3035 _argvec[6] = (unsigned long)(arg6); \
3036 _argvec[7] = (unsigned long)(arg7); \
3037 _argvec[8] = (unsigned long)(arg8); \
3038 _argvec[9] = (unsigned long)(arg9); \
3039 _argvec[10] = (unsigned long)(arg10); \
3040 _argvec[11] = (unsigned long)(arg11); \
3041 __asm__ volatile( \
3042 "ldr r0, [%1, #40] \n\t" \
3043 "ldr r1, [%1, #44] \n\t" \
3044 "push {r0, r1} \n\t" \
3045 "ldr r0, [%1, #20] \n\t" \
3046 "ldr r1, [%1, #24] \n\t" \
3047 "ldr r2, [%1, #28] \n\t" \
3048 "ldr r3, [%1, #32] \n\t" \
3049 "ldr r4, [%1, #36] \n\t" \
3050 "push {r0, r1, r2, r3, r4} \n\t" \
3051 "ldr r0, [%1, #4] \n\t" \
3052 "ldr r1, [%1, #8] \n\t" \
3053 "ldr r2, [%1, #12] \n\t" \
3054 "ldr r3, [%1, #16] \n\t" \
3055 "ldr r4, [%1] \n\t" /* target->r4 */ \
3056 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3057 "add sp, sp, #28 \n\t" \
3058 "mov %0, r0" \
3059 : /*out*/ "=r" (_res) \
3060 : /*in*/ "0" (&_argvec[0]) \
3061 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3062 ); \
3063 lval = (__typeof__(lval)) _res; \
3064 } while (0)
3065
3066#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3067 arg6,arg7,arg8,arg9,arg10, \
3068 arg11,arg12) \
3069 do { \
3070 volatile OrigFn _orig = (orig); \
3071 volatile unsigned long _argvec[13]; \
3072 volatile unsigned long _res; \
3073 _argvec[0] = (unsigned long)_orig.nraddr; \
3074 _argvec[1] = (unsigned long)(arg1); \
3075 _argvec[2] = (unsigned long)(arg2); \
3076 _argvec[3] = (unsigned long)(arg3); \
3077 _argvec[4] = (unsigned long)(arg4); \
3078 _argvec[5] = (unsigned long)(arg5); \
3079 _argvec[6] = (unsigned long)(arg6); \
3080 _argvec[7] = (unsigned long)(arg7); \
3081 _argvec[8] = (unsigned long)(arg8); \
3082 _argvec[9] = (unsigned long)(arg9); \
3083 _argvec[10] = (unsigned long)(arg10); \
3084 _argvec[11] = (unsigned long)(arg11); \
3085 _argvec[12] = (unsigned long)(arg12); \
3086 __asm__ volatile( \
3087 "ldr r0, [%1, #40] \n\t" \
3088 "ldr r1, [%1, #44] \n\t" \
3089 "ldr r2, [%1, #48] \n\t" \
3090 "push {r0, r1, r2} \n\t" \
3091 "ldr r0, [%1, #20] \n\t" \
3092 "ldr r1, [%1, #24] \n\t" \
3093 "ldr r2, [%1, #28] \n\t" \
3094 "ldr r3, [%1, #32] \n\t" \
3095 "ldr r4, [%1, #36] \n\t" \
3096 "push {r0, r1, r2, r3, r4} \n\t" \
3097 "ldr r0, [%1, #4] \n\t" \
3098 "ldr r1, [%1, #8] \n\t" \
3099 "ldr r2, [%1, #12] \n\t" \
3100 "ldr r3, [%1, #16] \n\t" \
3101 "ldr r4, [%1] \n\t" /* target->r4 */ \
3102 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3103 "add sp, sp, #32 \n\t" \
3104 "mov %0, r0" \
3105 : /*out*/ "=r" (_res) \
3106 : /*in*/ "0" (&_argvec[0]) \
3107 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3108 ); \
3109 lval = (__typeof__(lval)) _res; \
3110 } while (0)
3111
3112#endif /* PLAT_arm_linux */
3113
sewardjb5b87402011-03-07 16:05:35 +00003114/* ------------------------- s390x-linux ------------------------- */
3115
3116#if defined(PLAT_s390x_linux)
3117
3118/* Similar workaround as amd64 (see above), but we use r11 as frame
3119 pointer and save the old r11 in r7. r11 might be used for
3120 argvec, therefore we copy argvec in r1 since r1 is clobbered
3121 after the call anyway. */
3122#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
3123# define __FRAME_POINTER \
3124 ,"d"(__builtin_dwarf_cfa())
3125# define VALGRIND_CFI_PROLOGUE \
3126 ".cfi_remember_state\n\t" \
3127 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
3128 "lgr 7,11\n\t" \
3129 "lgr 11,%2\n\t" \
3130 ".cfi_def_cfa r11, 0\n\t"
3131# define VALGRIND_CFI_EPILOGUE \
3132 "lgr 11, 7\n\t" \
3133 ".cfi_restore_state\n\t"
3134#else
3135# define __FRAME_POINTER
3136# define VALGRIND_CFI_PROLOGUE \
3137 "lgr 1,%1\n\t"
3138# define VALGRIND_CFI_EPILOGUE
3139#endif
3140
3141
3142
3143
3144/* These regs are trashed by the hidden call. Note that we overwrite
3145 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
3146 function a proper return address. All others are ABI defined call
3147 clobbers. */
3148#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
3149 "f0","f1","f2","f3","f4","f5","f6","f7"
3150
3151
3152#define CALL_FN_W_v(lval, orig) \
3153 do { \
3154 volatile OrigFn _orig = (orig); \
3155 volatile unsigned long _argvec[1]; \
3156 volatile unsigned long _res; \
3157 _argvec[0] = (unsigned long)_orig.nraddr; \
3158 __asm__ volatile( \
3159 VALGRIND_CFI_PROLOGUE \
3160 "aghi 15,-160\n\t" \
3161 "lg 1, 0(1)\n\t" /* target->r1 */ \
3162 VALGRIND_CALL_NOREDIR_R1 \
3163 "lgr %0, 2\n\t" \
3164 "aghi 15,160\n\t" \
3165 VALGRIND_CFI_EPILOGUE \
3166 : /*out*/ "=d" (_res) \
3167 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
3168 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3169 ); \
3170 lval = (__typeof__(lval)) _res; \
3171 } while (0)
3172
3173/* The call abi has the arguments in r2-r6 and stack */
3174#define CALL_FN_W_W(lval, orig, arg1) \
3175 do { \
3176 volatile OrigFn _orig = (orig); \
3177 volatile unsigned long _argvec[2]; \
3178 volatile unsigned long _res; \
3179 _argvec[0] = (unsigned long)_orig.nraddr; \
3180 _argvec[1] = (unsigned long)arg1; \
3181 __asm__ volatile( \
3182 VALGRIND_CFI_PROLOGUE \
3183 "aghi 15,-160\n\t" \
3184 "lg 2, 8(1)\n\t" \
3185 "lg 1, 0(1)\n\t" \
3186 VALGRIND_CALL_NOREDIR_R1 \
3187 "lgr %0, 2\n\t" \
3188 "aghi 15,160\n\t" \
3189 VALGRIND_CFI_EPILOGUE \
3190 : /*out*/ "=d" (_res) \
3191 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3192 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3193 ); \
3194 lval = (__typeof__(lval)) _res; \
3195 } while (0)
3196
3197#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
3198 do { \
3199 volatile OrigFn _orig = (orig); \
3200 volatile unsigned long _argvec[3]; \
3201 volatile unsigned long _res; \
3202 _argvec[0] = (unsigned long)_orig.nraddr; \
3203 _argvec[1] = (unsigned long)arg1; \
3204 _argvec[2] = (unsigned long)arg2; \
3205 __asm__ volatile( \
3206 VALGRIND_CFI_PROLOGUE \
3207 "aghi 15,-160\n\t" \
3208 "lg 2, 8(1)\n\t" \
3209 "lg 3,16(1)\n\t" \
3210 "lg 1, 0(1)\n\t" \
3211 VALGRIND_CALL_NOREDIR_R1 \
3212 "lgr %0, 2\n\t" \
3213 "aghi 15,160\n\t" \
3214 VALGRIND_CFI_EPILOGUE \
3215 : /*out*/ "=d" (_res) \
3216 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3217 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3218 ); \
3219 lval = (__typeof__(lval)) _res; \
3220 } while (0)
3221
3222#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
3223 do { \
3224 volatile OrigFn _orig = (orig); \
3225 volatile unsigned long _argvec[4]; \
3226 volatile unsigned long _res; \
3227 _argvec[0] = (unsigned long)_orig.nraddr; \
3228 _argvec[1] = (unsigned long)arg1; \
3229 _argvec[2] = (unsigned long)arg2; \
3230 _argvec[3] = (unsigned long)arg3; \
3231 __asm__ volatile( \
3232 VALGRIND_CFI_PROLOGUE \
3233 "aghi 15,-160\n\t" \
3234 "lg 2, 8(1)\n\t" \
3235 "lg 3,16(1)\n\t" \
3236 "lg 4,24(1)\n\t" \
3237 "lg 1, 0(1)\n\t" \
3238 VALGRIND_CALL_NOREDIR_R1 \
3239 "lgr %0, 2\n\t" \
3240 "aghi 15,160\n\t" \
3241 VALGRIND_CFI_EPILOGUE \
3242 : /*out*/ "=d" (_res) \
3243 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3244 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3245 ); \
3246 lval = (__typeof__(lval)) _res; \
3247 } while (0)
3248
3249#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
3250 do { \
3251 volatile OrigFn _orig = (orig); \
3252 volatile unsigned long _argvec[5]; \
3253 volatile unsigned long _res; \
3254 _argvec[0] = (unsigned long)_orig.nraddr; \
3255 _argvec[1] = (unsigned long)arg1; \
3256 _argvec[2] = (unsigned long)arg2; \
3257 _argvec[3] = (unsigned long)arg3; \
3258 _argvec[4] = (unsigned long)arg4; \
3259 __asm__ volatile( \
3260 VALGRIND_CFI_PROLOGUE \
3261 "aghi 15,-160\n\t" \
3262 "lg 2, 8(1)\n\t" \
3263 "lg 3,16(1)\n\t" \
3264 "lg 4,24(1)\n\t" \
3265 "lg 5,32(1)\n\t" \
3266 "lg 1, 0(1)\n\t" \
3267 VALGRIND_CALL_NOREDIR_R1 \
3268 "lgr %0, 2\n\t" \
3269 "aghi 15,160\n\t" \
3270 VALGRIND_CFI_EPILOGUE \
3271 : /*out*/ "=d" (_res) \
3272 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3273 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3274 ); \
3275 lval = (__typeof__(lval)) _res; \
3276 } while (0)
3277
3278#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
3279 do { \
3280 volatile OrigFn _orig = (orig); \
3281 volatile unsigned long _argvec[6]; \
3282 volatile unsigned long _res; \
3283 _argvec[0] = (unsigned long)_orig.nraddr; \
3284 _argvec[1] = (unsigned long)arg1; \
3285 _argvec[2] = (unsigned long)arg2; \
3286 _argvec[3] = (unsigned long)arg3; \
3287 _argvec[4] = (unsigned long)arg4; \
3288 _argvec[5] = (unsigned long)arg5; \
3289 __asm__ volatile( \
3290 VALGRIND_CFI_PROLOGUE \
3291 "aghi 15,-160\n\t" \
3292 "lg 2, 8(1)\n\t" \
3293 "lg 3,16(1)\n\t" \
3294 "lg 4,24(1)\n\t" \
3295 "lg 5,32(1)\n\t" \
3296 "lg 6,40(1)\n\t" \
3297 "lg 1, 0(1)\n\t" \
3298 VALGRIND_CALL_NOREDIR_R1 \
3299 "lgr %0, 2\n\t" \
3300 "aghi 15,160\n\t" \
3301 VALGRIND_CFI_EPILOGUE \
3302 : /*out*/ "=d" (_res) \
3303 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3304 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3305 ); \
3306 lval = (__typeof__(lval)) _res; \
3307 } while (0)
3308
3309#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3310 arg6) \
3311 do { \
3312 volatile OrigFn _orig = (orig); \
3313 volatile unsigned long _argvec[7]; \
3314 volatile unsigned long _res; \
3315 _argvec[0] = (unsigned long)_orig.nraddr; \
3316 _argvec[1] = (unsigned long)arg1; \
3317 _argvec[2] = (unsigned long)arg2; \
3318 _argvec[3] = (unsigned long)arg3; \
3319 _argvec[4] = (unsigned long)arg4; \
3320 _argvec[5] = (unsigned long)arg5; \
3321 _argvec[6] = (unsigned long)arg6; \
3322 __asm__ volatile( \
3323 VALGRIND_CFI_PROLOGUE \
3324 "aghi 15,-168\n\t" \
3325 "lg 2, 8(1)\n\t" \
3326 "lg 3,16(1)\n\t" \
3327 "lg 4,24(1)\n\t" \
3328 "lg 5,32(1)\n\t" \
3329 "lg 6,40(1)\n\t" \
3330 "mvc 160(8,15), 48(1)\n\t" \
3331 "lg 1, 0(1)\n\t" \
3332 VALGRIND_CALL_NOREDIR_R1 \
3333 "lgr %0, 2\n\t" \
3334 "aghi 15,168\n\t" \
3335 VALGRIND_CFI_EPILOGUE \
3336 : /*out*/ "=d" (_res) \
3337 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3338 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3339 ); \
3340 lval = (__typeof__(lval)) _res; \
3341 } while (0)
3342
3343#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3344 arg6, arg7) \
3345 do { \
3346 volatile OrigFn _orig = (orig); \
3347 volatile unsigned long _argvec[8]; \
3348 volatile unsigned long _res; \
3349 _argvec[0] = (unsigned long)_orig.nraddr; \
3350 _argvec[1] = (unsigned long)arg1; \
3351 _argvec[2] = (unsigned long)arg2; \
3352 _argvec[3] = (unsigned long)arg3; \
3353 _argvec[4] = (unsigned long)arg4; \
3354 _argvec[5] = (unsigned long)arg5; \
3355 _argvec[6] = (unsigned long)arg6; \
3356 _argvec[7] = (unsigned long)arg7; \
3357 __asm__ volatile( \
3358 VALGRIND_CFI_PROLOGUE \
3359 "aghi 15,-176\n\t" \
3360 "lg 2, 8(1)\n\t" \
3361 "lg 3,16(1)\n\t" \
3362 "lg 4,24(1)\n\t" \
3363 "lg 5,32(1)\n\t" \
3364 "lg 6,40(1)\n\t" \
3365 "mvc 160(8,15), 48(1)\n\t" \
3366 "mvc 168(8,15), 56(1)\n\t" \
3367 "lg 1, 0(1)\n\t" \
3368 VALGRIND_CALL_NOREDIR_R1 \
3369 "lgr %0, 2\n\t" \
3370 "aghi 15,176\n\t" \
3371 VALGRIND_CFI_EPILOGUE \
3372 : /*out*/ "=d" (_res) \
3373 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3374 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3375 ); \
3376 lval = (__typeof__(lval)) _res; \
3377 } while (0)
3378
3379#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3380 arg6, arg7 ,arg8) \
3381 do { \
3382 volatile OrigFn _orig = (orig); \
3383 volatile unsigned long _argvec[9]; \
3384 volatile unsigned long _res; \
3385 _argvec[0] = (unsigned long)_orig.nraddr; \
3386 _argvec[1] = (unsigned long)arg1; \
3387 _argvec[2] = (unsigned long)arg2; \
3388 _argvec[3] = (unsigned long)arg3; \
3389 _argvec[4] = (unsigned long)arg4; \
3390 _argvec[5] = (unsigned long)arg5; \
3391 _argvec[6] = (unsigned long)arg6; \
3392 _argvec[7] = (unsigned long)arg7; \
3393 _argvec[8] = (unsigned long)arg8; \
3394 __asm__ volatile( \
3395 VALGRIND_CFI_PROLOGUE \
3396 "aghi 15,-184\n\t" \
3397 "lg 2, 8(1)\n\t" \
3398 "lg 3,16(1)\n\t" \
3399 "lg 4,24(1)\n\t" \
3400 "lg 5,32(1)\n\t" \
3401 "lg 6,40(1)\n\t" \
3402 "mvc 160(8,15), 48(1)\n\t" \
3403 "mvc 168(8,15), 56(1)\n\t" \
3404 "mvc 176(8,15), 64(1)\n\t" \
3405 "lg 1, 0(1)\n\t" \
3406 VALGRIND_CALL_NOREDIR_R1 \
3407 "lgr %0, 2\n\t" \
3408 "aghi 15,184\n\t" \
3409 VALGRIND_CFI_EPILOGUE \
3410 : /*out*/ "=d" (_res) \
3411 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3412 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3413 ); \
3414 lval = (__typeof__(lval)) _res; \
3415 } while (0)
3416
3417#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3418 arg6, arg7 ,arg8, arg9) \
3419 do { \
3420 volatile OrigFn _orig = (orig); \
3421 volatile unsigned long _argvec[10]; \
3422 volatile unsigned long _res; \
3423 _argvec[0] = (unsigned long)_orig.nraddr; \
3424 _argvec[1] = (unsigned long)arg1; \
3425 _argvec[2] = (unsigned long)arg2; \
3426 _argvec[3] = (unsigned long)arg3; \
3427 _argvec[4] = (unsigned long)arg4; \
3428 _argvec[5] = (unsigned long)arg5; \
3429 _argvec[6] = (unsigned long)arg6; \
3430 _argvec[7] = (unsigned long)arg7; \
3431 _argvec[8] = (unsigned long)arg8; \
3432 _argvec[9] = (unsigned long)arg9; \
3433 __asm__ volatile( \
3434 VALGRIND_CFI_PROLOGUE \
3435 "aghi 15,-192\n\t" \
3436 "lg 2, 8(1)\n\t" \
3437 "lg 3,16(1)\n\t" \
3438 "lg 4,24(1)\n\t" \
3439 "lg 5,32(1)\n\t" \
3440 "lg 6,40(1)\n\t" \
3441 "mvc 160(8,15), 48(1)\n\t" \
3442 "mvc 168(8,15), 56(1)\n\t" \
3443 "mvc 176(8,15), 64(1)\n\t" \
3444 "mvc 184(8,15), 72(1)\n\t" \
3445 "lg 1, 0(1)\n\t" \
3446 VALGRIND_CALL_NOREDIR_R1 \
3447 "lgr %0, 2\n\t" \
3448 "aghi 15,192\n\t" \
3449 VALGRIND_CFI_EPILOGUE \
3450 : /*out*/ "=d" (_res) \
3451 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3452 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3453 ); \
3454 lval = (__typeof__(lval)) _res; \
3455 } while (0)
3456
3457#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3458 arg6, arg7 ,arg8, arg9, arg10) \
3459 do { \
3460 volatile OrigFn _orig = (orig); \
3461 volatile unsigned long _argvec[11]; \
3462 volatile unsigned long _res; \
3463 _argvec[0] = (unsigned long)_orig.nraddr; \
3464 _argvec[1] = (unsigned long)arg1; \
3465 _argvec[2] = (unsigned long)arg2; \
3466 _argvec[3] = (unsigned long)arg3; \
3467 _argvec[4] = (unsigned long)arg4; \
3468 _argvec[5] = (unsigned long)arg5; \
3469 _argvec[6] = (unsigned long)arg6; \
3470 _argvec[7] = (unsigned long)arg7; \
3471 _argvec[8] = (unsigned long)arg8; \
3472 _argvec[9] = (unsigned long)arg9; \
3473 _argvec[10] = (unsigned long)arg10; \
3474 __asm__ volatile( \
3475 VALGRIND_CFI_PROLOGUE \
3476 "aghi 15,-200\n\t" \
3477 "lg 2, 8(1)\n\t" \
3478 "lg 3,16(1)\n\t" \
3479 "lg 4,24(1)\n\t" \
3480 "lg 5,32(1)\n\t" \
3481 "lg 6,40(1)\n\t" \
3482 "mvc 160(8,15), 48(1)\n\t" \
3483 "mvc 168(8,15), 56(1)\n\t" \
3484 "mvc 176(8,15), 64(1)\n\t" \
3485 "mvc 184(8,15), 72(1)\n\t" \
3486 "mvc 192(8,15), 80(1)\n\t" \
3487 "lg 1, 0(1)\n\t" \
3488 VALGRIND_CALL_NOREDIR_R1 \
3489 "lgr %0, 2\n\t" \
3490 "aghi 15,200\n\t" \
3491 VALGRIND_CFI_EPILOGUE \
3492 : /*out*/ "=d" (_res) \
3493 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3494 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3495 ); \
3496 lval = (__typeof__(lval)) _res; \
3497 } while (0)
3498
3499#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3500 arg6, arg7 ,arg8, arg9, arg10, arg11) \
3501 do { \
3502 volatile OrigFn _orig = (orig); \
3503 volatile unsigned long _argvec[12]; \
3504 volatile unsigned long _res; \
3505 _argvec[0] = (unsigned long)_orig.nraddr; \
3506 _argvec[1] = (unsigned long)arg1; \
3507 _argvec[2] = (unsigned long)arg2; \
3508 _argvec[3] = (unsigned long)arg3; \
3509 _argvec[4] = (unsigned long)arg4; \
3510 _argvec[5] = (unsigned long)arg5; \
3511 _argvec[6] = (unsigned long)arg6; \
3512 _argvec[7] = (unsigned long)arg7; \
3513 _argvec[8] = (unsigned long)arg8; \
3514 _argvec[9] = (unsigned long)arg9; \
3515 _argvec[10] = (unsigned long)arg10; \
3516 _argvec[11] = (unsigned long)arg11; \
3517 __asm__ volatile( \
3518 VALGRIND_CFI_PROLOGUE \
3519 "aghi 15,-208\n\t" \
3520 "lg 2, 8(1)\n\t" \
3521 "lg 3,16(1)\n\t" \
3522 "lg 4,24(1)\n\t" \
3523 "lg 5,32(1)\n\t" \
3524 "lg 6,40(1)\n\t" \
3525 "mvc 160(8,15), 48(1)\n\t" \
3526 "mvc 168(8,15), 56(1)\n\t" \
3527 "mvc 176(8,15), 64(1)\n\t" \
3528 "mvc 184(8,15), 72(1)\n\t" \
3529 "mvc 192(8,15), 80(1)\n\t" \
3530 "mvc 200(8,15), 88(1)\n\t" \
3531 "lg 1, 0(1)\n\t" \
3532 VALGRIND_CALL_NOREDIR_R1 \
3533 "lgr %0, 2\n\t" \
3534 "aghi 15,208\n\t" \
3535 VALGRIND_CFI_EPILOGUE \
3536 : /*out*/ "=d" (_res) \
3537 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3538 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3539 ); \
3540 lval = (__typeof__(lval)) _res; \
3541 } while (0)
3542
3543#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3544 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
3545 do { \
3546 volatile OrigFn _orig = (orig); \
3547 volatile unsigned long _argvec[13]; \
3548 volatile unsigned long _res; \
3549 _argvec[0] = (unsigned long)_orig.nraddr; \
3550 _argvec[1] = (unsigned long)arg1; \
3551 _argvec[2] = (unsigned long)arg2; \
3552 _argvec[3] = (unsigned long)arg3; \
3553 _argvec[4] = (unsigned long)arg4; \
3554 _argvec[5] = (unsigned long)arg5; \
3555 _argvec[6] = (unsigned long)arg6; \
3556 _argvec[7] = (unsigned long)arg7; \
3557 _argvec[8] = (unsigned long)arg8; \
3558 _argvec[9] = (unsigned long)arg9; \
3559 _argvec[10] = (unsigned long)arg10; \
3560 _argvec[11] = (unsigned long)arg11; \
3561 _argvec[12] = (unsigned long)arg12; \
3562 __asm__ volatile( \
3563 VALGRIND_CFI_PROLOGUE \
3564 "aghi 15,-216\n\t" \
3565 "lg 2, 8(1)\n\t" \
3566 "lg 3,16(1)\n\t" \
3567 "lg 4,24(1)\n\t" \
3568 "lg 5,32(1)\n\t" \
3569 "lg 6,40(1)\n\t" \
3570 "mvc 160(8,15), 48(1)\n\t" \
3571 "mvc 168(8,15), 56(1)\n\t" \
3572 "mvc 176(8,15), 64(1)\n\t" \
3573 "mvc 184(8,15), 72(1)\n\t" \
3574 "mvc 192(8,15), 80(1)\n\t" \
3575 "mvc 200(8,15), 88(1)\n\t" \
3576 "mvc 208(8,15), 96(1)\n\t" \
3577 "lg 1, 0(1)\n\t" \
3578 VALGRIND_CALL_NOREDIR_R1 \
3579 "lgr %0, 2\n\t" \
3580 "aghi 15,216\n\t" \
3581 VALGRIND_CFI_EPILOGUE \
3582 : /*out*/ "=d" (_res) \
3583 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3584 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3585 ); \
3586 lval = (__typeof__(lval)) _res; \
3587 } while (0)
3588
3589
3590#endif /* PLAT_s390x_linux */
3591
sewardj0ec07f32006-01-12 12:32:32 +00003592
3593/* ------------------------------------------------------------------ */
3594/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
3595/* */
njn30d76c62005-06-18 15:07:39 +00003596/* ------------------------------------------------------------------ */
3597
sewardj2e93c502002-04-12 11:12:52 +00003598/* Some request codes. There are many more of these, but most are not
3599 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00003600 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00003601
sewardj0ec07f32006-01-12 12:32:32 +00003602 Core ones are in the range 0x00000000--0x0000ffff. The non-public
3603 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00003604*/
3605
sewardj0ec07f32006-01-12 12:32:32 +00003606/* These macros are used by tools -- they must be public, but don't
3607 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00003608#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00003609 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00003610#define VG_IS_TOOL_USERREQ(a, b, v) \
3611 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00003612
sewardj5ce4b152006-03-11 12:57:41 +00003613/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3614 This enum comprises an ABI exported by Valgrind to programs
3615 which use client requests. DO NOT CHANGE THE ORDER OF THESE
3616 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00003617typedef
njn4c791212003-05-02 17:53:54 +00003618 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
3619 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00003620
sewardj0ec07f32006-01-12 12:32:32 +00003621 /* These allow any function to be called from the simulated
3622 CPU but run on the real CPU. Nb: the first arg passed to
3623 the function is always the ThreadId of the running
3624 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00003625 function, etc. */
njn4c791212003-05-02 17:53:54 +00003626 VG_USERREQ__CLIENT_CALL0 = 0x1101,
3627 VG_USERREQ__CLIENT_CALL1 = 0x1102,
3628 VG_USERREQ__CLIENT_CALL2 = 0x1103,
3629 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00003630
sewardj0ec07f32006-01-12 12:32:32 +00003631 /* Can be useful in regression testing suites -- eg. can
3632 send Valgrind's output to /dev/null and still count
3633 errors. */
njn4c791212003-05-02 17:53:54 +00003634 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00003635
sewardj3b290482011-05-06 21:02:55 +00003636 /* Allows a string (gdb monitor command) to be passed to the tool
3637 Used for interaction with vgdb/gdb */
3638 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
3639
sewardj0ec07f32006-01-12 12:32:32 +00003640 /* These are useful and can be interpreted by any tool that
3641 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00003642 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00003643 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00003644 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00003645 /* Memory pool support. */
3646 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
3647 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
3648 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
3649 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00003650 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00003651 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
3652 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
3653 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00003654
fitzhardinge39de4b42003-10-31 07:12:21 +00003655 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00003656 /* The first two pass the va_list argument by value, which
3657 assumes it is the same size as or smaller than a UWord,
3658 which generally isn't the case. Hence are deprecated.
3659 The second two pass the vargs by reference and so are
3660 immune to this problem. */
3661 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00003662 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00003663 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00003664 /* both :: char* fmt, va_list* vargs */
3665 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
3666 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00003667
3668 /* Stack support. */
3669 VG_USERREQ__STACK_REGISTER = 0x1501,
3670 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00003671 VG_USERREQ__STACK_CHANGE = 0x1503,
3672
3673 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00003674 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
3675
3676 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00003677 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
3678
3679 /* Disable/enable error reporting level. Takes a single
3680 Word arg which is the delta to this thread's error
3681 disablement indicator. Hence 1 disables or further
3682 disables errors, and -1 moves back towards enablement.
3683 Other values are not allowed. */
3684 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801
njn25e49d8e72002-09-23 09:36:25 +00003685 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00003686
sewardj0ec07f32006-01-12 12:32:32 +00003687#if !defined(__GNUC__)
3688# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00003689#endif
sewardj2e93c502002-04-12 11:12:52 +00003690
bartfa5115a2010-09-02 09:33:02 +00003691
sewardj0ec07f32006-01-12 12:32:32 +00003692/* Returns the number of Valgrinds this code is running under. That
3693 is, 0 if running natively, 1 if running under Valgrind, 2 if
3694 running under Valgrind which is running under another Valgrind,
3695 etc. */
bartfa5115a2010-09-02 09:33:02 +00003696#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00003697 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00003698 VG_USERREQ__RUNNING_ON_VALGRIND, \
3699 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00003700
3701
sewardj18d75132002-05-16 11:06:21 +00003702/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3703 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
3704 since it provides a way to make sure valgrind will retranslate the
3705 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00003706#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
3707 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
3708 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00003709
njn26aba4d2005-05-16 13:31:23 +00003710
sewardj0ec07f32006-01-12 12:32:32 +00003711/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00003712 Possibly with a backtrace. This is a really ugly hack. The return value
3713 is the number of characters printed, excluding the "**<pid>** " part at the
3714 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00003715
bart42f83fe2012-01-31 10:13:51 +00003716#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00003717/* Modern GCC will optimize the static routine out if unused,
3718 and unused attribute will shut down warnings about it. */
3719static int VALGRIND_PRINTF(const char *format, ...)
3720 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00003721#endif
sewardj7eca0cc2006-04-12 17:15:35 +00003722static int
bart0da2c772010-09-01 10:18:36 +00003723#if defined(_MSC_VER)
3724__inline
3725#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00003726VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003727{
bart8c7e25f2011-03-04 16:55:56 +00003728#if defined(NVALGRIND)
3729 return 0;
3730#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00003731#if defined(_MSC_VER)
3732 uintptr_t _qzz_res;
3733#else
njnc6168192004-11-29 13:54:10 +00003734 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00003735#endif
sewardjc560fb32010-01-28 15:23:54 +00003736 va_list vargs;
3737 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00003738#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00003739 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00003740 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00003741 (uintptr_t)format,
3742 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00003743 0, 0, 0);
3744#else
bart575ce8e2011-05-15 07:04:03 +00003745 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00003746 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00003747 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00003748 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00003749 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00003750#endif
sewardjc560fb32010-01-28 15:23:54 +00003751 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003752 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00003753#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00003754}
3755
bart42f83fe2012-01-31 10:13:51 +00003756#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00003757static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3758 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00003759#endif
sewardj7eca0cc2006-04-12 17:15:35 +00003760static int
bart0da2c772010-09-01 10:18:36 +00003761#if defined(_MSC_VER)
3762__inline
3763#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00003764VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003765{
bart8c7e25f2011-03-04 16:55:56 +00003766#if defined(NVALGRIND)
3767 return 0;
3768#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00003769#if defined(_MSC_VER)
3770 uintptr_t _qzz_res;
3771#else
njnc6168192004-11-29 13:54:10 +00003772 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00003773#endif
sewardjc560fb32010-01-28 15:23:54 +00003774 va_list vargs;
3775 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00003776#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00003777 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00003778 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00003779 (uintptr_t)format,
3780 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00003781 0, 0, 0);
3782#else
bart575ce8e2011-05-15 07:04:03 +00003783 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00003784 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00003785 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00003786 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00003787 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00003788#endif
sewardjc560fb32010-01-28 15:23:54 +00003789 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003790 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003791#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00003792}
sewardj18d75132002-05-16 11:06:21 +00003793
sewardj0ec07f32006-01-12 12:32:32 +00003794
njn3e884182003-04-15 13:03:23 +00003795/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00003796 real CPU, calling an arbitary function.
3797
3798 Note that the current ThreadId is inserted as the first argument.
3799 So this call:
3800
3801 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3802
3803 requires f to have this signature:
3804
3805 Word f(Word tid, Word arg1, Word arg2)
3806
3807 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00003808
3809 Note that these client requests are not entirely reliable. For example,
3810 if you call a function with them that subsequently calls printf(),
3811 there's a high chance Valgrind will crash. Generally, your prospects of
3812 these working are made higher if the called function does not refer to
3813 any global variables, and does not refer to any libc or other functions
3814 (printf et al). Any kind of entanglement with libc or dynamic linking is
3815 likely to have a bad outcome, for tricky reasons which we've grappled
3816 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00003817*/
sewardj0ec07f32006-01-12 12:32:32 +00003818#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00003819 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3820 VG_USERREQ__CLIENT_CALL0, \
3821 _qyy_fn, \
3822 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00003823
bart575ce8e2011-05-15 07:04:03 +00003824#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
3825 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3826 VG_USERREQ__CLIENT_CALL1, \
3827 _qyy_fn, \
3828 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00003829
bart575ce8e2011-05-15 07:04:03 +00003830#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
3831 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3832 VG_USERREQ__CLIENT_CALL2, \
3833 _qyy_fn, \
3834 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00003835
sewardj0ec07f32006-01-12 12:32:32 +00003836#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00003837 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3838 VG_USERREQ__CLIENT_CALL3, \
3839 _qyy_fn, \
3840 _qyy_arg1, _qyy_arg2, \
3841 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00003842
3843
nethercote7cc9c232004-01-21 15:08:04 +00003844/* Counts the number of errors that have been recorded by a tool. Nb:
3845 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00003846 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00003847#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00003848 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
3849 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00003850 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00003851 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00003852
njn3ac96952009-07-09 23:35:44 +00003853/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
3854 when heap blocks are allocated in order to give accurate results. This
3855 happens automatically for the standard allocator functions such as
3856 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
3857 delete[], etc.
njnd7994182003-10-02 13:44:04 +00003858
njn3ac96952009-07-09 23:35:44 +00003859 But if your program uses a custom allocator, this doesn't automatically
3860 happen, and Valgrind will not do as well. For example, if you allocate
3861 superblocks with mmap() and then allocates chunks of the superblocks, all
3862 Valgrind's observations will be at the mmap() level and it won't know that
3863 the chunks should be considered separate entities. In Memcheck's case,
3864 that means you probably won't get heap block overrun detection (because
3865 there won't be redzones marked as unaddressable) and you definitely won't
3866 get any leak detection.
3867
3868 The following client requests allow a custom allocator to be annotated so
3869 that it can be handled accurately by Valgrind.
3870
3871 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
3872 by a malloc()-like function. For Memcheck (an illustrative case), this
3873 does two things:
3874
3875 - It records that the block has been allocated. This means any addresses
3876 within the block mentioned in error messages will be
3877 identified as belonging to the block. It also means that if the block
3878 isn't freed it will be detected by the leak checker.
3879
3880 - It marks the block as being addressable and undefined (if 'is_zeroed' is
3881 not set), or addressable and defined (if 'is_zeroed' is set). This
3882 controls how accesses to the block by the program are handled.
3883
3884 'addr' is the start of the usable block (ie. after any
3885 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
3886 can apply redzones -- these are blocks of padding at the start and end of
3887 each block. Adding redzones is recommended as it makes it much more likely
3888 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
3889 zeroed (or filled with another predictable value), as is the case for
3890 calloc().
3891
3892 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
3893 heap block -- that will be used by the client program -- is allocated.
3894 It's best to put it at the outermost level of the allocator if possible;
3895 for example, if you have a function my_alloc() which calls
3896 internal_alloc(), and the client request is put inside internal_alloc(),
3897 stack traces relating to the heap block will contain entries for both
3898 my_alloc() and internal_alloc(), which is probably not what you want.
3899
njnb965efb2009-08-10 07:36:54 +00003900 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
3901 custom blocks from within a heap block, B, that has been allocated with
3902 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
3903 -- the custom blocks will take precedence.
3904
njn3ac96952009-07-09 23:35:44 +00003905 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
3906 Memcheck, it does two things:
3907
3908 - It records that the block has been deallocated. This assumes that the
3909 block was annotated as having been allocated via
3910 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3911
3912 - It marks the block as being unaddressable.
3913
3914 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
3915 heap block is deallocated.
3916
bart91347382011-03-25 20:07:25 +00003917 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
3918 Memcheck, it does four things:
3919
3920 - It records that the size of a block has been changed. This assumes that
3921 the block was annotated as having been allocated via
3922 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3923
3924 - If the block shrunk, it marks the freed memory as being unaddressable.
3925
3926 - If the block grew, it marks the new area as undefined and defines a red
3927 zone past the end of the new block.
3928
3929 - The V-bits of the overlap between the old and the new block are preserved.
3930
3931 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
3932 and before deallocation of the old block.
3933
3934 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00003935 allocator working well with Memcheck. More specifically, if your allocator
3936 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
3937 will be necessary to mark the memory as addressable just before the zeroing
3938 occurs, otherwise you'll get a lot of invalid write errors. For example,
3939 you'll need to do this if your allocator recycles freed blocks, but it
3940 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
3941 Alternatively, if your allocator reuses freed blocks for allocator-internal
3942 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
3943
3944 Really, what's happening is a blurring of the lines between the client
3945 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
3946 memory should be considered unaddressable to the client program, but the
3947 allocator knows more than the rest of the client program and so may be able
3948 to safely access it. Extra client requests are necessary for Valgrind to
3949 understand the distinction between the allocator and the rest of the
3950 program.
3951
njn32f8d8c2009-07-15 02:31:45 +00003952 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00003953*/
sewardj4b3a7422011-10-24 13:21:57 +00003954#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
3955 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
3956 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00003957
njn32f8d8c2009-07-15 02:31:45 +00003958/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3959 Ignored if addr == 0.
3960*/
sewardj4b3a7422011-10-24 13:21:57 +00003961#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
3962 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
3963 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00003964
3965/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3966 Ignored if addr == 0.
3967*/
sewardj4b3a7422011-10-24 13:21:57 +00003968#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
3969 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
3970 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00003971
rjwalshbc0bb832004-06-19 18:12:36 +00003972/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003973#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00003974 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
3975 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003976
3977/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003978#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00003979 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
3980 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003981
3982/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003983#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00003984 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
3985 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003986
3987/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003988#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00003989 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
3990 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003991
sewardj2c1c9df2006-07-28 00:06:37 +00003992/* Disassociate any pieces outside a particular range. */
3993#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00003994 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
3995 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00003996
sewardjc740d762006-10-05 17:59:23 +00003997/* Resize and/or move a piece associated with a memory pool. */
3998#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00003999 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
4000 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00004001
4002/* Resize and/or move a piece associated with a memory pool. */
4003#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00004004 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
4005 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00004006
4007/* Return 1 if a mempool exists, else 0. */
4008#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00004009 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00004010 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00004011 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00004012
rjwalsh0140af52005-06-04 20:42:33 +00004013/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004014#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00004015 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004016 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00004017 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004018
4019/* Unmark the piece of memory associated with a stack id as being a
4020 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004021#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00004022 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
4023 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004024
4025/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004026#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00004027 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
4028 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004029
sewardjc8259b82009-04-22 22:42:10 +00004030/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00004031#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4032 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4033 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00004034
sewardj5c659622010-08-20 18:22:07 +00004035/* Map a code address to a source file name and line number. buf64
4036 must point to a 64-byte buffer in the caller's address space. The
4037 result will be dumped in there and is guaranteed to be zero
4038 terminated. If no info is found, the first byte is set to zero. */
4039#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00004040 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00004041 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00004042 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00004043
sewardjdc873c02011-07-24 16:02:33 +00004044/* Disable error reporting for this thread. Behaves in a stack like
4045 way, so you can safely call this multiple times provided that
4046 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
4047 to re-enable reporting. The first call of this macro disables
4048 reporting. Subsequent calls have no effect except to increase the
4049 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
4050 reporting. Child threads do not inherit this setting from their
4051 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00004052#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00004053 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4054 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00004055
4056/* Re-enable error reporting, as per comments on
4057 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00004058#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00004059 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4060 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00004061
sewardjc112c8e2011-06-24 18:26:11 +00004062#undef PLAT_x86_darwin
4063#undef PLAT_amd64_darwin
4064#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +00004065#undef PLAT_x86_linux
4066#undef PLAT_amd64_linux
4067#undef PLAT_ppc32_linux
4068#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004069#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00004070#undef PLAT_s390x_linux
sewardj0ec07f32006-01-12 12:32:32 +00004071
njn3e884182003-04-15 13:03:23 +00004072#endif /* __VALGRIND_H */