blob: 22b8a617b3a19cfbad7431565ce779329c447394 [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001/* -*- c -*-
njn25e49d8e72002-09-23 09:36:25 +00002 ----------------------------------------------------------------
3
4 Notice that the following BSD-style license applies to this one
njn7fd15d62006-03-31 12:05:04 +00005 file (valgrind.h) only. The rest of Valgrind is licensed under the
6 terms of the GNU General Public License, version 2, unless
7 otherwise indicated. See the COPYING file in the source
8 distribution for details.
njn25e49d8e72002-09-23 09:36:25 +00009
10 ----------------------------------------------------------------
11
njnb9c427c2004-12-01 14:14:42 +000012 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
sewardjde4a1d02002-03-22 01:27:54 +000014
sewardj9eecbbb2010-05-03 21:37:12 +000015 Copyright (C) 2000-2010 Julian Seward. All rights reserved.
sewardjde4a1d02002-03-22 01:27:54 +000016
njn25e49d8e72002-09-23 09:36:25 +000017 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
sewardjde4a1d02002-03-22 01:27:54 +000020
njn25e49d8e72002-09-23 09:36:25 +000021 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
sewardjde4a1d02002-03-22 01:27:54 +000023
njn25e49d8e72002-09-23 09:36:25 +000024 2. The origin of this software must not be misrepresented; you must
25 not claim that you wrote the original software. If you use this
26 software in a product, an acknowledgment in the product
27 documentation would be appreciated but is not required.
sewardjde4a1d02002-03-22 01:27:54 +000028
njn25e49d8e72002-09-23 09:36:25 +000029 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
31
32 4. The name of the author may not be used to endorse or promote
33 products derived from this software without specific prior written
34 permission.
35
36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48 ----------------------------------------------------------------
49
50 Notice that the above BSD-style license applies to this one file
51 (valgrind.h) only. The entire rest of Valgrind is licensed under
52 the terms of the GNU General Public License, version 2. See the
53 COPYING file in the source distribution for details.
54
55 ----------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000056*/
57
58
njn30d76c62005-06-18 15:07:39 +000059/* This file is for inclusion into client (your!) code.
60
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
63
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
sewardj0ec07f32006-01-12 12:32:32 +000067 consumes very few (eg. 7) instructions, so the resulting performance
njn30d76c62005-06-18 15:07:39 +000068 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
72
sewardjde4a1d02002-03-22 01:27:54 +000073#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
sewardj71044162010-03-03 22:57:47 +000076
77/* ------------------------------------------------------------------ */
78/* VERSION NUMBER OF VALGRIND */
79/* ------------------------------------------------------------------ */
80
81/* Specify Valgrind's version number, so that user code can
sewardj0fe1d4c2010-04-19 08:43:26 +000082 conditionally compile based on our version number. Note that these
83 were introduced at version 3.6 and so do not exist in version 3.5
84 or earlier. The recommended way to use them to check for "version
85 X.Y or later" is (eg)
86
87#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
88 && (__VALGRIND_MAJOR__ > 3 \
89 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
90*/
91#define __VALGRIND_MAJOR__ 3
sewardj71044162010-03-03 22:57:47 +000092#define __VALGRIND_MINOR__ 6
93
94
fitzhardinge39de4b42003-10-31 07:12:21 +000095#include <stdarg.h>
96
njn3dd0a912005-06-28 19:44:10 +000097/* Nb: this file might be included in a file compiled with -ansi. So
98 we can't use C++ style "//" comments nor the "asm" keyword (instead
99 use "__asm__"). */
100
sewardjf5c1a7f2006-10-17 01:32:48 +0000101/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +0000102 that in this file we're using the compiler's CPP symbols for
103 identifying architectures, which are different to the ones we use
104 within the rest of Valgrind. Note, __powerpc__ is active for both
105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardj59570ff2010-01-01 11:59:33 +0000106 latter (on Linux, that is).
107
108 Misc note: how to find out what's predefined in gcc by default:
109 gcc -Wp,-dM somefile.c
110*/
sewardj7af32302010-01-02 10:37:58 +0000111#undef PLAT_x86_darwin
112#undef PLAT_amd64_darwin
bart7f489812010-08-27 10:05:27 +0000113#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +0000114#undef PLAT_x86_linux
115#undef PLAT_amd64_linux
116#undef PLAT_ppc32_linux
117#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000118#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +0000119#undef PLAT_s390x_linux
120
sewardj0ec07f32006-01-12 12:32:32 +0000121
sewardj6e9de462011-06-28 07:25:29 +0000122#if defined(__APPLE__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000123# define PLAT_x86_darwin 1
124#elif defined(__APPLE__) && defined(__x86_64__)
125# define PLAT_amd64_darwin 1
sewardj6e9de462011-06-28 07:25:29 +0000126#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
127 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000128# define PLAT_x86_win32 1
sewardj59570ff2010-01-01 11:59:33 +0000129#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000130# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000131#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000132# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000133#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000134# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000135#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000136# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000137#elif defined(__linux__) && defined(__arm__)
138# define PLAT_arm_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000139#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
140# define PLAT_s390x_linux 1
njnf76d27a2009-05-28 01:53:07 +0000141#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000142/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000143 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000144# if !defined(NVALGRIND)
145# define NVALGRIND 1
146# endif
147#endif
148
149
njn30d76c62005-06-18 15:07:39 +0000150/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000151/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
152/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000153/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000154
bart575ce8e2011-05-15 07:04:03 +0000155/*
156 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
157 * request. Accepts both pointers and integers as arguments.
158 *
159 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
160 * client request and whose value equals the client request result. Accepts
161 * both pointers and integers as arguments.
162 */
163
164#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
165 _zzq_request, _zzq_arg1, _zzq_arg2, \
166 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
167 { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
168 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
169 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); }
170
sewardj0ec07f32006-01-12 12:32:32 +0000171#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000172
173/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000174 from the compiled code (analogous to NDEBUG's effects on
175 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000176#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
177 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000178 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000179 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000180
sewardj0ec07f32006-01-12 12:32:32 +0000181#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000182
sewardj0ec07f32006-01-12 12:32:32 +0000183/* The following defines the magic code sequences which the JITter
184 spots and handles magically. Don't look too closely at them as
185 they will rot your brain.
186
187 The assembly code sequences for all architectures is in this one
188 file. This is because this file must be stand-alone, and we don't
189 want to have multiple files.
190
191 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
192 value gets put in the return slot, so that everything works when
193 this is executed not under Valgrind. Args are passed in a memory
194 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000195 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000196
nethercote54265442004-10-26 12:56:58 +0000197 The macro args are:
198 _zzq_rlval result lvalue
199 _zzq_default default value (result returned when running on real CPU)
200 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000201 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000202
sewardj0ec07f32006-01-12 12:32:32 +0000203 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000204 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
205 guest's NRADDR pseudo-register and whatever other information is
206 needed to safely run the call original from the wrapper: on
207 ppc64-linux, the R2 value at the divert point is also needed. This
208 information is abstracted into a user-visible type, OrigFn.
209
210 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
211 guest, but guarantees that the branch instruction will not be
212 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
213 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
214 complete inline asm, since it needs to be combined with more magic
215 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000216*/
217
njnf76d27a2009-05-28 01:53:07 +0000218/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000219
sewardj520a03a2010-10-07 10:46:15 +0000220#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000221 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000222
223typedef
224 struct {
225 unsigned int nraddr; /* where's the code? */
226 }
227 OrigFn;
228
sewardj0ec07f32006-01-12 12:32:32 +0000229#define __SPECIAL_INSTRUCTION_PREAMBLE \
230 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000231 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000232
bart575ce8e2011-05-15 07:04:03 +0000233#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
234 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000235 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000236 __extension__ \
237 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000238 volatile unsigned int _zzq_result; \
239 _zzq_args[0] = (unsigned int)(_zzq_request); \
240 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
241 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
242 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
243 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000244 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000245 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
246 /* %EDX = client_request ( %EAX ) */ \
247 "xchgl %%ebx,%%ebx" \
248 : "=d" (_zzq_result) \
249 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
250 : "cc", "memory" \
251 ); \
bart575ce8e2011-05-15 07:04:03 +0000252 _zzq_result; \
253 })
sewardj2c48c7b2005-11-29 13:05:56 +0000254
sewardjc8858442006-01-20 15:17:20 +0000255#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
256 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
257 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000258 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
259 /* %EAX = guest_NRADDR */ \
260 "xchgl %%ecx,%%ecx" \
261 : "=a" (__addr) \
262 : \
263 : "cc", "memory" \
264 ); \
sewardjc8858442006-01-20 15:17:20 +0000265 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000266 }
sewardj0ec07f32006-01-12 12:32:32 +0000267
268#define VALGRIND_CALL_NOREDIR_EAX \
269 __SPECIAL_INSTRUCTION_PREAMBLE \
270 /* call-noredir *%EAX */ \
271 "xchgl %%edx,%%edx\n\t"
sewardj60227842010-10-07 10:00:56 +0000272#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000273
274/* ------------------------- x86-Win32 ------------------------- */
275
276#if defined(PLAT_x86_win32) && !defined(__GNUC__)
277
278typedef
279 struct {
280 unsigned int nraddr; /* where's the code? */
281 }
282 OrigFn;
283
284#if defined(_MSC_VER)
285
286#define __SPECIAL_INSTRUCTION_PREAMBLE \
287 __asm rol edi, 3 __asm rol edi, 13 \
288 __asm rol edi, 29 __asm rol edi, 19
289
bart575ce8e2011-05-15 07:04:03 +0000290#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
291 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000292 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000293 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
294 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
295 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
296 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
297
298static __inline uintptr_t
299valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
300 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
301 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
302 uintptr_t _zzq_arg5)
303{
304 volatile uintptr_t _zzq_args[6];
305 volatile unsigned int _zzq_result;
306 _zzq_args[0] = (uintptr_t)(_zzq_request);
307 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
308 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
309 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
310 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
311 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
312 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
313 __SPECIAL_INSTRUCTION_PREAMBLE
314 /* %EDX = client_request ( %EAX ) */
315 __asm xchg ebx,ebx
316 __asm mov _zzq_result, edx
317 }
318 return _zzq_result;
319}
bart7f489812010-08-27 10:05:27 +0000320
321#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
322 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
323 volatile unsigned int __addr; \
324 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
325 /* %EAX = guest_NRADDR */ \
326 __asm xchg ecx,ecx \
327 __asm mov __addr, eax \
328 } \
329 _zzq_orig->nraddr = __addr; \
330 }
331
332#define VALGRIND_CALL_NOREDIR_EAX ERROR
333
334#else
335#error Unsupported compiler.
336#endif
337
338#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000339
njnf76d27a2009-05-28 01:53:07 +0000340/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000341
njnf76d27a2009-05-28 01:53:07 +0000342#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000343
344typedef
345 struct {
346 unsigned long long int nraddr; /* where's the code? */
347 }
348 OrigFn;
349
sewardj0ec07f32006-01-12 12:32:32 +0000350#define __SPECIAL_INSTRUCTION_PREAMBLE \
351 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000352 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000353
bart575ce8e2011-05-15 07:04:03 +0000354#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
355 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000356 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000357 __extension__ \
358 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000359 volatile unsigned long long int _zzq_result; \
360 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
361 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
362 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
363 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
364 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000365 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000366 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
367 /* %RDX = client_request ( %RAX ) */ \
368 "xchgq %%rbx,%%rbx" \
369 : "=d" (_zzq_result) \
370 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
371 : "cc", "memory" \
372 ); \
bart575ce8e2011-05-15 07:04:03 +0000373 _zzq_result; \
374 })
sewardj0ec07f32006-01-12 12:32:32 +0000375
sewardjc8858442006-01-20 15:17:20 +0000376#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
377 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
378 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000379 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
380 /* %RAX = guest_NRADDR */ \
381 "xchgq %%rcx,%%rcx" \
382 : "=a" (__addr) \
383 : \
384 : "cc", "memory" \
385 ); \
sewardjc8858442006-01-20 15:17:20 +0000386 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000387 }
388
389#define VALGRIND_CALL_NOREDIR_RAX \
390 __SPECIAL_INSTRUCTION_PREAMBLE \
391 /* call-noredir *%RAX */ \
392 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000393#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000394
sewardjf5c1a7f2006-10-17 01:32:48 +0000395/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000396
sewardjf5c1a7f2006-10-17 01:32:48 +0000397#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000398
399typedef
400 struct {
sewardjc8858442006-01-20 15:17:20 +0000401 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000402 }
403 OrigFn;
404
sewardj0ec07f32006-01-12 12:32:32 +0000405#define __SPECIAL_INSTRUCTION_PREAMBLE \
406 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000407 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000408
bart575ce8e2011-05-15 07:04:03 +0000409#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
410 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000411 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000412 \
bart575ce8e2011-05-15 07:04:03 +0000413 __extension__ \
414 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000415 unsigned int _zzq_result; \
416 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000417 _zzq_args[0] = (unsigned int)(_zzq_request); \
418 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
419 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
420 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
421 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000422 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000423 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000424 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
425 "mr 4,%2\n\t" /*ptr*/ \
426 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000427 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000428 "or 1,1,1\n\t" \
429 "mr %0,3" /*result*/ \
430 : "=b" (_zzq_result) \
431 : "b" (_zzq_default), "b" (_zzq_ptr) \
432 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000433 _zzq_result; \
434 })
sewardj0ec07f32006-01-12 12:32:32 +0000435
sewardjd68ac3e2006-01-20 14:31:57 +0000436#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
437 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000438 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000439 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
440 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000441 "or 2,2,2\n\t" \
442 "mr %0,3" \
443 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000444 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000445 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000446 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000447 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000448 }
449
450#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
451 __SPECIAL_INSTRUCTION_PREAMBLE \
452 /* branch-and-link-to-noredir *%R11 */ \
453 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000454#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000455
sewardjf5c1a7f2006-10-17 01:32:48 +0000456/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000457
sewardjf5c1a7f2006-10-17 01:32:48 +0000458#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000459
460typedef
461 struct {
462 unsigned long long int nraddr; /* where's the code? */
463 unsigned long long int r2; /* what tocptr do we need? */
464 }
465 OrigFn;
466
sewardj1a85f4f2006-01-12 21:15:35 +0000467#define __SPECIAL_INSTRUCTION_PREAMBLE \
468 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
469 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
470
bart575ce8e2011-05-15 07:04:03 +0000471#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
472 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000473 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000474 \
bart575ce8e2011-05-15 07:04:03 +0000475 __extension__ \
476 ({ unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000477 register unsigned long long int _zzq_result __asm__("r3"); \
478 register unsigned long long int* _zzq_ptr __asm__("r4"); \
479 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
480 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
481 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
482 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
483 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000484 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000485 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000486 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
487 /* %R3 = client_request ( %R4 ) */ \
488 "or 1,1,1" \
489 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000490 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000491 : "cc", "memory"); \
bart575ce8e2011-05-15 07:04:03 +0000492 _zzq_result; \
493 })
sewardj1a85f4f2006-01-12 21:15:35 +0000494
sewardjd68ac3e2006-01-20 14:31:57 +0000495#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
496 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
497 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000498 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
499 /* %R3 = guest_NRADDR */ \
500 "or 2,2,2" \
501 : "=r" (__addr) \
502 : \
503 : "cc", "memory" \
504 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000505 _zzq_orig->nraddr = __addr; \
506 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
507 /* %R3 = guest_NRADDR_GPR2 */ \
508 "or 4,4,4" \
509 : "=r" (__addr) \
510 : \
511 : "cc", "memory" \
512 ); \
513 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000514 }
515
516#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
517 __SPECIAL_INSTRUCTION_PREAMBLE \
518 /* branch-and-link-to-noredir *%R11 */ \
519 "or 3,3,3\n\t"
520
sewardjf5c1a7f2006-10-17 01:32:48 +0000521#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000522
sewardj59570ff2010-01-01 11:59:33 +0000523/* ------------------------- arm-linux ------------------------- */
524
525#if defined(PLAT_arm_linux)
526
527typedef
528 struct {
529 unsigned int nraddr; /* where's the code? */
530 }
531 OrigFn;
532
533#define __SPECIAL_INSTRUCTION_PREAMBLE \
534 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
535 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
536
bart575ce8e2011-05-15 07:04:03 +0000537#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
538 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000539 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
540 \
bart575ce8e2011-05-15 07:04:03 +0000541 __extension__ \
542 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000543 volatile unsigned int _zzq_result; \
544 _zzq_args[0] = (unsigned int)(_zzq_request); \
545 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
546 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
547 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
548 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
549 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
550 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
551 "mov r4, %2\n\t" /*ptr*/ \
552 __SPECIAL_INSTRUCTION_PREAMBLE \
553 /* R3 = client_request ( R4 ) */ \
554 "orr r10, r10, r10\n\t" \
555 "mov %0, r3" /*result*/ \
556 : "=r" (_zzq_result) \
557 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
558 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000559 _zzq_result; \
560 })
sewardj59570ff2010-01-01 11:59:33 +0000561
562#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
563 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
564 unsigned int __addr; \
565 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
566 /* R3 = guest_NRADDR */ \
567 "orr r11, r11, r11\n\t" \
568 "mov %0, r3" \
569 : "=r" (__addr) \
570 : \
571 : "cc", "memory", "r3" \
572 ); \
573 _zzq_orig->nraddr = __addr; \
574 }
575
576#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
577 __SPECIAL_INSTRUCTION_PREAMBLE \
578 /* branch-and-link-to-noredir *%R4 */ \
579 "orr r12, r12, r12\n\t"
580
581#endif /* PLAT_arm_linux */
582
sewardjb5b87402011-03-07 16:05:35 +0000583/* ------------------------ s390x-linux ------------------------ */
584
585#if defined(PLAT_s390x_linux)
586
587typedef
588 struct {
589 unsigned long long int nraddr; /* where's the code? */
590 }
591 OrigFn;
592
593/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
594 * code. This detection is implemented in platform specific toIR.c
595 * (e.g. VEX/priv/guest_s390_decoder.c).
596 */
597#define __SPECIAL_INSTRUCTION_PREAMBLE \
598 "lr 15,15\n\t" \
599 "lr 1,1\n\t" \
600 "lr 2,2\n\t" \
601 "lr 3,3\n\t"
602
603#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
604#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
605#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
606
bart575ce8e2011-05-15 07:04:03 +0000607#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
608 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000609 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000610 __extension__ \
611 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000612 volatile unsigned long long int _zzq_result; \
613 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
614 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
615 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
616 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
617 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
618 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
619 __asm__ volatile(/* r2 = args */ \
620 "lgr 2,%1\n\t" \
621 /* r3 = default */ \
622 "lgr 3,%2\n\t" \
623 __SPECIAL_INSTRUCTION_PREAMBLE \
624 __CLIENT_REQUEST_CODE \
625 /* results = r3 */ \
626 "lgr %0, 3\n\t" \
627 : "=d" (_zzq_result) \
628 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
629 : "cc", "2", "3", "memory" \
630 ); \
bart575ce8e2011-05-15 07:04:03 +0000631 _zzq_result; \
632 })
sewardjb5b87402011-03-07 16:05:35 +0000633
634#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
635 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
636 volatile unsigned long long int __addr; \
637 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
638 __GET_NR_CONTEXT_CODE \
639 "lgr %0, 3\n\t" \
640 : "=a" (__addr) \
641 : \
642 : "cc", "3", "memory" \
643 ); \
644 _zzq_orig->nraddr = __addr; \
645 }
646
647#define VALGRIND_CALL_NOREDIR_R1 \
648 __SPECIAL_INSTRUCTION_PREAMBLE \
649 __CALL_NO_REDIR_CODE
650
651#endif /* PLAT_s390x_linux */
652
sewardjf5c1a7f2006-10-17 01:32:48 +0000653/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000654
sewardj37091fb2002-11-16 11:06:50 +0000655#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000656
nethercote69d9c462004-10-26 13:00:12 +0000657
njn30d76c62005-06-18 15:07:39 +0000658/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000659/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000660/* ugly. It's the least-worst tradeoff I can think of. */
661/* ------------------------------------------------------------------ */
662
663/* This section defines magic (a.k.a appalling-hack) macros for doing
664 guaranteed-no-redirection macros, so as to get from function
665 wrappers to the functions they are wrapping. The whole point is to
666 construct standard call sequences, but to do the call itself with a
667 special no-redirect call pseudo-instruction that the JIT
668 understands and handles specially. This section is long and
669 repetitious, and I can't see a way to make it shorter.
670
671 The naming scheme is as follows:
672
673 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
674
675 'W' stands for "word" and 'v' for "void". Hence there are
676 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
677 and for each, the possibility of returning a word-typed result, or
678 no result.
679*/
680
681/* Use these to write the name of your wrapper. NOTE: duplicates
682 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
683
njn5f5ef2a2009-05-11 08:01:09 +0000684/* Use an extra level of macroisation so as to ensure the soname/fnname
685 args are fully macro-expanded before pasting them together. */
686#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
687
sewardj0ec07f32006-01-12 12:32:32 +0000688#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000689 VG_CONCAT4(_vgwZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000690
691#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000692 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000693
sewardjd68ac3e2006-01-20 14:31:57 +0000694/* Use this macro from within a wrapper function to collect the
695 context (address and possibly other info) of the original function.
696 Once you have that you can then use it in one of the CALL_FN_
697 macros. The type of the argument _lval is OrigFn. */
698#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000699
700/* Derivatives of the main macros below, for calling functions
701 returning void. */
702
703#define CALL_FN_v_v(fnptr) \
704 do { volatile unsigned long _junk; \
705 CALL_FN_W_v(_junk,fnptr); } while (0)
706
707#define CALL_FN_v_W(fnptr, arg1) \
708 do { volatile unsigned long _junk; \
709 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
710
711#define CALL_FN_v_WW(fnptr, arg1,arg2) \
712 do { volatile unsigned long _junk; \
713 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
714
sewardj5ce4b152006-03-11 12:57:41 +0000715#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
716 do { volatile unsigned long _junk; \
717 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
718
njn2b5f0a92009-05-19 01:24:50 +0000719#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
720 do { volatile unsigned long _junk; \
721 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
722
723#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
724 do { volatile unsigned long _junk; \
725 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
726
727#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
728 do { volatile unsigned long _junk; \
729 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
730
731#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
732 do { volatile unsigned long _junk; \
733 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
734
njnf76d27a2009-05-28 01:53:07 +0000735/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000736
njnf76d27a2009-05-28 01:53:07 +0000737#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000738
739/* These regs are trashed by the hidden call. No need to mention eax
740 as gcc can already see that, plus causes gcc to bomb. */
741#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
742
743/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
744 long) == 4. */
745
sewardj66226cc2006-01-20 15:46:46 +0000746#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000747 do { \
sewardj66226cc2006-01-20 15:46:46 +0000748 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000749 volatile unsigned long _argvec[1]; \
750 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000751 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000752 __asm__ volatile( \
753 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
754 VALGRIND_CALL_NOREDIR_EAX \
755 : /*out*/ "=a" (_res) \
756 : /*in*/ "a" (&_argvec[0]) \
757 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
758 ); \
759 lval = (__typeof__(lval)) _res; \
760 } while (0)
761
sewardj66226cc2006-01-20 15:46:46 +0000762#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000763 do { \
sewardj66226cc2006-01-20 15:46:46 +0000764 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000765 volatile unsigned long _argvec[2]; \
766 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000767 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000768 _argvec[1] = (unsigned long)(arg1); \
769 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000770 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000771 "pushl 4(%%eax)\n\t" \
772 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
773 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000774 "addl $16, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000775 : /*out*/ "=a" (_res) \
776 : /*in*/ "a" (&_argvec[0]) \
777 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
778 ); \
779 lval = (__typeof__(lval)) _res; \
780 } while (0)
781
sewardj66226cc2006-01-20 15:46:46 +0000782#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000783 do { \
sewardj66226cc2006-01-20 15:46:46 +0000784 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000785 volatile unsigned long _argvec[3]; \
786 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000787 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000788 _argvec[1] = (unsigned long)(arg1); \
789 _argvec[2] = (unsigned long)(arg2); \
790 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000791 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000792 "pushl 8(%%eax)\n\t" \
793 "pushl 4(%%eax)\n\t" \
794 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
795 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000796 "addl $16, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000797 : /*out*/ "=a" (_res) \
798 : /*in*/ "a" (&_argvec[0]) \
799 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
800 ); \
801 lval = (__typeof__(lval)) _res; \
802 } while (0)
803
sewardj9e8b07a2006-02-18 21:13:29 +0000804#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
805 do { \
806 volatile OrigFn _orig = (orig); \
807 volatile unsigned long _argvec[4]; \
808 volatile unsigned long _res; \
809 _argvec[0] = (unsigned long)_orig.nraddr; \
810 _argvec[1] = (unsigned long)(arg1); \
811 _argvec[2] = (unsigned long)(arg2); \
812 _argvec[3] = (unsigned long)(arg3); \
813 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000814 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +0000815 "pushl 12(%%eax)\n\t" \
816 "pushl 8(%%eax)\n\t" \
817 "pushl 4(%%eax)\n\t" \
818 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
819 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000820 "addl $16, %%esp\n" \
sewardj9e8b07a2006-02-18 21:13:29 +0000821 : /*out*/ "=a" (_res) \
822 : /*in*/ "a" (&_argvec[0]) \
823 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
824 ); \
825 lval = (__typeof__(lval)) _res; \
826 } while (0)
827
sewardj66226cc2006-01-20 15:46:46 +0000828#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000829 do { \
sewardj66226cc2006-01-20 15:46:46 +0000830 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000831 volatile unsigned long _argvec[5]; \
832 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000833 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000834 _argvec[1] = (unsigned long)(arg1); \
835 _argvec[2] = (unsigned long)(arg2); \
836 _argvec[3] = (unsigned long)(arg3); \
837 _argvec[4] = (unsigned long)(arg4); \
838 __asm__ volatile( \
839 "pushl 16(%%eax)\n\t" \
840 "pushl 12(%%eax)\n\t" \
841 "pushl 8(%%eax)\n\t" \
842 "pushl 4(%%eax)\n\t" \
843 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
844 VALGRIND_CALL_NOREDIR_EAX \
845 "addl $16, %%esp\n" \
846 : /*out*/ "=a" (_res) \
847 : /*in*/ "a" (&_argvec[0]) \
848 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
849 ); \
850 lval = (__typeof__(lval)) _res; \
851 } while (0)
852
sewardj66226cc2006-01-20 15:46:46 +0000853#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000854 do { \
sewardj66226cc2006-01-20 15:46:46 +0000855 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000856 volatile unsigned long _argvec[6]; \
857 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000858 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000859 _argvec[1] = (unsigned long)(arg1); \
860 _argvec[2] = (unsigned long)(arg2); \
861 _argvec[3] = (unsigned long)(arg3); \
862 _argvec[4] = (unsigned long)(arg4); \
863 _argvec[5] = (unsigned long)(arg5); \
864 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000865 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000866 "pushl 20(%%eax)\n\t" \
867 "pushl 16(%%eax)\n\t" \
868 "pushl 12(%%eax)\n\t" \
869 "pushl 8(%%eax)\n\t" \
870 "pushl 4(%%eax)\n\t" \
871 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
872 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000873 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000874 : /*out*/ "=a" (_res) \
875 : /*in*/ "a" (&_argvec[0]) \
876 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
877 ); \
878 lval = (__typeof__(lval)) _res; \
879 } while (0)
880
sewardj66226cc2006-01-20 15:46:46 +0000881#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000882 do { \
sewardj66226cc2006-01-20 15:46:46 +0000883 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000884 volatile unsigned long _argvec[7]; \
885 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000886 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000887 _argvec[1] = (unsigned long)(arg1); \
888 _argvec[2] = (unsigned long)(arg2); \
889 _argvec[3] = (unsigned long)(arg3); \
890 _argvec[4] = (unsigned long)(arg4); \
891 _argvec[5] = (unsigned long)(arg5); \
892 _argvec[6] = (unsigned long)(arg6); \
893 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000894 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000895 "pushl 24(%%eax)\n\t" \
896 "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_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
912 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000913 do { \
sewardj66226cc2006-01-20 15:46:46 +0000914 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000915 volatile unsigned long _argvec[8]; \
916 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000917 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000918 _argvec[1] = (unsigned long)(arg1); \
919 _argvec[2] = (unsigned long)(arg2); \
920 _argvec[3] = (unsigned long)(arg3); \
921 _argvec[4] = (unsigned long)(arg4); \
922 _argvec[5] = (unsigned long)(arg5); \
923 _argvec[6] = (unsigned long)(arg6); \
924 _argvec[7] = (unsigned long)(arg7); \
925 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000926 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000927 "pushl 28(%%eax)\n\t" \
928 "pushl 24(%%eax)\n\t" \
929 "pushl 20(%%eax)\n\t" \
930 "pushl 16(%%eax)\n\t" \
931 "pushl 12(%%eax)\n\t" \
932 "pushl 8(%%eax)\n\t" \
933 "pushl 4(%%eax)\n\t" \
934 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
935 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000936 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000937 : /*out*/ "=a" (_res) \
938 : /*in*/ "a" (&_argvec[0]) \
939 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
940 ); \
941 lval = (__typeof__(lval)) _res; \
942 } while (0)
943
sewardj66226cc2006-01-20 15:46:46 +0000944#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
945 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000946 do { \
sewardj66226cc2006-01-20 15:46:46 +0000947 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000948 volatile unsigned long _argvec[9]; \
949 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000950 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000951 _argvec[1] = (unsigned long)(arg1); \
952 _argvec[2] = (unsigned long)(arg2); \
953 _argvec[3] = (unsigned long)(arg3); \
954 _argvec[4] = (unsigned long)(arg4); \
955 _argvec[5] = (unsigned long)(arg5); \
956 _argvec[6] = (unsigned long)(arg6); \
957 _argvec[7] = (unsigned long)(arg7); \
958 _argvec[8] = (unsigned long)(arg8); \
959 __asm__ volatile( \
960 "pushl 32(%%eax)\n\t" \
961 "pushl 28(%%eax)\n\t" \
962 "pushl 24(%%eax)\n\t" \
963 "pushl 20(%%eax)\n\t" \
964 "pushl 16(%%eax)\n\t" \
965 "pushl 12(%%eax)\n\t" \
966 "pushl 8(%%eax)\n\t" \
967 "pushl 4(%%eax)\n\t" \
968 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
969 VALGRIND_CALL_NOREDIR_EAX \
970 "addl $32, %%esp\n" \
971 : /*out*/ "=a" (_res) \
972 : /*in*/ "a" (&_argvec[0]) \
973 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
974 ); \
975 lval = (__typeof__(lval)) _res; \
976 } while (0)
977
sewardj45fa5b02006-03-09 19:06:23 +0000978#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
979 arg7,arg8,arg9) \
980 do { \
981 volatile OrigFn _orig = (orig); \
982 volatile unsigned long _argvec[10]; \
983 volatile unsigned long _res; \
984 _argvec[0] = (unsigned long)_orig.nraddr; \
985 _argvec[1] = (unsigned long)(arg1); \
986 _argvec[2] = (unsigned long)(arg2); \
987 _argvec[3] = (unsigned long)(arg3); \
988 _argvec[4] = (unsigned long)(arg4); \
989 _argvec[5] = (unsigned long)(arg5); \
990 _argvec[6] = (unsigned long)(arg6); \
991 _argvec[7] = (unsigned long)(arg7); \
992 _argvec[8] = (unsigned long)(arg8); \
993 _argvec[9] = (unsigned long)(arg9); \
994 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000995 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +0000996 "pushl 36(%%eax)\n\t" \
997 "pushl 32(%%eax)\n\t" \
998 "pushl 28(%%eax)\n\t" \
999 "pushl 24(%%eax)\n\t" \
1000 "pushl 20(%%eax)\n\t" \
1001 "pushl 16(%%eax)\n\t" \
1002 "pushl 12(%%eax)\n\t" \
1003 "pushl 8(%%eax)\n\t" \
1004 "pushl 4(%%eax)\n\t" \
1005 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1006 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001007 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001008 : /*out*/ "=a" (_res) \
1009 : /*in*/ "a" (&_argvec[0]) \
1010 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1011 ); \
1012 lval = (__typeof__(lval)) _res; \
1013 } while (0)
1014
1015#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1016 arg7,arg8,arg9,arg10) \
1017 do { \
1018 volatile OrigFn _orig = (orig); \
1019 volatile unsigned long _argvec[11]; \
1020 volatile unsigned long _res; \
1021 _argvec[0] = (unsigned long)_orig.nraddr; \
1022 _argvec[1] = (unsigned long)(arg1); \
1023 _argvec[2] = (unsigned long)(arg2); \
1024 _argvec[3] = (unsigned long)(arg3); \
1025 _argvec[4] = (unsigned long)(arg4); \
1026 _argvec[5] = (unsigned long)(arg5); \
1027 _argvec[6] = (unsigned long)(arg6); \
1028 _argvec[7] = (unsigned long)(arg7); \
1029 _argvec[8] = (unsigned long)(arg8); \
1030 _argvec[9] = (unsigned long)(arg9); \
1031 _argvec[10] = (unsigned long)(arg10); \
1032 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001033 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001034 "pushl 40(%%eax)\n\t" \
1035 "pushl 36(%%eax)\n\t" \
1036 "pushl 32(%%eax)\n\t" \
1037 "pushl 28(%%eax)\n\t" \
1038 "pushl 24(%%eax)\n\t" \
1039 "pushl 20(%%eax)\n\t" \
1040 "pushl 16(%%eax)\n\t" \
1041 "pushl 12(%%eax)\n\t" \
1042 "pushl 8(%%eax)\n\t" \
1043 "pushl 4(%%eax)\n\t" \
1044 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1045 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001046 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001047 : /*out*/ "=a" (_res) \
1048 : /*in*/ "a" (&_argvec[0]) \
1049 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1050 ); \
1051 lval = (__typeof__(lval)) _res; \
1052 } while (0)
1053
sewardj5ce4b152006-03-11 12:57:41 +00001054#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1055 arg6,arg7,arg8,arg9,arg10, \
1056 arg11) \
1057 do { \
1058 volatile OrigFn _orig = (orig); \
1059 volatile unsigned long _argvec[12]; \
1060 volatile unsigned long _res; \
1061 _argvec[0] = (unsigned long)_orig.nraddr; \
1062 _argvec[1] = (unsigned long)(arg1); \
1063 _argvec[2] = (unsigned long)(arg2); \
1064 _argvec[3] = (unsigned long)(arg3); \
1065 _argvec[4] = (unsigned long)(arg4); \
1066 _argvec[5] = (unsigned long)(arg5); \
1067 _argvec[6] = (unsigned long)(arg6); \
1068 _argvec[7] = (unsigned long)(arg7); \
1069 _argvec[8] = (unsigned long)(arg8); \
1070 _argvec[9] = (unsigned long)(arg9); \
1071 _argvec[10] = (unsigned long)(arg10); \
1072 _argvec[11] = (unsigned long)(arg11); \
1073 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001074 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001075 "pushl 44(%%eax)\n\t" \
1076 "pushl 40(%%eax)\n\t" \
1077 "pushl 36(%%eax)\n\t" \
1078 "pushl 32(%%eax)\n\t" \
1079 "pushl 28(%%eax)\n\t" \
1080 "pushl 24(%%eax)\n\t" \
1081 "pushl 20(%%eax)\n\t" \
1082 "pushl 16(%%eax)\n\t" \
1083 "pushl 12(%%eax)\n\t" \
1084 "pushl 8(%%eax)\n\t" \
1085 "pushl 4(%%eax)\n\t" \
1086 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1087 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001088 "addl $48, %%esp\n" \
sewardj5ce4b152006-03-11 12:57:41 +00001089 : /*out*/ "=a" (_res) \
1090 : /*in*/ "a" (&_argvec[0]) \
1091 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1092 ); \
1093 lval = (__typeof__(lval)) _res; \
1094 } while (0)
1095
sewardj66226cc2006-01-20 15:46:46 +00001096#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1097 arg6,arg7,arg8,arg9,arg10, \
1098 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001099 do { \
sewardj66226cc2006-01-20 15:46:46 +00001100 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001101 volatile unsigned long _argvec[13]; \
1102 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001103 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001104 _argvec[1] = (unsigned long)(arg1); \
1105 _argvec[2] = (unsigned long)(arg2); \
1106 _argvec[3] = (unsigned long)(arg3); \
1107 _argvec[4] = (unsigned long)(arg4); \
1108 _argvec[5] = (unsigned long)(arg5); \
1109 _argvec[6] = (unsigned long)(arg6); \
1110 _argvec[7] = (unsigned long)(arg7); \
1111 _argvec[8] = (unsigned long)(arg8); \
1112 _argvec[9] = (unsigned long)(arg9); \
1113 _argvec[10] = (unsigned long)(arg10); \
1114 _argvec[11] = (unsigned long)(arg11); \
1115 _argvec[12] = (unsigned long)(arg12); \
1116 __asm__ volatile( \
1117 "pushl 48(%%eax)\n\t" \
1118 "pushl 44(%%eax)\n\t" \
1119 "pushl 40(%%eax)\n\t" \
1120 "pushl 36(%%eax)\n\t" \
1121 "pushl 32(%%eax)\n\t" \
1122 "pushl 28(%%eax)\n\t" \
1123 "pushl 24(%%eax)\n\t" \
1124 "pushl 20(%%eax)\n\t" \
1125 "pushl 16(%%eax)\n\t" \
1126 "pushl 12(%%eax)\n\t" \
1127 "pushl 8(%%eax)\n\t" \
1128 "pushl 4(%%eax)\n\t" \
1129 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1130 VALGRIND_CALL_NOREDIR_EAX \
1131 "addl $48, %%esp\n" \
1132 : /*out*/ "=a" (_res) \
1133 : /*in*/ "a" (&_argvec[0]) \
1134 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1135 ); \
1136 lval = (__typeof__(lval)) _res; \
1137 } while (0)
1138
njnf76d27a2009-05-28 01:53:07 +00001139#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001140
njnf76d27a2009-05-28 01:53:07 +00001141/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001142
njnf76d27a2009-05-28 01:53:07 +00001143#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001144
1145/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1146
1147/* These regs are trashed by the hidden call. */
1148#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1149 "rdi", "r8", "r9", "r10", "r11"
1150
sewardjdfa55cf2010-10-06 22:07:06 +00001151/* This is all pretty complex. It's so as to make stack unwinding
1152 work reliably. See bug 243270. The basic problem is the sub and
1153 add of 128 of %rsp in all of the following macros. If gcc believes
1154 the CFA is in %rsp, then unwinding may fail, because what's at the
1155 CFA is not what gcc "expected" when it constructs the CFIs for the
1156 places where the macros are instantiated.
1157
1158 But we can't just add a CFI annotation to increase the CFA offset
1159 by 128, to match the sub of 128 from %rsp, because we don't know
1160 whether gcc has chosen %rsp as the CFA at that point, or whether it
1161 has chosen some other register (eg, %rbp). In the latter case,
1162 adding a CFI annotation to change the CFA offset is simply wrong.
1163
1164 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001165 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001166 CFI annotation to say what the register is. We choose %rbp for
1167 this (perhaps perversely), because:
1168
1169 (1) %rbp is already subject to unwinding. If a new register was
1170 chosen then the unwinder would have to unwind it in all stack
1171 traces, which is expensive, and
1172
1173 (2) %rbp is already subject to precise exception updates in the
1174 JIT. If a new register was chosen, we'd have to have precise
1175 exceptions for it too, which reduces performance of the
1176 generated code.
1177
1178 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001179 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001180 list of trashed registers at the end of the inline assembly
1181 fragments; gcc won't allow %rbp to appear in that list. Hence
1182 instead we need to stash %rbp in %r15 for the duration of the asm,
1183 and say that %r15 is trashed instead. gcc seems happy to go with
1184 that.
1185
1186 Oh .. and this all needs to be conditionalised so that it is
1187 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001188 that don't support __builtin_dwarf_cfa. Furthermore, since
1189 this header file is freestanding, it has to be independent of
1190 config.h, and so the following conditionalisation cannot depend on
1191 configure time checks.
1192
1193 Although it's not clear from
1194 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1195 this expression excludes Darwin.
1196 .cfi directives in Darwin assembly appear to be completely
1197 different and I haven't investigated how they work.
1198
1199 For even more entertainment value, note we have to use the
1200 completely undocumented __builtin_dwarf_cfa(), which appears to
1201 really compute the CFA, whereas __builtin_frame_address(0) claims
1202 to but actually doesn't. See
1203 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001204*/
sewardj8d1dc152010-10-08 17:43:26 +00001205#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001206# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001207 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001208# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001209 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001210 "movq %2, %%rbp\n\t" \
1211 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001212 ".cfi_def_cfa rbp, 0\n\t"
1213# define VALGRIND_CFI_EPILOGUE \
1214 "movq %%r15, %%rbp\n\t" \
1215 ".cfi_restore_state\n\t"
1216#else
1217# define __FRAME_POINTER
1218# define VALGRIND_CFI_PROLOGUE
1219# define VALGRIND_CFI_EPILOGUE
1220#endif
1221
1222
sewardj0ec07f32006-01-12 12:32:32 +00001223/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1224 long) == 8. */
1225
sewardja07c2e12007-11-09 23:09:50 +00001226/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1227 macros. In order not to trash the stack redzone, we need to drop
1228 %rsp by 128 before the hidden call, and restore afterwards. The
1229 nastyness is that it is only by luck that the stack still appears
1230 to be unwindable during the hidden call - since then the behaviour
1231 of any routine using this macro does not match what the CFI data
1232 says. Sigh.
1233
1234 Why is this important? Imagine that a wrapper has a stack
1235 allocated local, and passes to the hidden call, a pointer to it.
1236 Because gcc does not know about the hidden call, it may allocate
1237 that local in the redzone. Unfortunately the hidden call may then
1238 trash it before it comes to use it. So we must step clear of the
1239 redzone, for the duration of the hidden call, to make it safe.
1240
1241 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001242 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001243 self describing (none of this CFI nonsense) so at least messing
1244 with the stack pointer doesn't give a danger of non-unwindable
1245 stack. */
1246
sewardjc8858442006-01-20 15:17:20 +00001247#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001248 do { \
sewardjc8858442006-01-20 15:17:20 +00001249 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001250 volatile unsigned long _argvec[1]; \
1251 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001252 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001253 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001254 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001255 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001256 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1257 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001258 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001259 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001260 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001261 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1262 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001263 ); \
1264 lval = (__typeof__(lval)) _res; \
1265 } while (0)
1266
sewardjc8858442006-01-20 15:17:20 +00001267#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001268 do { \
sewardjc8858442006-01-20 15:17:20 +00001269 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001270 volatile unsigned long _argvec[2]; \
1271 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001272 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001273 _argvec[1] = (unsigned long)(arg1); \
1274 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001275 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001276 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001277 "movq 8(%%rax), %%rdi\n\t" \
1278 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1279 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001280 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001281 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001282 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001283 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1284 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001285 ); \
1286 lval = (__typeof__(lval)) _res; \
1287 } while (0)
1288
sewardjc8858442006-01-20 15:17:20 +00001289#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001290 do { \
sewardjc8858442006-01-20 15:17:20 +00001291 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001292 volatile unsigned long _argvec[3]; \
1293 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001294 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001295 _argvec[1] = (unsigned long)(arg1); \
1296 _argvec[2] = (unsigned long)(arg2); \
1297 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001298 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001299 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001300 "movq 16(%%rax), %%rsi\n\t" \
1301 "movq 8(%%rax), %%rdi\n\t" \
1302 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1303 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001304 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001305 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001306 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001307 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1308 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001309 ); \
1310 lval = (__typeof__(lval)) _res; \
1311 } while (0)
1312
sewardja50f9dc2006-03-11 16:19:14 +00001313#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1314 do { \
1315 volatile OrigFn _orig = (orig); \
1316 volatile unsigned long _argvec[4]; \
1317 volatile unsigned long _res; \
1318 _argvec[0] = (unsigned long)_orig.nraddr; \
1319 _argvec[1] = (unsigned long)(arg1); \
1320 _argvec[2] = (unsigned long)(arg2); \
1321 _argvec[3] = (unsigned long)(arg3); \
1322 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001323 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001324 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001325 "movq 24(%%rax), %%rdx\n\t" \
1326 "movq 16(%%rax), %%rsi\n\t" \
1327 "movq 8(%%rax), %%rdi\n\t" \
1328 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1329 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001330 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001331 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001332 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001333 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1334 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001335 ); \
1336 lval = (__typeof__(lval)) _res; \
1337 } while (0)
1338
1339#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1340 do { \
1341 volatile OrigFn _orig = (orig); \
1342 volatile unsigned long _argvec[5]; \
1343 volatile unsigned long _res; \
1344 _argvec[0] = (unsigned long)_orig.nraddr; \
1345 _argvec[1] = (unsigned long)(arg1); \
1346 _argvec[2] = (unsigned long)(arg2); \
1347 _argvec[3] = (unsigned long)(arg3); \
1348 _argvec[4] = (unsigned long)(arg4); \
1349 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001350 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001351 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001352 "movq 32(%%rax), %%rcx\n\t" \
1353 "movq 24(%%rax), %%rdx\n\t" \
1354 "movq 16(%%rax), %%rsi\n\t" \
1355 "movq 8(%%rax), %%rdi\n\t" \
1356 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1357 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001358 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001359 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001360 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001361 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1362 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001363 ); \
1364 lval = (__typeof__(lval)) _res; \
1365 } while (0)
1366
1367#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1368 do { \
1369 volatile OrigFn _orig = (orig); \
1370 volatile unsigned long _argvec[6]; \
1371 volatile unsigned long _res; \
1372 _argvec[0] = (unsigned long)_orig.nraddr; \
1373 _argvec[1] = (unsigned long)(arg1); \
1374 _argvec[2] = (unsigned long)(arg2); \
1375 _argvec[3] = (unsigned long)(arg3); \
1376 _argvec[4] = (unsigned long)(arg4); \
1377 _argvec[5] = (unsigned long)(arg5); \
1378 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001379 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001380 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001381 "movq 40(%%rax), %%r8\n\t" \
1382 "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_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1398 do { \
1399 volatile OrigFn _orig = (orig); \
1400 volatile unsigned long _argvec[7]; \
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 _argvec[6] = (unsigned long)(arg6); \
1409 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001410 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001411 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001412 "movq 48(%%rax), %%r9\n\t" \
1413 "movq 40(%%rax), %%r8\n\t" \
1414 "movq 32(%%rax), %%rcx\n\t" \
1415 "movq 24(%%rax), %%rdx\n\t" \
1416 "movq 16(%%rax), %%rsi\n\t" \
1417 "movq 8(%%rax), %%rdi\n\t" \
1418 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1419 VALGRIND_CALL_NOREDIR_RAX \
bart2823aac2010-09-05 12:10:25 +00001420 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001421 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001422 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001423 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1424 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001425 ); \
1426 lval = (__typeof__(lval)) _res; \
1427 } while (0)
1428
1429#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1430 arg7) \
1431 do { \
1432 volatile OrigFn _orig = (orig); \
1433 volatile unsigned long _argvec[8]; \
1434 volatile unsigned long _res; \
1435 _argvec[0] = (unsigned long)_orig.nraddr; \
1436 _argvec[1] = (unsigned long)(arg1); \
1437 _argvec[2] = (unsigned long)(arg2); \
1438 _argvec[3] = (unsigned long)(arg3); \
1439 _argvec[4] = (unsigned long)(arg4); \
1440 _argvec[5] = (unsigned long)(arg5); \
1441 _argvec[6] = (unsigned long)(arg6); \
1442 _argvec[7] = (unsigned long)(arg7); \
1443 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001444 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001445 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001446 "pushq 56(%%rax)\n\t" \
1447 "movq 48(%%rax), %%r9\n\t" \
1448 "movq 40(%%rax), %%r8\n\t" \
1449 "movq 32(%%rax), %%rcx\n\t" \
1450 "movq 24(%%rax), %%rdx\n\t" \
1451 "movq 16(%%rax), %%rsi\n\t" \
1452 "movq 8(%%rax), %%rdi\n\t" \
1453 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1454 VALGRIND_CALL_NOREDIR_RAX \
1455 "addq $8, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001456 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001457 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001458 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001459 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1460 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001461 ); \
1462 lval = (__typeof__(lval)) _res; \
1463 } while (0)
1464
1465#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1466 arg7,arg8) \
1467 do { \
1468 volatile OrigFn _orig = (orig); \
1469 volatile unsigned long _argvec[9]; \
1470 volatile unsigned long _res; \
1471 _argvec[0] = (unsigned long)_orig.nraddr; \
1472 _argvec[1] = (unsigned long)(arg1); \
1473 _argvec[2] = (unsigned long)(arg2); \
1474 _argvec[3] = (unsigned long)(arg3); \
1475 _argvec[4] = (unsigned long)(arg4); \
1476 _argvec[5] = (unsigned long)(arg5); \
1477 _argvec[6] = (unsigned long)(arg6); \
1478 _argvec[7] = (unsigned long)(arg7); \
1479 _argvec[8] = (unsigned long)(arg8); \
1480 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001481 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001482 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001483 "pushq 64(%%rax)\n\t" \
1484 "pushq 56(%%rax)\n\t" \
1485 "movq 48(%%rax), %%r9\n\t" \
1486 "movq 40(%%rax), %%r8\n\t" \
1487 "movq 32(%%rax), %%rcx\n\t" \
1488 "movq 24(%%rax), %%rdx\n\t" \
1489 "movq 16(%%rax), %%rsi\n\t" \
1490 "movq 8(%%rax), %%rdi\n\t" \
1491 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1492 VALGRIND_CALL_NOREDIR_RAX \
1493 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001494 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001495 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001496 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001497 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1498 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001499 ); \
1500 lval = (__typeof__(lval)) _res; \
1501 } while (0)
1502
1503#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1504 arg7,arg8,arg9) \
1505 do { \
1506 volatile OrigFn _orig = (orig); \
1507 volatile unsigned long _argvec[10]; \
1508 volatile unsigned long _res; \
1509 _argvec[0] = (unsigned long)_orig.nraddr; \
1510 _argvec[1] = (unsigned long)(arg1); \
1511 _argvec[2] = (unsigned long)(arg2); \
1512 _argvec[3] = (unsigned long)(arg3); \
1513 _argvec[4] = (unsigned long)(arg4); \
1514 _argvec[5] = (unsigned long)(arg5); \
1515 _argvec[6] = (unsigned long)(arg6); \
1516 _argvec[7] = (unsigned long)(arg7); \
1517 _argvec[8] = (unsigned long)(arg8); \
1518 _argvec[9] = (unsigned long)(arg9); \
1519 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001520 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001521 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001522 "pushq 72(%%rax)\n\t" \
1523 "pushq 64(%%rax)\n\t" \
1524 "pushq 56(%%rax)\n\t" \
1525 "movq 48(%%rax), %%r9\n\t" \
1526 "movq 40(%%rax), %%r8\n\t" \
1527 "movq 32(%%rax), %%rcx\n\t" \
1528 "movq 24(%%rax), %%rdx\n\t" \
1529 "movq 16(%%rax), %%rsi\n\t" \
1530 "movq 8(%%rax), %%rdi\n\t" \
1531 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1532 VALGRIND_CALL_NOREDIR_RAX \
1533 "addq $24, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001534 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001535 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001536 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001537 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1538 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001539 ); \
1540 lval = (__typeof__(lval)) _res; \
1541 } while (0)
1542
1543#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1544 arg7,arg8,arg9,arg10) \
1545 do { \
1546 volatile OrigFn _orig = (orig); \
1547 volatile unsigned long _argvec[11]; \
1548 volatile unsigned long _res; \
1549 _argvec[0] = (unsigned long)_orig.nraddr; \
1550 _argvec[1] = (unsigned long)(arg1); \
1551 _argvec[2] = (unsigned long)(arg2); \
1552 _argvec[3] = (unsigned long)(arg3); \
1553 _argvec[4] = (unsigned long)(arg4); \
1554 _argvec[5] = (unsigned long)(arg5); \
1555 _argvec[6] = (unsigned long)(arg6); \
1556 _argvec[7] = (unsigned long)(arg7); \
1557 _argvec[8] = (unsigned long)(arg8); \
1558 _argvec[9] = (unsigned long)(arg9); \
1559 _argvec[10] = (unsigned long)(arg10); \
1560 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001561 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001562 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001563 "pushq 80(%%rax)\n\t" \
1564 "pushq 72(%%rax)\n\t" \
1565 "pushq 64(%%rax)\n\t" \
1566 "pushq 56(%%rax)\n\t" \
1567 "movq 48(%%rax), %%r9\n\t" \
1568 "movq 40(%%rax), %%r8\n\t" \
1569 "movq 32(%%rax), %%rcx\n\t" \
1570 "movq 24(%%rax), %%rdx\n\t" \
1571 "movq 16(%%rax), %%rsi\n\t" \
1572 "movq 8(%%rax), %%rdi\n\t" \
1573 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1574 VALGRIND_CALL_NOREDIR_RAX \
1575 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001576 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001577 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001578 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001579 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1580 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001581 ); \
1582 lval = (__typeof__(lval)) _res; \
1583 } while (0)
1584
1585#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1586 arg7,arg8,arg9,arg10,arg11) \
1587 do { \
1588 volatile OrigFn _orig = (orig); \
1589 volatile unsigned long _argvec[12]; \
1590 volatile unsigned long _res; \
1591 _argvec[0] = (unsigned long)_orig.nraddr; \
1592 _argvec[1] = (unsigned long)(arg1); \
1593 _argvec[2] = (unsigned long)(arg2); \
1594 _argvec[3] = (unsigned long)(arg3); \
1595 _argvec[4] = (unsigned long)(arg4); \
1596 _argvec[5] = (unsigned long)(arg5); \
1597 _argvec[6] = (unsigned long)(arg6); \
1598 _argvec[7] = (unsigned long)(arg7); \
1599 _argvec[8] = (unsigned long)(arg8); \
1600 _argvec[9] = (unsigned long)(arg9); \
1601 _argvec[10] = (unsigned long)(arg10); \
1602 _argvec[11] = (unsigned long)(arg11); \
1603 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001604 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001605 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001606 "pushq 88(%%rax)\n\t" \
1607 "pushq 80(%%rax)\n\t" \
1608 "pushq 72(%%rax)\n\t" \
1609 "pushq 64(%%rax)\n\t" \
1610 "pushq 56(%%rax)\n\t" \
1611 "movq 48(%%rax), %%r9\n\t" \
1612 "movq 40(%%rax), %%r8\n\t" \
1613 "movq 32(%%rax), %%rcx\n\t" \
1614 "movq 24(%%rax), %%rdx\n\t" \
1615 "movq 16(%%rax), %%rsi\n\t" \
1616 "movq 8(%%rax), %%rdi\n\t" \
1617 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1618 VALGRIND_CALL_NOREDIR_RAX \
1619 "addq $40, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001620 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001621 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001622 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001623 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1624 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001625 ); \
1626 lval = (__typeof__(lval)) _res; \
1627 } while (0)
1628
1629#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1630 arg7,arg8,arg9,arg10,arg11,arg12) \
1631 do { \
1632 volatile OrigFn _orig = (orig); \
1633 volatile unsigned long _argvec[13]; \
1634 volatile unsigned long _res; \
1635 _argvec[0] = (unsigned long)_orig.nraddr; \
1636 _argvec[1] = (unsigned long)(arg1); \
1637 _argvec[2] = (unsigned long)(arg2); \
1638 _argvec[3] = (unsigned long)(arg3); \
1639 _argvec[4] = (unsigned long)(arg4); \
1640 _argvec[5] = (unsigned long)(arg5); \
1641 _argvec[6] = (unsigned long)(arg6); \
1642 _argvec[7] = (unsigned long)(arg7); \
1643 _argvec[8] = (unsigned long)(arg8); \
1644 _argvec[9] = (unsigned long)(arg9); \
1645 _argvec[10] = (unsigned long)(arg10); \
1646 _argvec[11] = (unsigned long)(arg11); \
1647 _argvec[12] = (unsigned long)(arg12); \
1648 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001649 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001650 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001651 "pushq 96(%%rax)\n\t" \
1652 "pushq 88(%%rax)\n\t" \
1653 "pushq 80(%%rax)\n\t" \
1654 "pushq 72(%%rax)\n\t" \
1655 "pushq 64(%%rax)\n\t" \
1656 "pushq 56(%%rax)\n\t" \
1657 "movq 48(%%rax), %%r9\n\t" \
1658 "movq 40(%%rax), %%r8\n\t" \
1659 "movq 32(%%rax), %%rcx\n\t" \
1660 "movq 24(%%rax), %%rdx\n\t" \
1661 "movq 16(%%rax), %%rsi\n\t" \
1662 "movq 8(%%rax), %%rdi\n\t" \
1663 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1664 VALGRIND_CALL_NOREDIR_RAX \
1665 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001666 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001667 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001668 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001669 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1670 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001671 ); \
1672 lval = (__typeof__(lval)) _res; \
1673 } while (0)
1674
njnf76d27a2009-05-28 01:53:07 +00001675#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001676
sewardjf5c1a7f2006-10-17 01:32:48 +00001677/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001678
sewardjf5c1a7f2006-10-17 01:32:48 +00001679#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001680
sewardjead61df2006-03-12 13:39:15 +00001681/* This is useful for finding out about the on-stack stuff:
1682
1683 extern int f9 ( int,int,int,int,int,int,int,int,int );
1684 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1685 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1686 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1687
1688 int g9 ( void ) {
1689 return f9(11,22,33,44,55,66,77,88,99);
1690 }
1691 int g10 ( void ) {
1692 return f10(11,22,33,44,55,66,77,88,99,110);
1693 }
1694 int g11 ( void ) {
1695 return f11(11,22,33,44,55,66,77,88,99,110,121);
1696 }
1697 int g12 ( void ) {
1698 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1699 }
1700*/
1701
sewardj0ec07f32006-01-12 12:32:32 +00001702/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1703
1704/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001705#define __CALLER_SAVED_REGS \
1706 "lr", "ctr", "xer", \
1707 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1708 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1709 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001710
sewardjead61df2006-03-12 13:39:15 +00001711/* These CALL_FN_ macros assume that on ppc32-linux,
1712 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001713
sewardj38de0992006-01-20 16:46:34 +00001714#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001715 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001716 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001717 volatile unsigned long _argvec[1]; \
1718 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001719 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001720 __asm__ volatile( \
1721 "mr 11,%1\n\t" \
1722 "lwz 11,0(11)\n\t" /* target->r11 */ \
1723 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1724 "mr %0,3" \
1725 : /*out*/ "=r" (_res) \
1726 : /*in*/ "r" (&_argvec[0]) \
1727 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1728 ); \
1729 lval = (__typeof__(lval)) _res; \
1730 } while (0)
1731
sewardj38de0992006-01-20 16:46:34 +00001732#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001733 do { \
sewardj38de0992006-01-20 16:46:34 +00001734 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001735 volatile unsigned long _argvec[2]; \
1736 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001737 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001738 _argvec[1] = (unsigned long)arg1; \
1739 __asm__ volatile( \
1740 "mr 11,%1\n\t" \
1741 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1742 "lwz 11,0(11)\n\t" /* target->r11 */ \
1743 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1744 "mr %0,3" \
1745 : /*out*/ "=r" (_res) \
1746 : /*in*/ "r" (&_argvec[0]) \
1747 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1748 ); \
1749 lval = (__typeof__(lval)) _res; \
1750 } while (0)
1751
sewardj38de0992006-01-20 16:46:34 +00001752#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001753 do { \
sewardj38de0992006-01-20 16:46:34 +00001754 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001755 volatile unsigned long _argvec[3]; \
1756 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001757 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001758 _argvec[1] = (unsigned long)arg1; \
1759 _argvec[2] = (unsigned long)arg2; \
1760 __asm__ volatile( \
1761 "mr 11,%1\n\t" \
1762 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1763 "lwz 4,8(11)\n\t" \
1764 "lwz 11,0(11)\n\t" /* target->r11 */ \
1765 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1766 "mr %0,3" \
1767 : /*out*/ "=r" (_res) \
1768 : /*in*/ "r" (&_argvec[0]) \
1769 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1770 ); \
1771 lval = (__typeof__(lval)) _res; \
1772 } while (0)
1773
sewardjead61df2006-03-12 13:39:15 +00001774#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1775 do { \
1776 volatile OrigFn _orig = (orig); \
1777 volatile unsigned long _argvec[4]; \
1778 volatile unsigned long _res; \
1779 _argvec[0] = (unsigned long)_orig.nraddr; \
1780 _argvec[1] = (unsigned long)arg1; \
1781 _argvec[2] = (unsigned long)arg2; \
1782 _argvec[3] = (unsigned long)arg3; \
1783 __asm__ volatile( \
1784 "mr 11,%1\n\t" \
1785 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1786 "lwz 4,8(11)\n\t" \
1787 "lwz 5,12(11)\n\t" \
1788 "lwz 11,0(11)\n\t" /* target->r11 */ \
1789 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1790 "mr %0,3" \
1791 : /*out*/ "=r" (_res) \
1792 : /*in*/ "r" (&_argvec[0]) \
1793 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1794 ); \
1795 lval = (__typeof__(lval)) _res; \
1796 } while (0)
1797
1798#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1799 do { \
1800 volatile OrigFn _orig = (orig); \
1801 volatile unsigned long _argvec[5]; \
1802 volatile unsigned long _res; \
1803 _argvec[0] = (unsigned long)_orig.nraddr; \
1804 _argvec[1] = (unsigned long)arg1; \
1805 _argvec[2] = (unsigned long)arg2; \
1806 _argvec[3] = (unsigned long)arg3; \
1807 _argvec[4] = (unsigned long)arg4; \
1808 __asm__ volatile( \
1809 "mr 11,%1\n\t" \
1810 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1811 "lwz 4,8(11)\n\t" \
1812 "lwz 5,12(11)\n\t" \
1813 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1814 "lwz 11,0(11)\n\t" /* target->r11 */ \
1815 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1816 "mr %0,3" \
1817 : /*out*/ "=r" (_res) \
1818 : /*in*/ "r" (&_argvec[0]) \
1819 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1820 ); \
1821 lval = (__typeof__(lval)) _res; \
1822 } while (0)
1823
1824#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1825 do { \
1826 volatile OrigFn _orig = (orig); \
1827 volatile unsigned long _argvec[6]; \
1828 volatile unsigned long _res; \
1829 _argvec[0] = (unsigned long)_orig.nraddr; \
1830 _argvec[1] = (unsigned long)arg1; \
1831 _argvec[2] = (unsigned long)arg2; \
1832 _argvec[3] = (unsigned long)arg3; \
1833 _argvec[4] = (unsigned long)arg4; \
1834 _argvec[5] = (unsigned long)arg5; \
1835 __asm__ volatile( \
1836 "mr 11,%1\n\t" \
1837 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1838 "lwz 4,8(11)\n\t" \
1839 "lwz 5,12(11)\n\t" \
1840 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1841 "lwz 7,20(11)\n\t" \
1842 "lwz 11,0(11)\n\t" /* target->r11 */ \
1843 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1844 "mr %0,3" \
1845 : /*out*/ "=r" (_res) \
1846 : /*in*/ "r" (&_argvec[0]) \
1847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1848 ); \
1849 lval = (__typeof__(lval)) _res; \
1850 } while (0)
1851
1852#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1853 do { \
1854 volatile OrigFn _orig = (orig); \
1855 volatile unsigned long _argvec[7]; \
1856 volatile unsigned long _res; \
1857 _argvec[0] = (unsigned long)_orig.nraddr; \
1858 _argvec[1] = (unsigned long)arg1; \
1859 _argvec[2] = (unsigned long)arg2; \
1860 _argvec[3] = (unsigned long)arg3; \
1861 _argvec[4] = (unsigned long)arg4; \
1862 _argvec[5] = (unsigned long)arg5; \
1863 _argvec[6] = (unsigned long)arg6; \
1864 __asm__ volatile( \
1865 "mr 11,%1\n\t" \
1866 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1867 "lwz 4,8(11)\n\t" \
1868 "lwz 5,12(11)\n\t" \
1869 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1870 "lwz 7,20(11)\n\t" \
1871 "lwz 8,24(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_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1883 arg7) \
1884 do { \
1885 volatile OrigFn _orig = (orig); \
1886 volatile unsigned long _argvec[8]; \
1887 volatile unsigned long _res; \
1888 _argvec[0] = (unsigned long)_orig.nraddr; \
1889 _argvec[1] = (unsigned long)arg1; \
1890 _argvec[2] = (unsigned long)arg2; \
1891 _argvec[3] = (unsigned long)arg3; \
1892 _argvec[4] = (unsigned long)arg4; \
1893 _argvec[5] = (unsigned long)arg5; \
1894 _argvec[6] = (unsigned long)arg6; \
1895 _argvec[7] = (unsigned long)arg7; \
1896 __asm__ volatile( \
1897 "mr 11,%1\n\t" \
1898 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1899 "lwz 4,8(11)\n\t" \
1900 "lwz 5,12(11)\n\t" \
1901 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1902 "lwz 7,20(11)\n\t" \
1903 "lwz 8,24(11)\n\t" \
1904 "lwz 9,28(11)\n\t" \
1905 "lwz 11,0(11)\n\t" /* target->r11 */ \
1906 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1907 "mr %0,3" \
1908 : /*out*/ "=r" (_res) \
1909 : /*in*/ "r" (&_argvec[0]) \
1910 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1911 ); \
1912 lval = (__typeof__(lval)) _res; \
1913 } while (0)
1914
1915#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1916 arg7,arg8) \
1917 do { \
1918 volatile OrigFn _orig = (orig); \
1919 volatile unsigned long _argvec[9]; \
1920 volatile unsigned long _res; \
1921 _argvec[0] = (unsigned long)_orig.nraddr; \
1922 _argvec[1] = (unsigned long)arg1; \
1923 _argvec[2] = (unsigned long)arg2; \
1924 _argvec[3] = (unsigned long)arg3; \
1925 _argvec[4] = (unsigned long)arg4; \
1926 _argvec[5] = (unsigned long)arg5; \
1927 _argvec[6] = (unsigned long)arg6; \
1928 _argvec[7] = (unsigned long)arg7; \
1929 _argvec[8] = (unsigned long)arg8; \
1930 __asm__ volatile( \
1931 "mr 11,%1\n\t" \
1932 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1933 "lwz 4,8(11)\n\t" \
1934 "lwz 5,12(11)\n\t" \
1935 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1936 "lwz 7,20(11)\n\t" \
1937 "lwz 8,24(11)\n\t" \
1938 "lwz 9,28(11)\n\t" \
1939 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1940 "lwz 11,0(11)\n\t" /* target->r11 */ \
1941 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1942 "mr %0,3" \
1943 : /*out*/ "=r" (_res) \
1944 : /*in*/ "r" (&_argvec[0]) \
1945 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1946 ); \
1947 lval = (__typeof__(lval)) _res; \
1948 } while (0)
1949
1950#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1951 arg7,arg8,arg9) \
1952 do { \
1953 volatile OrigFn _orig = (orig); \
1954 volatile unsigned long _argvec[10]; \
1955 volatile unsigned long _res; \
1956 _argvec[0] = (unsigned long)_orig.nraddr; \
1957 _argvec[1] = (unsigned long)arg1; \
1958 _argvec[2] = (unsigned long)arg2; \
1959 _argvec[3] = (unsigned long)arg3; \
1960 _argvec[4] = (unsigned long)arg4; \
1961 _argvec[5] = (unsigned long)arg5; \
1962 _argvec[6] = (unsigned long)arg6; \
1963 _argvec[7] = (unsigned long)arg7; \
1964 _argvec[8] = (unsigned long)arg8; \
1965 _argvec[9] = (unsigned long)arg9; \
1966 __asm__ volatile( \
1967 "mr 11,%1\n\t" \
1968 "addi 1,1,-16\n\t" \
1969 /* arg9 */ \
1970 "lwz 3,36(11)\n\t" \
1971 "stw 3,8(1)\n\t" \
1972 /* args1-8 */ \
1973 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1974 "lwz 4,8(11)\n\t" \
1975 "lwz 5,12(11)\n\t" \
1976 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1977 "lwz 7,20(11)\n\t" \
1978 "lwz 8,24(11)\n\t" \
1979 "lwz 9,28(11)\n\t" \
1980 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1981 "lwz 11,0(11)\n\t" /* target->r11 */ \
1982 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1983 "addi 1,1,16\n\t" \
1984 "mr %0,3" \
1985 : /*out*/ "=r" (_res) \
1986 : /*in*/ "r" (&_argvec[0]) \
1987 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1988 ); \
1989 lval = (__typeof__(lval)) _res; \
1990 } while (0)
1991
1992#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1993 arg7,arg8,arg9,arg10) \
1994 do { \
1995 volatile OrigFn _orig = (orig); \
1996 volatile unsigned long _argvec[11]; \
1997 volatile unsigned long _res; \
1998 _argvec[0] = (unsigned long)_orig.nraddr; \
1999 _argvec[1] = (unsigned long)arg1; \
2000 _argvec[2] = (unsigned long)arg2; \
2001 _argvec[3] = (unsigned long)arg3; \
2002 _argvec[4] = (unsigned long)arg4; \
2003 _argvec[5] = (unsigned long)arg5; \
2004 _argvec[6] = (unsigned long)arg6; \
2005 _argvec[7] = (unsigned long)arg7; \
2006 _argvec[8] = (unsigned long)arg8; \
2007 _argvec[9] = (unsigned long)arg9; \
2008 _argvec[10] = (unsigned long)arg10; \
2009 __asm__ volatile( \
2010 "mr 11,%1\n\t" \
2011 "addi 1,1,-16\n\t" \
2012 /* arg10 */ \
2013 "lwz 3,40(11)\n\t" \
2014 "stw 3,12(1)\n\t" \
2015 /* arg9 */ \
2016 "lwz 3,36(11)\n\t" \
2017 "stw 3,8(1)\n\t" \
2018 /* args1-8 */ \
2019 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2020 "lwz 4,8(11)\n\t" \
2021 "lwz 5,12(11)\n\t" \
2022 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2023 "lwz 7,20(11)\n\t" \
2024 "lwz 8,24(11)\n\t" \
2025 "lwz 9,28(11)\n\t" \
2026 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2027 "lwz 11,0(11)\n\t" /* target->r11 */ \
2028 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2029 "addi 1,1,16\n\t" \
2030 "mr %0,3" \
2031 : /*out*/ "=r" (_res) \
2032 : /*in*/ "r" (&_argvec[0]) \
2033 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2034 ); \
2035 lval = (__typeof__(lval)) _res; \
2036 } while (0)
2037
2038#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2039 arg7,arg8,arg9,arg10,arg11) \
2040 do { \
2041 volatile OrigFn _orig = (orig); \
2042 volatile unsigned long _argvec[12]; \
2043 volatile unsigned long _res; \
2044 _argvec[0] = (unsigned long)_orig.nraddr; \
2045 _argvec[1] = (unsigned long)arg1; \
2046 _argvec[2] = (unsigned long)arg2; \
2047 _argvec[3] = (unsigned long)arg3; \
2048 _argvec[4] = (unsigned long)arg4; \
2049 _argvec[5] = (unsigned long)arg5; \
2050 _argvec[6] = (unsigned long)arg6; \
2051 _argvec[7] = (unsigned long)arg7; \
2052 _argvec[8] = (unsigned long)arg8; \
2053 _argvec[9] = (unsigned long)arg9; \
2054 _argvec[10] = (unsigned long)arg10; \
2055 _argvec[11] = (unsigned long)arg11; \
2056 __asm__ volatile( \
2057 "mr 11,%1\n\t" \
2058 "addi 1,1,-32\n\t" \
2059 /* arg11 */ \
2060 "lwz 3,44(11)\n\t" \
2061 "stw 3,16(1)\n\t" \
2062 /* arg10 */ \
2063 "lwz 3,40(11)\n\t" \
2064 "stw 3,12(1)\n\t" \
2065 /* arg9 */ \
2066 "lwz 3,36(11)\n\t" \
2067 "stw 3,8(1)\n\t" \
2068 /* args1-8 */ \
2069 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2070 "lwz 4,8(11)\n\t" \
2071 "lwz 5,12(11)\n\t" \
2072 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2073 "lwz 7,20(11)\n\t" \
2074 "lwz 8,24(11)\n\t" \
2075 "lwz 9,28(11)\n\t" \
2076 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2077 "lwz 11,0(11)\n\t" /* target->r11 */ \
2078 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2079 "addi 1,1,32\n\t" \
2080 "mr %0,3" \
2081 : /*out*/ "=r" (_res) \
2082 : /*in*/ "r" (&_argvec[0]) \
2083 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2084 ); \
2085 lval = (__typeof__(lval)) _res; \
2086 } while (0)
2087
2088#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2089 arg7,arg8,arg9,arg10,arg11,arg12) \
2090 do { \
2091 volatile OrigFn _orig = (orig); \
2092 volatile unsigned long _argvec[13]; \
2093 volatile unsigned long _res; \
2094 _argvec[0] = (unsigned long)_orig.nraddr; \
2095 _argvec[1] = (unsigned long)arg1; \
2096 _argvec[2] = (unsigned long)arg2; \
2097 _argvec[3] = (unsigned long)arg3; \
2098 _argvec[4] = (unsigned long)arg4; \
2099 _argvec[5] = (unsigned long)arg5; \
2100 _argvec[6] = (unsigned long)arg6; \
2101 _argvec[7] = (unsigned long)arg7; \
2102 _argvec[8] = (unsigned long)arg8; \
2103 _argvec[9] = (unsigned long)arg9; \
2104 _argvec[10] = (unsigned long)arg10; \
2105 _argvec[11] = (unsigned long)arg11; \
2106 _argvec[12] = (unsigned long)arg12; \
2107 __asm__ volatile( \
2108 "mr 11,%1\n\t" \
2109 "addi 1,1,-32\n\t" \
2110 /* arg12 */ \
2111 "lwz 3,48(11)\n\t" \
2112 "stw 3,20(1)\n\t" \
2113 /* arg11 */ \
2114 "lwz 3,44(11)\n\t" \
2115 "stw 3,16(1)\n\t" \
2116 /* arg10 */ \
2117 "lwz 3,40(11)\n\t" \
2118 "stw 3,12(1)\n\t" \
2119 /* arg9 */ \
2120 "lwz 3,36(11)\n\t" \
2121 "stw 3,8(1)\n\t" \
2122 /* args1-8 */ \
2123 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2124 "lwz 4,8(11)\n\t" \
2125 "lwz 5,12(11)\n\t" \
2126 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2127 "lwz 7,20(11)\n\t" \
2128 "lwz 8,24(11)\n\t" \
2129 "lwz 9,28(11)\n\t" \
2130 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2131 "lwz 11,0(11)\n\t" /* target->r11 */ \
2132 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2133 "addi 1,1,32\n\t" \
2134 "mr %0,3" \
2135 : /*out*/ "=r" (_res) \
2136 : /*in*/ "r" (&_argvec[0]) \
2137 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2138 ); \
2139 lval = (__typeof__(lval)) _res; \
2140 } while (0)
2141
sewardjf5c1a7f2006-10-17 01:32:48 +00002142#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002143
sewardjf5c1a7f2006-10-17 01:32:48 +00002144/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002145
sewardjf5c1a7f2006-10-17 01:32:48 +00002146#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002147
2148/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2149
2150/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002151#define __CALLER_SAVED_REGS \
2152 "lr", "ctr", "xer", \
2153 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2154 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2155 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002156
2157/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2158 long) == 8. */
2159
sewardjd68ac3e2006-01-20 14:31:57 +00002160#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002161 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002162 volatile OrigFn _orig = (orig); \
2163 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002164 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002165 /* _argvec[0] holds current r2 across the call */ \
2166 _argvec[1] = (unsigned long)_orig.r2; \
2167 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002168 __asm__ volatile( \
2169 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002170 "std 2,-16(11)\n\t" /* save tocptr */ \
2171 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2172 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002173 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2174 "mr 11,%1\n\t" \
2175 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002176 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002177 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002178 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002179 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2180 ); \
2181 lval = (__typeof__(lval)) _res; \
2182 } while (0)
2183
sewardjd68ac3e2006-01-20 14:31:57 +00002184#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002185 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002186 volatile OrigFn _orig = (orig); \
2187 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002188 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002189 /* _argvec[0] holds current r2 across the call */ \
2190 _argvec[1] = (unsigned long)_orig.r2; \
2191 _argvec[2] = (unsigned long)_orig.nraddr; \
2192 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002193 __asm__ volatile( \
2194 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002195 "std 2,-16(11)\n\t" /* save tocptr */ \
2196 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2197 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2198 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002199 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2200 "mr 11,%1\n\t" \
2201 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002202 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002203 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002204 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002205 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2206 ); \
2207 lval = (__typeof__(lval)) _res; \
2208 } while (0)
2209
sewardjd68ac3e2006-01-20 14:31:57 +00002210#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002211 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002212 volatile OrigFn _orig = (orig); \
2213 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002214 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002215 /* _argvec[0] holds current r2 across the call */ \
2216 _argvec[1] = (unsigned long)_orig.r2; \
2217 _argvec[2] = (unsigned long)_orig.nraddr; \
2218 _argvec[2+1] = (unsigned long)arg1; \
2219 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002220 __asm__ volatile( \
2221 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002222 "std 2,-16(11)\n\t" /* save tocptr */ \
2223 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2224 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002225 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002226 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002227 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2228 "mr 11,%1\n\t" \
2229 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002230 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002231 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002232 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002233 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2234 ); \
2235 lval = (__typeof__(lval)) _res; \
2236 } while (0)
2237
sewardjcd636392006-03-12 16:48:14 +00002238#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2239 do { \
2240 volatile OrigFn _orig = (orig); \
2241 volatile unsigned long _argvec[3+3]; \
2242 volatile unsigned long _res; \
2243 /* _argvec[0] holds current r2 across the call */ \
2244 _argvec[1] = (unsigned long)_orig.r2; \
2245 _argvec[2] = (unsigned long)_orig.nraddr; \
2246 _argvec[2+1] = (unsigned long)arg1; \
2247 _argvec[2+2] = (unsigned long)arg2; \
2248 _argvec[2+3] = (unsigned long)arg3; \
2249 __asm__ volatile( \
2250 "mr 11,%1\n\t" \
2251 "std 2,-16(11)\n\t" /* save tocptr */ \
2252 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2253 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2254 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2255 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2256 "ld 11, 0(11)\n\t" /* target->r11 */ \
2257 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2258 "mr 11,%1\n\t" \
2259 "mr %0,3\n\t" \
2260 "ld 2,-16(11)" /* restore tocptr */ \
2261 : /*out*/ "=r" (_res) \
2262 : /*in*/ "r" (&_argvec[2]) \
2263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2264 ); \
2265 lval = (__typeof__(lval)) _res; \
2266 } while (0)
2267
2268#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2269 do { \
2270 volatile OrigFn _orig = (orig); \
2271 volatile unsigned long _argvec[3+4]; \
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 _argvec[2+4] = (unsigned long)arg4; \
2280 __asm__ volatile( \
2281 "mr 11,%1\n\t" \
2282 "std 2,-16(11)\n\t" /* save tocptr */ \
2283 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2284 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2285 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2286 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2287 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2288 "ld 11, 0(11)\n\t" /* target->r11 */ \
2289 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2290 "mr 11,%1\n\t" \
2291 "mr %0,3\n\t" \
2292 "ld 2,-16(11)" /* restore tocptr */ \
2293 : /*out*/ "=r" (_res) \
2294 : /*in*/ "r" (&_argvec[2]) \
2295 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2296 ); \
2297 lval = (__typeof__(lval)) _res; \
2298 } while (0)
2299
2300#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2301 do { \
2302 volatile OrigFn _orig = (orig); \
2303 volatile unsigned long _argvec[3+5]; \
2304 volatile unsigned long _res; \
2305 /* _argvec[0] holds current r2 across the call */ \
2306 _argvec[1] = (unsigned long)_orig.r2; \
2307 _argvec[2] = (unsigned long)_orig.nraddr; \
2308 _argvec[2+1] = (unsigned long)arg1; \
2309 _argvec[2+2] = (unsigned long)arg2; \
2310 _argvec[2+3] = (unsigned long)arg3; \
2311 _argvec[2+4] = (unsigned long)arg4; \
2312 _argvec[2+5] = (unsigned long)arg5; \
2313 __asm__ volatile( \
2314 "mr 11,%1\n\t" \
2315 "std 2,-16(11)\n\t" /* save tocptr */ \
2316 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2317 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2318 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2319 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2320 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2321 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2322 "ld 11, 0(11)\n\t" /* target->r11 */ \
2323 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2324 "mr 11,%1\n\t" \
2325 "mr %0,3\n\t" \
2326 "ld 2,-16(11)" /* restore tocptr */ \
2327 : /*out*/ "=r" (_res) \
2328 : /*in*/ "r" (&_argvec[2]) \
2329 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2330 ); \
2331 lval = (__typeof__(lval)) _res; \
2332 } while (0)
2333
2334#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2335 do { \
2336 volatile OrigFn _orig = (orig); \
2337 volatile unsigned long _argvec[3+6]; \
2338 volatile unsigned long _res; \
2339 /* _argvec[0] holds current r2 across the call */ \
2340 _argvec[1] = (unsigned long)_orig.r2; \
2341 _argvec[2] = (unsigned long)_orig.nraddr; \
2342 _argvec[2+1] = (unsigned long)arg1; \
2343 _argvec[2+2] = (unsigned long)arg2; \
2344 _argvec[2+3] = (unsigned long)arg3; \
2345 _argvec[2+4] = (unsigned long)arg4; \
2346 _argvec[2+5] = (unsigned long)arg5; \
2347 _argvec[2+6] = (unsigned long)arg6; \
2348 __asm__ volatile( \
2349 "mr 11,%1\n\t" \
2350 "std 2,-16(11)\n\t" /* save tocptr */ \
2351 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2352 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2353 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2354 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2355 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2356 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2357 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2358 "ld 11, 0(11)\n\t" /* target->r11 */ \
2359 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2360 "mr 11,%1\n\t" \
2361 "mr %0,3\n\t" \
2362 "ld 2,-16(11)" /* restore tocptr */ \
2363 : /*out*/ "=r" (_res) \
2364 : /*in*/ "r" (&_argvec[2]) \
2365 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2366 ); \
2367 lval = (__typeof__(lval)) _res; \
2368 } while (0)
2369
2370#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2371 arg7) \
2372 do { \
2373 volatile OrigFn _orig = (orig); \
2374 volatile unsigned long _argvec[3+7]; \
2375 volatile unsigned long _res; \
2376 /* _argvec[0] holds current r2 across the call */ \
2377 _argvec[1] = (unsigned long)_orig.r2; \
2378 _argvec[2] = (unsigned long)_orig.nraddr; \
2379 _argvec[2+1] = (unsigned long)arg1; \
2380 _argvec[2+2] = (unsigned long)arg2; \
2381 _argvec[2+3] = (unsigned long)arg3; \
2382 _argvec[2+4] = (unsigned long)arg4; \
2383 _argvec[2+5] = (unsigned long)arg5; \
2384 _argvec[2+6] = (unsigned long)arg6; \
2385 _argvec[2+7] = (unsigned long)arg7; \
2386 __asm__ volatile( \
2387 "mr 11,%1\n\t" \
2388 "std 2,-16(11)\n\t" /* save tocptr */ \
2389 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2390 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2391 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2392 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2393 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2394 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2395 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2396 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2397 "ld 11, 0(11)\n\t" /* target->r11 */ \
2398 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2399 "mr 11,%1\n\t" \
2400 "mr %0,3\n\t" \
2401 "ld 2,-16(11)" /* restore tocptr */ \
2402 : /*out*/ "=r" (_res) \
2403 : /*in*/ "r" (&_argvec[2]) \
2404 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2405 ); \
2406 lval = (__typeof__(lval)) _res; \
2407 } while (0)
2408
2409#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2410 arg7,arg8) \
2411 do { \
2412 volatile OrigFn _orig = (orig); \
2413 volatile unsigned long _argvec[3+8]; \
2414 volatile unsigned long _res; \
2415 /* _argvec[0] holds current r2 across the call */ \
2416 _argvec[1] = (unsigned long)_orig.r2; \
2417 _argvec[2] = (unsigned long)_orig.nraddr; \
2418 _argvec[2+1] = (unsigned long)arg1; \
2419 _argvec[2+2] = (unsigned long)arg2; \
2420 _argvec[2+3] = (unsigned long)arg3; \
2421 _argvec[2+4] = (unsigned long)arg4; \
2422 _argvec[2+5] = (unsigned long)arg5; \
2423 _argvec[2+6] = (unsigned long)arg6; \
2424 _argvec[2+7] = (unsigned long)arg7; \
2425 _argvec[2+8] = (unsigned long)arg8; \
2426 __asm__ volatile( \
2427 "mr 11,%1\n\t" \
2428 "std 2,-16(11)\n\t" /* save tocptr */ \
2429 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2430 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2431 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2432 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2433 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2434 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2435 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2436 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2437 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2438 "ld 11, 0(11)\n\t" /* target->r11 */ \
2439 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2440 "mr 11,%1\n\t" \
2441 "mr %0,3\n\t" \
2442 "ld 2,-16(11)" /* restore tocptr */ \
2443 : /*out*/ "=r" (_res) \
2444 : /*in*/ "r" (&_argvec[2]) \
2445 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2446 ); \
2447 lval = (__typeof__(lval)) _res; \
2448 } while (0)
2449
2450#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2451 arg7,arg8,arg9) \
2452 do { \
2453 volatile OrigFn _orig = (orig); \
2454 volatile unsigned long _argvec[3+9]; \
2455 volatile unsigned long _res; \
2456 /* _argvec[0] holds current r2 across the call */ \
2457 _argvec[1] = (unsigned long)_orig.r2; \
2458 _argvec[2] = (unsigned long)_orig.nraddr; \
2459 _argvec[2+1] = (unsigned long)arg1; \
2460 _argvec[2+2] = (unsigned long)arg2; \
2461 _argvec[2+3] = (unsigned long)arg3; \
2462 _argvec[2+4] = (unsigned long)arg4; \
2463 _argvec[2+5] = (unsigned long)arg5; \
2464 _argvec[2+6] = (unsigned long)arg6; \
2465 _argvec[2+7] = (unsigned long)arg7; \
2466 _argvec[2+8] = (unsigned long)arg8; \
2467 _argvec[2+9] = (unsigned long)arg9; \
2468 __asm__ volatile( \
2469 "mr 11,%1\n\t" \
2470 "std 2,-16(11)\n\t" /* save tocptr */ \
2471 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2472 "addi 1,1,-128\n\t" /* expand stack frame */ \
2473 /* arg9 */ \
2474 "ld 3,72(11)\n\t" \
2475 "std 3,112(1)\n\t" \
2476 /* args1-8 */ \
2477 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2478 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2479 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2480 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2481 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2482 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2483 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2484 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2485 "ld 11, 0(11)\n\t" /* target->r11 */ \
2486 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2487 "mr 11,%1\n\t" \
2488 "mr %0,3\n\t" \
2489 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2490 "addi 1,1,128" /* restore frame */ \
2491 : /*out*/ "=r" (_res) \
2492 : /*in*/ "r" (&_argvec[2]) \
2493 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2494 ); \
2495 lval = (__typeof__(lval)) _res; \
2496 } while (0)
2497
2498#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2499 arg7,arg8,arg9,arg10) \
2500 do { \
2501 volatile OrigFn _orig = (orig); \
2502 volatile unsigned long _argvec[3+10]; \
2503 volatile unsigned long _res; \
2504 /* _argvec[0] holds current r2 across the call */ \
2505 _argvec[1] = (unsigned long)_orig.r2; \
2506 _argvec[2] = (unsigned long)_orig.nraddr; \
2507 _argvec[2+1] = (unsigned long)arg1; \
2508 _argvec[2+2] = (unsigned long)arg2; \
2509 _argvec[2+3] = (unsigned long)arg3; \
2510 _argvec[2+4] = (unsigned long)arg4; \
2511 _argvec[2+5] = (unsigned long)arg5; \
2512 _argvec[2+6] = (unsigned long)arg6; \
2513 _argvec[2+7] = (unsigned long)arg7; \
2514 _argvec[2+8] = (unsigned long)arg8; \
2515 _argvec[2+9] = (unsigned long)arg9; \
2516 _argvec[2+10] = (unsigned long)arg10; \
2517 __asm__ volatile( \
2518 "mr 11,%1\n\t" \
2519 "std 2,-16(11)\n\t" /* save tocptr */ \
2520 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2521 "addi 1,1,-128\n\t" /* expand stack frame */ \
2522 /* arg10 */ \
2523 "ld 3,80(11)\n\t" \
2524 "std 3,120(1)\n\t" \
2525 /* arg9 */ \
2526 "ld 3,72(11)\n\t" \
2527 "std 3,112(1)\n\t" \
2528 /* args1-8 */ \
2529 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2530 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2531 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2532 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2533 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2534 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2535 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2536 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2537 "ld 11, 0(11)\n\t" /* target->r11 */ \
2538 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2539 "mr 11,%1\n\t" \
2540 "mr %0,3\n\t" \
2541 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2542 "addi 1,1,128" /* restore frame */ \
2543 : /*out*/ "=r" (_res) \
2544 : /*in*/ "r" (&_argvec[2]) \
2545 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2546 ); \
2547 lval = (__typeof__(lval)) _res; \
2548 } while (0)
2549
2550#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2551 arg7,arg8,arg9,arg10,arg11) \
2552 do { \
2553 volatile OrigFn _orig = (orig); \
2554 volatile unsigned long _argvec[3+11]; \
2555 volatile unsigned long _res; \
2556 /* _argvec[0] holds current r2 across the call */ \
2557 _argvec[1] = (unsigned long)_orig.r2; \
2558 _argvec[2] = (unsigned long)_orig.nraddr; \
2559 _argvec[2+1] = (unsigned long)arg1; \
2560 _argvec[2+2] = (unsigned long)arg2; \
2561 _argvec[2+3] = (unsigned long)arg3; \
2562 _argvec[2+4] = (unsigned long)arg4; \
2563 _argvec[2+5] = (unsigned long)arg5; \
2564 _argvec[2+6] = (unsigned long)arg6; \
2565 _argvec[2+7] = (unsigned long)arg7; \
2566 _argvec[2+8] = (unsigned long)arg8; \
2567 _argvec[2+9] = (unsigned long)arg9; \
2568 _argvec[2+10] = (unsigned long)arg10; \
2569 _argvec[2+11] = (unsigned long)arg11; \
2570 __asm__ volatile( \
2571 "mr 11,%1\n\t" \
2572 "std 2,-16(11)\n\t" /* save tocptr */ \
2573 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2574 "addi 1,1,-144\n\t" /* expand stack frame */ \
2575 /* arg11 */ \
2576 "ld 3,88(11)\n\t" \
2577 "std 3,128(1)\n\t" \
2578 /* arg10 */ \
2579 "ld 3,80(11)\n\t" \
2580 "std 3,120(1)\n\t" \
2581 /* arg9 */ \
2582 "ld 3,72(11)\n\t" \
2583 "std 3,112(1)\n\t" \
2584 /* args1-8 */ \
2585 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2586 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2587 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2588 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2589 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2590 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2591 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2592 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2593 "ld 11, 0(11)\n\t" /* target->r11 */ \
2594 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2595 "mr 11,%1\n\t" \
2596 "mr %0,3\n\t" \
2597 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2598 "addi 1,1,144" /* restore frame */ \
2599 : /*out*/ "=r" (_res) \
2600 : /*in*/ "r" (&_argvec[2]) \
2601 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2602 ); \
2603 lval = (__typeof__(lval)) _res; \
2604 } while (0)
2605
2606#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2607 arg7,arg8,arg9,arg10,arg11,arg12) \
2608 do { \
2609 volatile OrigFn _orig = (orig); \
2610 volatile unsigned long _argvec[3+12]; \
2611 volatile unsigned long _res; \
2612 /* _argvec[0] holds current r2 across the call */ \
2613 _argvec[1] = (unsigned long)_orig.r2; \
2614 _argvec[2] = (unsigned long)_orig.nraddr; \
2615 _argvec[2+1] = (unsigned long)arg1; \
2616 _argvec[2+2] = (unsigned long)arg2; \
2617 _argvec[2+3] = (unsigned long)arg3; \
2618 _argvec[2+4] = (unsigned long)arg4; \
2619 _argvec[2+5] = (unsigned long)arg5; \
2620 _argvec[2+6] = (unsigned long)arg6; \
2621 _argvec[2+7] = (unsigned long)arg7; \
2622 _argvec[2+8] = (unsigned long)arg8; \
2623 _argvec[2+9] = (unsigned long)arg9; \
2624 _argvec[2+10] = (unsigned long)arg10; \
2625 _argvec[2+11] = (unsigned long)arg11; \
2626 _argvec[2+12] = (unsigned long)arg12; \
2627 __asm__ volatile( \
2628 "mr 11,%1\n\t" \
2629 "std 2,-16(11)\n\t" /* save tocptr */ \
2630 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2631 "addi 1,1,-144\n\t" /* expand stack frame */ \
2632 /* arg12 */ \
2633 "ld 3,96(11)\n\t" \
2634 "std 3,136(1)\n\t" \
2635 /* arg11 */ \
2636 "ld 3,88(11)\n\t" \
2637 "std 3,128(1)\n\t" \
2638 /* arg10 */ \
2639 "ld 3,80(11)\n\t" \
2640 "std 3,120(1)\n\t" \
2641 /* arg9 */ \
2642 "ld 3,72(11)\n\t" \
2643 "std 3,112(1)\n\t" \
2644 /* args1-8 */ \
2645 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2646 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2647 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2648 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2649 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2650 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2651 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2652 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2653 "ld 11, 0(11)\n\t" /* target->r11 */ \
2654 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2655 "mr 11,%1\n\t" \
2656 "mr %0,3\n\t" \
2657 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2658 "addi 1,1,144" /* restore frame */ \
2659 : /*out*/ "=r" (_res) \
2660 : /*in*/ "r" (&_argvec[2]) \
2661 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2662 ); \
2663 lval = (__typeof__(lval)) _res; \
2664 } while (0)
2665
sewardjf5c1a7f2006-10-17 01:32:48 +00002666#endif /* PLAT_ppc64_linux */
2667
sewardj59570ff2010-01-01 11:59:33 +00002668/* ------------------------- arm-linux ------------------------- */
2669
2670#if defined(PLAT_arm_linux)
2671
2672/* These regs are trashed by the hidden call. */
2673#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2674
2675/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2676 long) == 4. */
2677
2678#define CALL_FN_W_v(lval, orig) \
2679 do { \
2680 volatile OrigFn _orig = (orig); \
2681 volatile unsigned long _argvec[1]; \
2682 volatile unsigned long _res; \
2683 _argvec[0] = (unsigned long)_orig.nraddr; \
2684 __asm__ volatile( \
2685 "ldr r4, [%1] \n\t" /* target->r4 */ \
2686 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2687 "mov %0, r0\n" \
2688 : /*out*/ "=r" (_res) \
2689 : /*in*/ "0" (&_argvec[0]) \
2690 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2691 ); \
2692 lval = (__typeof__(lval)) _res; \
2693 } while (0)
2694
2695#define CALL_FN_W_W(lval, orig, arg1) \
2696 do { \
2697 volatile OrigFn _orig = (orig); \
2698 volatile unsigned long _argvec[2]; \
2699 volatile unsigned long _res; \
2700 _argvec[0] = (unsigned long)_orig.nraddr; \
2701 _argvec[1] = (unsigned long)(arg1); \
2702 __asm__ volatile( \
2703 "ldr r0, [%1, #4] \n\t" \
2704 "ldr r4, [%1] \n\t" /* target->r4 */ \
2705 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2706 "mov %0, r0\n" \
2707 : /*out*/ "=r" (_res) \
2708 : /*in*/ "0" (&_argvec[0]) \
2709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2710 ); \
2711 lval = (__typeof__(lval)) _res; \
2712 } while (0)
2713
2714#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2715 do { \
2716 volatile OrigFn _orig = (orig); \
2717 volatile unsigned long _argvec[3]; \
2718 volatile unsigned long _res; \
2719 _argvec[0] = (unsigned long)_orig.nraddr; \
2720 _argvec[1] = (unsigned long)(arg1); \
2721 _argvec[2] = (unsigned long)(arg2); \
2722 __asm__ volatile( \
2723 "ldr r0, [%1, #4] \n\t" \
2724 "ldr r1, [%1, #8] \n\t" \
2725 "ldr r4, [%1] \n\t" /* target->r4 */ \
2726 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2727 "mov %0, r0\n" \
2728 : /*out*/ "=r" (_res) \
2729 : /*in*/ "0" (&_argvec[0]) \
2730 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2731 ); \
2732 lval = (__typeof__(lval)) _res; \
2733 } while (0)
2734
2735#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2736 do { \
2737 volatile OrigFn _orig = (orig); \
2738 volatile unsigned long _argvec[4]; \
2739 volatile unsigned long _res; \
2740 _argvec[0] = (unsigned long)_orig.nraddr; \
2741 _argvec[1] = (unsigned long)(arg1); \
2742 _argvec[2] = (unsigned long)(arg2); \
2743 _argvec[3] = (unsigned long)(arg3); \
2744 __asm__ volatile( \
2745 "ldr r0, [%1, #4] \n\t" \
2746 "ldr r1, [%1, #8] \n\t" \
2747 "ldr r2, [%1, #12] \n\t" \
2748 "ldr r4, [%1] \n\t" /* target->r4 */ \
2749 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2750 "mov %0, r0\n" \
2751 : /*out*/ "=r" (_res) \
2752 : /*in*/ "0" (&_argvec[0]) \
2753 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2754 ); \
2755 lval = (__typeof__(lval)) _res; \
2756 } while (0)
2757
2758#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2759 do { \
2760 volatile OrigFn _orig = (orig); \
2761 volatile unsigned long _argvec[5]; \
2762 volatile unsigned long _res; \
2763 _argvec[0] = (unsigned long)_orig.nraddr; \
2764 _argvec[1] = (unsigned long)(arg1); \
2765 _argvec[2] = (unsigned long)(arg2); \
2766 _argvec[3] = (unsigned long)(arg3); \
2767 _argvec[4] = (unsigned long)(arg4); \
2768 __asm__ volatile( \
2769 "ldr r0, [%1, #4] \n\t" \
2770 "ldr r1, [%1, #8] \n\t" \
2771 "ldr r2, [%1, #12] \n\t" \
2772 "ldr r3, [%1, #16] \n\t" \
2773 "ldr r4, [%1] \n\t" /* target->r4 */ \
2774 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2775 "mov %0, r0" \
2776 : /*out*/ "=r" (_res) \
2777 : /*in*/ "0" (&_argvec[0]) \
2778 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2779 ); \
2780 lval = (__typeof__(lval)) _res; \
2781 } while (0)
2782
2783#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2784 do { \
2785 volatile OrigFn _orig = (orig); \
2786 volatile unsigned long _argvec[6]; \
2787 volatile unsigned long _res; \
2788 _argvec[0] = (unsigned long)_orig.nraddr; \
2789 _argvec[1] = (unsigned long)(arg1); \
2790 _argvec[2] = (unsigned long)(arg2); \
2791 _argvec[3] = (unsigned long)(arg3); \
2792 _argvec[4] = (unsigned long)(arg4); \
2793 _argvec[5] = (unsigned long)(arg5); \
2794 __asm__ volatile( \
2795 "ldr r0, [%1, #20] \n\t" \
2796 "push {r0} \n\t" \
2797 "ldr r0, [%1, #4] \n\t" \
2798 "ldr r1, [%1, #8] \n\t" \
2799 "ldr r2, [%1, #12] \n\t" \
2800 "ldr r3, [%1, #16] \n\t" \
2801 "ldr r4, [%1] \n\t" /* target->r4 */ \
2802 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2803 "add sp, sp, #4 \n\t" \
2804 "mov %0, r0" \
2805 : /*out*/ "=r" (_res) \
2806 : /*in*/ "0" (&_argvec[0]) \
2807 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2808 ); \
2809 lval = (__typeof__(lval)) _res; \
2810 } while (0)
2811
2812#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2813 do { \
2814 volatile OrigFn _orig = (orig); \
2815 volatile unsigned long _argvec[7]; \
2816 volatile unsigned long _res; \
2817 _argvec[0] = (unsigned long)_orig.nraddr; \
2818 _argvec[1] = (unsigned long)(arg1); \
2819 _argvec[2] = (unsigned long)(arg2); \
2820 _argvec[3] = (unsigned long)(arg3); \
2821 _argvec[4] = (unsigned long)(arg4); \
2822 _argvec[5] = (unsigned long)(arg5); \
2823 _argvec[6] = (unsigned long)(arg6); \
2824 __asm__ volatile( \
2825 "ldr r0, [%1, #20] \n\t" \
2826 "ldr r1, [%1, #24] \n\t" \
2827 "push {r0, r1} \n\t" \
2828 "ldr r0, [%1, #4] \n\t" \
2829 "ldr r1, [%1, #8] \n\t" \
2830 "ldr r2, [%1, #12] \n\t" \
2831 "ldr r3, [%1, #16] \n\t" \
2832 "ldr r4, [%1] \n\t" /* target->r4 */ \
2833 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2834 "add sp, sp, #8 \n\t" \
2835 "mov %0, r0" \
2836 : /*out*/ "=r" (_res) \
2837 : /*in*/ "0" (&_argvec[0]) \
2838 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2839 ); \
2840 lval = (__typeof__(lval)) _res; \
2841 } while (0)
2842
2843#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2844 arg7) \
2845 do { \
2846 volatile OrigFn _orig = (orig); \
2847 volatile unsigned long _argvec[8]; \
2848 volatile unsigned long _res; \
2849 _argvec[0] = (unsigned long)_orig.nraddr; \
2850 _argvec[1] = (unsigned long)(arg1); \
2851 _argvec[2] = (unsigned long)(arg2); \
2852 _argvec[3] = (unsigned long)(arg3); \
2853 _argvec[4] = (unsigned long)(arg4); \
2854 _argvec[5] = (unsigned long)(arg5); \
2855 _argvec[6] = (unsigned long)(arg6); \
2856 _argvec[7] = (unsigned long)(arg7); \
2857 __asm__ volatile( \
2858 "ldr r0, [%1, #20] \n\t" \
2859 "ldr r1, [%1, #24] \n\t" \
2860 "ldr r2, [%1, #28] \n\t" \
2861 "push {r0, r1, r2} \n\t" \
2862 "ldr r0, [%1, #4] \n\t" \
2863 "ldr r1, [%1, #8] \n\t" \
2864 "ldr r2, [%1, #12] \n\t" \
2865 "ldr r3, [%1, #16] \n\t" \
2866 "ldr r4, [%1] \n\t" /* target->r4 */ \
2867 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2868 "add sp, sp, #12 \n\t" \
2869 "mov %0, r0" \
2870 : /*out*/ "=r" (_res) \
2871 : /*in*/ "0" (&_argvec[0]) \
2872 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2873 ); \
2874 lval = (__typeof__(lval)) _res; \
2875 } while (0)
2876
2877#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2878 arg7,arg8) \
2879 do { \
2880 volatile OrigFn _orig = (orig); \
2881 volatile unsigned long _argvec[9]; \
2882 volatile unsigned long _res; \
2883 _argvec[0] = (unsigned long)_orig.nraddr; \
2884 _argvec[1] = (unsigned long)(arg1); \
2885 _argvec[2] = (unsigned long)(arg2); \
2886 _argvec[3] = (unsigned long)(arg3); \
2887 _argvec[4] = (unsigned long)(arg4); \
2888 _argvec[5] = (unsigned long)(arg5); \
2889 _argvec[6] = (unsigned long)(arg6); \
2890 _argvec[7] = (unsigned long)(arg7); \
2891 _argvec[8] = (unsigned long)(arg8); \
2892 __asm__ volatile( \
2893 "ldr r0, [%1, #20] \n\t" \
2894 "ldr r1, [%1, #24] \n\t" \
2895 "ldr r2, [%1, #28] \n\t" \
2896 "ldr r3, [%1, #32] \n\t" \
2897 "push {r0, r1, r2, r3} \n\t" \
2898 "ldr r0, [%1, #4] \n\t" \
2899 "ldr r1, [%1, #8] \n\t" \
2900 "ldr r2, [%1, #12] \n\t" \
2901 "ldr r3, [%1, #16] \n\t" \
2902 "ldr r4, [%1] \n\t" /* target->r4 */ \
2903 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2904 "add sp, sp, #16 \n\t" \
2905 "mov %0, r0" \
2906 : /*out*/ "=r" (_res) \
2907 : /*in*/ "0" (&_argvec[0]) \
2908 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2909 ); \
2910 lval = (__typeof__(lval)) _res; \
2911 } while (0)
2912
2913#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2914 arg7,arg8,arg9) \
2915 do { \
2916 volatile OrigFn _orig = (orig); \
2917 volatile unsigned long _argvec[10]; \
2918 volatile unsigned long _res; \
2919 _argvec[0] = (unsigned long)_orig.nraddr; \
2920 _argvec[1] = (unsigned long)(arg1); \
2921 _argvec[2] = (unsigned long)(arg2); \
2922 _argvec[3] = (unsigned long)(arg3); \
2923 _argvec[4] = (unsigned long)(arg4); \
2924 _argvec[5] = (unsigned long)(arg5); \
2925 _argvec[6] = (unsigned long)(arg6); \
2926 _argvec[7] = (unsigned long)(arg7); \
2927 _argvec[8] = (unsigned long)(arg8); \
2928 _argvec[9] = (unsigned long)(arg9); \
2929 __asm__ volatile( \
2930 "ldr r0, [%1, #20] \n\t" \
2931 "ldr r1, [%1, #24] \n\t" \
2932 "ldr r2, [%1, #28] \n\t" \
2933 "ldr r3, [%1, #32] \n\t" \
2934 "ldr r4, [%1, #36] \n\t" \
2935 "push {r0, r1, r2, r3, r4} \n\t" \
2936 "ldr r0, [%1, #4] \n\t" \
2937 "ldr r1, [%1, #8] \n\t" \
2938 "ldr r2, [%1, #12] \n\t" \
2939 "ldr r3, [%1, #16] \n\t" \
2940 "ldr r4, [%1] \n\t" /* target->r4 */ \
2941 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2942 "add sp, sp, #20 \n\t" \
2943 "mov %0, r0" \
2944 : /*out*/ "=r" (_res) \
2945 : /*in*/ "0" (&_argvec[0]) \
2946 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2947 ); \
2948 lval = (__typeof__(lval)) _res; \
2949 } while (0)
2950
2951#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2952 arg7,arg8,arg9,arg10) \
2953 do { \
2954 volatile OrigFn _orig = (orig); \
2955 volatile unsigned long _argvec[11]; \
2956 volatile unsigned long _res; \
2957 _argvec[0] = (unsigned long)_orig.nraddr; \
2958 _argvec[1] = (unsigned long)(arg1); \
2959 _argvec[2] = (unsigned long)(arg2); \
2960 _argvec[3] = (unsigned long)(arg3); \
2961 _argvec[4] = (unsigned long)(arg4); \
2962 _argvec[5] = (unsigned long)(arg5); \
2963 _argvec[6] = (unsigned long)(arg6); \
2964 _argvec[7] = (unsigned long)(arg7); \
2965 _argvec[8] = (unsigned long)(arg8); \
2966 _argvec[9] = (unsigned long)(arg9); \
2967 _argvec[10] = (unsigned long)(arg10); \
2968 __asm__ volatile( \
2969 "ldr r0, [%1, #40] \n\t" \
2970 "push {r0} \n\t" \
2971 "ldr r0, [%1, #20] \n\t" \
2972 "ldr r1, [%1, #24] \n\t" \
2973 "ldr r2, [%1, #28] \n\t" \
2974 "ldr r3, [%1, #32] \n\t" \
2975 "ldr r4, [%1, #36] \n\t" \
2976 "push {r0, r1, r2, r3, r4} \n\t" \
2977 "ldr r0, [%1, #4] \n\t" \
2978 "ldr r1, [%1, #8] \n\t" \
2979 "ldr r2, [%1, #12] \n\t" \
2980 "ldr r3, [%1, #16] \n\t" \
2981 "ldr r4, [%1] \n\t" /* target->r4 */ \
2982 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2983 "add sp, sp, #24 \n\t" \
2984 "mov %0, r0" \
2985 : /*out*/ "=r" (_res) \
2986 : /*in*/ "0" (&_argvec[0]) \
2987 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2988 ); \
2989 lval = (__typeof__(lval)) _res; \
2990 } while (0)
2991
2992#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2993 arg6,arg7,arg8,arg9,arg10, \
2994 arg11) \
2995 do { \
2996 volatile OrigFn _orig = (orig); \
2997 volatile unsigned long _argvec[12]; \
2998 volatile unsigned long _res; \
2999 _argvec[0] = (unsigned long)_orig.nraddr; \
3000 _argvec[1] = (unsigned long)(arg1); \
3001 _argvec[2] = (unsigned long)(arg2); \
3002 _argvec[3] = (unsigned long)(arg3); \
3003 _argvec[4] = (unsigned long)(arg4); \
3004 _argvec[5] = (unsigned long)(arg5); \
3005 _argvec[6] = (unsigned long)(arg6); \
3006 _argvec[7] = (unsigned long)(arg7); \
3007 _argvec[8] = (unsigned long)(arg8); \
3008 _argvec[9] = (unsigned long)(arg9); \
3009 _argvec[10] = (unsigned long)(arg10); \
3010 _argvec[11] = (unsigned long)(arg11); \
3011 __asm__ volatile( \
3012 "ldr r0, [%1, #40] \n\t" \
3013 "ldr r1, [%1, #44] \n\t" \
3014 "push {r0, r1} \n\t" \
3015 "ldr r0, [%1, #20] \n\t" \
3016 "ldr r1, [%1, #24] \n\t" \
3017 "ldr r2, [%1, #28] \n\t" \
3018 "ldr r3, [%1, #32] \n\t" \
3019 "ldr r4, [%1, #36] \n\t" \
3020 "push {r0, r1, r2, r3, r4} \n\t" \
3021 "ldr r0, [%1, #4] \n\t" \
3022 "ldr r1, [%1, #8] \n\t" \
3023 "ldr r2, [%1, #12] \n\t" \
3024 "ldr r3, [%1, #16] \n\t" \
3025 "ldr r4, [%1] \n\t" /* target->r4 */ \
3026 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3027 "add sp, sp, #28 \n\t" \
3028 "mov %0, r0" \
3029 : /*out*/ "=r" (_res) \
3030 : /*in*/ "0" (&_argvec[0]) \
3031 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3032 ); \
3033 lval = (__typeof__(lval)) _res; \
3034 } while (0)
3035
3036#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3037 arg6,arg7,arg8,arg9,arg10, \
3038 arg11,arg12) \
3039 do { \
3040 volatile OrigFn _orig = (orig); \
3041 volatile unsigned long _argvec[13]; \
3042 volatile unsigned long _res; \
3043 _argvec[0] = (unsigned long)_orig.nraddr; \
3044 _argvec[1] = (unsigned long)(arg1); \
3045 _argvec[2] = (unsigned long)(arg2); \
3046 _argvec[3] = (unsigned long)(arg3); \
3047 _argvec[4] = (unsigned long)(arg4); \
3048 _argvec[5] = (unsigned long)(arg5); \
3049 _argvec[6] = (unsigned long)(arg6); \
3050 _argvec[7] = (unsigned long)(arg7); \
3051 _argvec[8] = (unsigned long)(arg8); \
3052 _argvec[9] = (unsigned long)(arg9); \
3053 _argvec[10] = (unsigned long)(arg10); \
3054 _argvec[11] = (unsigned long)(arg11); \
3055 _argvec[12] = (unsigned long)(arg12); \
3056 __asm__ volatile( \
3057 "ldr r0, [%1, #40] \n\t" \
3058 "ldr r1, [%1, #44] \n\t" \
3059 "ldr r2, [%1, #48] \n\t" \
3060 "push {r0, r1, r2} \n\t" \
3061 "ldr r0, [%1, #20] \n\t" \
3062 "ldr r1, [%1, #24] \n\t" \
3063 "ldr r2, [%1, #28] \n\t" \
3064 "ldr r3, [%1, #32] \n\t" \
3065 "ldr r4, [%1, #36] \n\t" \
3066 "push {r0, r1, r2, r3, r4} \n\t" \
3067 "ldr r0, [%1, #4] \n\t" \
3068 "ldr r1, [%1, #8] \n\t" \
3069 "ldr r2, [%1, #12] \n\t" \
3070 "ldr r3, [%1, #16] \n\t" \
3071 "ldr r4, [%1] \n\t" /* target->r4 */ \
3072 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3073 "add sp, sp, #32 \n\t" \
3074 "mov %0, r0" \
3075 : /*out*/ "=r" (_res) \
3076 : /*in*/ "0" (&_argvec[0]) \
3077 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3078 ); \
3079 lval = (__typeof__(lval)) _res; \
3080 } while (0)
3081
3082#endif /* PLAT_arm_linux */
3083
sewardjb5b87402011-03-07 16:05:35 +00003084/* ------------------------- s390x-linux ------------------------- */
3085
3086#if defined(PLAT_s390x_linux)
3087
3088/* Similar workaround as amd64 (see above), but we use r11 as frame
3089 pointer and save the old r11 in r7. r11 might be used for
3090 argvec, therefore we copy argvec in r1 since r1 is clobbered
3091 after the call anyway. */
3092#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
3093# define __FRAME_POINTER \
3094 ,"d"(__builtin_dwarf_cfa())
3095# define VALGRIND_CFI_PROLOGUE \
3096 ".cfi_remember_state\n\t" \
3097 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
3098 "lgr 7,11\n\t" \
3099 "lgr 11,%2\n\t" \
3100 ".cfi_def_cfa r11, 0\n\t"
3101# define VALGRIND_CFI_EPILOGUE \
3102 "lgr 11, 7\n\t" \
3103 ".cfi_restore_state\n\t"
3104#else
3105# define __FRAME_POINTER
3106# define VALGRIND_CFI_PROLOGUE \
3107 "lgr 1,%1\n\t"
3108# define VALGRIND_CFI_EPILOGUE
3109#endif
3110
3111
3112
3113
3114/* These regs are trashed by the hidden call. Note that we overwrite
3115 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
3116 function a proper return address. All others are ABI defined call
3117 clobbers. */
3118#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
3119 "f0","f1","f2","f3","f4","f5","f6","f7"
3120
3121
3122#define CALL_FN_W_v(lval, orig) \
3123 do { \
3124 volatile OrigFn _orig = (orig); \
3125 volatile unsigned long _argvec[1]; \
3126 volatile unsigned long _res; \
3127 _argvec[0] = (unsigned long)_orig.nraddr; \
3128 __asm__ volatile( \
3129 VALGRIND_CFI_PROLOGUE \
3130 "aghi 15,-160\n\t" \
3131 "lg 1, 0(1)\n\t" /* target->r1 */ \
3132 VALGRIND_CALL_NOREDIR_R1 \
3133 "lgr %0, 2\n\t" \
3134 "aghi 15,160\n\t" \
3135 VALGRIND_CFI_EPILOGUE \
3136 : /*out*/ "=d" (_res) \
3137 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
3138 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3139 ); \
3140 lval = (__typeof__(lval)) _res; \
3141 } while (0)
3142
3143/* The call abi has the arguments in r2-r6 and stack */
3144#define CALL_FN_W_W(lval, orig, arg1) \
3145 do { \
3146 volatile OrigFn _orig = (orig); \
3147 volatile unsigned long _argvec[2]; \
3148 volatile unsigned long _res; \
3149 _argvec[0] = (unsigned long)_orig.nraddr; \
3150 _argvec[1] = (unsigned long)arg1; \
3151 __asm__ volatile( \
3152 VALGRIND_CFI_PROLOGUE \
3153 "aghi 15,-160\n\t" \
3154 "lg 2, 8(1)\n\t" \
3155 "lg 1, 0(1)\n\t" \
3156 VALGRIND_CALL_NOREDIR_R1 \
3157 "lgr %0, 2\n\t" \
3158 "aghi 15,160\n\t" \
3159 VALGRIND_CFI_EPILOGUE \
3160 : /*out*/ "=d" (_res) \
3161 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3162 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3163 ); \
3164 lval = (__typeof__(lval)) _res; \
3165 } while (0)
3166
3167#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
3168 do { \
3169 volatile OrigFn _orig = (orig); \
3170 volatile unsigned long _argvec[3]; \
3171 volatile unsigned long _res; \
3172 _argvec[0] = (unsigned long)_orig.nraddr; \
3173 _argvec[1] = (unsigned long)arg1; \
3174 _argvec[2] = (unsigned long)arg2; \
3175 __asm__ volatile( \
3176 VALGRIND_CFI_PROLOGUE \
3177 "aghi 15,-160\n\t" \
3178 "lg 2, 8(1)\n\t" \
3179 "lg 3,16(1)\n\t" \
3180 "lg 1, 0(1)\n\t" \
3181 VALGRIND_CALL_NOREDIR_R1 \
3182 "lgr %0, 2\n\t" \
3183 "aghi 15,160\n\t" \
3184 VALGRIND_CFI_EPILOGUE \
3185 : /*out*/ "=d" (_res) \
3186 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3187 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3188 ); \
3189 lval = (__typeof__(lval)) _res; \
3190 } while (0)
3191
3192#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
3193 do { \
3194 volatile OrigFn _orig = (orig); \
3195 volatile unsigned long _argvec[4]; \
3196 volatile unsigned long _res; \
3197 _argvec[0] = (unsigned long)_orig.nraddr; \
3198 _argvec[1] = (unsigned long)arg1; \
3199 _argvec[2] = (unsigned long)arg2; \
3200 _argvec[3] = (unsigned long)arg3; \
3201 __asm__ volatile( \
3202 VALGRIND_CFI_PROLOGUE \
3203 "aghi 15,-160\n\t" \
3204 "lg 2, 8(1)\n\t" \
3205 "lg 3,16(1)\n\t" \
3206 "lg 4,24(1)\n\t" \
3207 "lg 1, 0(1)\n\t" \
3208 VALGRIND_CALL_NOREDIR_R1 \
3209 "lgr %0, 2\n\t" \
3210 "aghi 15,160\n\t" \
3211 VALGRIND_CFI_EPILOGUE \
3212 : /*out*/ "=d" (_res) \
3213 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3214 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3215 ); \
3216 lval = (__typeof__(lval)) _res; \
3217 } while (0)
3218
3219#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
3220 do { \
3221 volatile OrigFn _orig = (orig); \
3222 volatile unsigned long _argvec[5]; \
3223 volatile unsigned long _res; \
3224 _argvec[0] = (unsigned long)_orig.nraddr; \
3225 _argvec[1] = (unsigned long)arg1; \
3226 _argvec[2] = (unsigned long)arg2; \
3227 _argvec[3] = (unsigned long)arg3; \
3228 _argvec[4] = (unsigned long)arg4; \
3229 __asm__ volatile( \
3230 VALGRIND_CFI_PROLOGUE \
3231 "aghi 15,-160\n\t" \
3232 "lg 2, 8(1)\n\t" \
3233 "lg 3,16(1)\n\t" \
3234 "lg 4,24(1)\n\t" \
3235 "lg 5,32(1)\n\t" \
3236 "lg 1, 0(1)\n\t" \
3237 VALGRIND_CALL_NOREDIR_R1 \
3238 "lgr %0, 2\n\t" \
3239 "aghi 15,160\n\t" \
3240 VALGRIND_CFI_EPILOGUE \
3241 : /*out*/ "=d" (_res) \
3242 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3243 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3244 ); \
3245 lval = (__typeof__(lval)) _res; \
3246 } while (0)
3247
3248#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
3249 do { \
3250 volatile OrigFn _orig = (orig); \
3251 volatile unsigned long _argvec[6]; \
3252 volatile unsigned long _res; \
3253 _argvec[0] = (unsigned long)_orig.nraddr; \
3254 _argvec[1] = (unsigned long)arg1; \
3255 _argvec[2] = (unsigned long)arg2; \
3256 _argvec[3] = (unsigned long)arg3; \
3257 _argvec[4] = (unsigned long)arg4; \
3258 _argvec[5] = (unsigned long)arg5; \
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 6,40(1)\n\t" \
3267 "lg 1, 0(1)\n\t" \
3268 VALGRIND_CALL_NOREDIR_R1 \
3269 "lgr %0, 2\n\t" \
3270 "aghi 15,160\n\t" \
3271 VALGRIND_CFI_EPILOGUE \
3272 : /*out*/ "=d" (_res) \
3273 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3274 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3275 ); \
3276 lval = (__typeof__(lval)) _res; \
3277 } while (0)
3278
3279#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3280 arg6) \
3281 do { \
3282 volatile OrigFn _orig = (orig); \
3283 volatile unsigned long _argvec[7]; \
3284 volatile unsigned long _res; \
3285 _argvec[0] = (unsigned long)_orig.nraddr; \
3286 _argvec[1] = (unsigned long)arg1; \
3287 _argvec[2] = (unsigned long)arg2; \
3288 _argvec[3] = (unsigned long)arg3; \
3289 _argvec[4] = (unsigned long)arg4; \
3290 _argvec[5] = (unsigned long)arg5; \
3291 _argvec[6] = (unsigned long)arg6; \
3292 __asm__ volatile( \
3293 VALGRIND_CFI_PROLOGUE \
3294 "aghi 15,-168\n\t" \
3295 "lg 2, 8(1)\n\t" \
3296 "lg 3,16(1)\n\t" \
3297 "lg 4,24(1)\n\t" \
3298 "lg 5,32(1)\n\t" \
3299 "lg 6,40(1)\n\t" \
3300 "mvc 160(8,15), 48(1)\n\t" \
3301 "lg 1, 0(1)\n\t" \
3302 VALGRIND_CALL_NOREDIR_R1 \
3303 "lgr %0, 2\n\t" \
3304 "aghi 15,168\n\t" \
3305 VALGRIND_CFI_EPILOGUE \
3306 : /*out*/ "=d" (_res) \
3307 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3308 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3309 ); \
3310 lval = (__typeof__(lval)) _res; \
3311 } while (0)
3312
3313#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3314 arg6, arg7) \
3315 do { \
3316 volatile OrigFn _orig = (orig); \
3317 volatile unsigned long _argvec[8]; \
3318 volatile unsigned long _res; \
3319 _argvec[0] = (unsigned long)_orig.nraddr; \
3320 _argvec[1] = (unsigned long)arg1; \
3321 _argvec[2] = (unsigned long)arg2; \
3322 _argvec[3] = (unsigned long)arg3; \
3323 _argvec[4] = (unsigned long)arg4; \
3324 _argvec[5] = (unsigned long)arg5; \
3325 _argvec[6] = (unsigned long)arg6; \
3326 _argvec[7] = (unsigned long)arg7; \
3327 __asm__ volatile( \
3328 VALGRIND_CFI_PROLOGUE \
3329 "aghi 15,-176\n\t" \
3330 "lg 2, 8(1)\n\t" \
3331 "lg 3,16(1)\n\t" \
3332 "lg 4,24(1)\n\t" \
3333 "lg 5,32(1)\n\t" \
3334 "lg 6,40(1)\n\t" \
3335 "mvc 160(8,15), 48(1)\n\t" \
3336 "mvc 168(8,15), 56(1)\n\t" \
3337 "lg 1, 0(1)\n\t" \
3338 VALGRIND_CALL_NOREDIR_R1 \
3339 "lgr %0, 2\n\t" \
3340 "aghi 15,176\n\t" \
3341 VALGRIND_CFI_EPILOGUE \
3342 : /*out*/ "=d" (_res) \
3343 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3344 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3345 ); \
3346 lval = (__typeof__(lval)) _res; \
3347 } while (0)
3348
3349#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3350 arg6, arg7 ,arg8) \
3351 do { \
3352 volatile OrigFn _orig = (orig); \
3353 volatile unsigned long _argvec[9]; \
3354 volatile unsigned long _res; \
3355 _argvec[0] = (unsigned long)_orig.nraddr; \
3356 _argvec[1] = (unsigned long)arg1; \
3357 _argvec[2] = (unsigned long)arg2; \
3358 _argvec[3] = (unsigned long)arg3; \
3359 _argvec[4] = (unsigned long)arg4; \
3360 _argvec[5] = (unsigned long)arg5; \
3361 _argvec[6] = (unsigned long)arg6; \
3362 _argvec[7] = (unsigned long)arg7; \
3363 _argvec[8] = (unsigned long)arg8; \
3364 __asm__ volatile( \
3365 VALGRIND_CFI_PROLOGUE \
3366 "aghi 15,-184\n\t" \
3367 "lg 2, 8(1)\n\t" \
3368 "lg 3,16(1)\n\t" \
3369 "lg 4,24(1)\n\t" \
3370 "lg 5,32(1)\n\t" \
3371 "lg 6,40(1)\n\t" \
3372 "mvc 160(8,15), 48(1)\n\t" \
3373 "mvc 168(8,15), 56(1)\n\t" \
3374 "mvc 176(8,15), 64(1)\n\t" \
3375 "lg 1, 0(1)\n\t" \
3376 VALGRIND_CALL_NOREDIR_R1 \
3377 "lgr %0, 2\n\t" \
3378 "aghi 15,184\n\t" \
3379 VALGRIND_CFI_EPILOGUE \
3380 : /*out*/ "=d" (_res) \
3381 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3382 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3383 ); \
3384 lval = (__typeof__(lval)) _res; \
3385 } while (0)
3386
3387#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3388 arg6, arg7 ,arg8, arg9) \
3389 do { \
3390 volatile OrigFn _orig = (orig); \
3391 volatile unsigned long _argvec[10]; \
3392 volatile unsigned long _res; \
3393 _argvec[0] = (unsigned long)_orig.nraddr; \
3394 _argvec[1] = (unsigned long)arg1; \
3395 _argvec[2] = (unsigned long)arg2; \
3396 _argvec[3] = (unsigned long)arg3; \
3397 _argvec[4] = (unsigned long)arg4; \
3398 _argvec[5] = (unsigned long)arg5; \
3399 _argvec[6] = (unsigned long)arg6; \
3400 _argvec[7] = (unsigned long)arg7; \
3401 _argvec[8] = (unsigned long)arg8; \
3402 _argvec[9] = (unsigned long)arg9; \
3403 __asm__ volatile( \
3404 VALGRIND_CFI_PROLOGUE \
3405 "aghi 15,-192\n\t" \
3406 "lg 2, 8(1)\n\t" \
3407 "lg 3,16(1)\n\t" \
3408 "lg 4,24(1)\n\t" \
3409 "lg 5,32(1)\n\t" \
3410 "lg 6,40(1)\n\t" \
3411 "mvc 160(8,15), 48(1)\n\t" \
3412 "mvc 168(8,15), 56(1)\n\t" \
3413 "mvc 176(8,15), 64(1)\n\t" \
3414 "mvc 184(8,15), 72(1)\n\t" \
3415 "lg 1, 0(1)\n\t" \
3416 VALGRIND_CALL_NOREDIR_R1 \
3417 "lgr %0, 2\n\t" \
3418 "aghi 15,192\n\t" \
3419 VALGRIND_CFI_EPILOGUE \
3420 : /*out*/ "=d" (_res) \
3421 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3422 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3423 ); \
3424 lval = (__typeof__(lval)) _res; \
3425 } while (0)
3426
3427#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3428 arg6, arg7 ,arg8, arg9, arg10) \
3429 do { \
3430 volatile OrigFn _orig = (orig); \
3431 volatile unsigned long _argvec[11]; \
3432 volatile unsigned long _res; \
3433 _argvec[0] = (unsigned long)_orig.nraddr; \
3434 _argvec[1] = (unsigned long)arg1; \
3435 _argvec[2] = (unsigned long)arg2; \
3436 _argvec[3] = (unsigned long)arg3; \
3437 _argvec[4] = (unsigned long)arg4; \
3438 _argvec[5] = (unsigned long)arg5; \
3439 _argvec[6] = (unsigned long)arg6; \
3440 _argvec[7] = (unsigned long)arg7; \
3441 _argvec[8] = (unsigned long)arg8; \
3442 _argvec[9] = (unsigned long)arg9; \
3443 _argvec[10] = (unsigned long)arg10; \
3444 __asm__ volatile( \
3445 VALGRIND_CFI_PROLOGUE \
3446 "aghi 15,-200\n\t" \
3447 "lg 2, 8(1)\n\t" \
3448 "lg 3,16(1)\n\t" \
3449 "lg 4,24(1)\n\t" \
3450 "lg 5,32(1)\n\t" \
3451 "lg 6,40(1)\n\t" \
3452 "mvc 160(8,15), 48(1)\n\t" \
3453 "mvc 168(8,15), 56(1)\n\t" \
3454 "mvc 176(8,15), 64(1)\n\t" \
3455 "mvc 184(8,15), 72(1)\n\t" \
3456 "mvc 192(8,15), 80(1)\n\t" \
3457 "lg 1, 0(1)\n\t" \
3458 VALGRIND_CALL_NOREDIR_R1 \
3459 "lgr %0, 2\n\t" \
3460 "aghi 15,200\n\t" \
3461 VALGRIND_CFI_EPILOGUE \
3462 : /*out*/ "=d" (_res) \
3463 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3464 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3465 ); \
3466 lval = (__typeof__(lval)) _res; \
3467 } while (0)
3468
3469#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3470 arg6, arg7 ,arg8, arg9, arg10, arg11) \
3471 do { \
3472 volatile OrigFn _orig = (orig); \
3473 volatile unsigned long _argvec[12]; \
3474 volatile unsigned long _res; \
3475 _argvec[0] = (unsigned long)_orig.nraddr; \
3476 _argvec[1] = (unsigned long)arg1; \
3477 _argvec[2] = (unsigned long)arg2; \
3478 _argvec[3] = (unsigned long)arg3; \
3479 _argvec[4] = (unsigned long)arg4; \
3480 _argvec[5] = (unsigned long)arg5; \
3481 _argvec[6] = (unsigned long)arg6; \
3482 _argvec[7] = (unsigned long)arg7; \
3483 _argvec[8] = (unsigned long)arg8; \
3484 _argvec[9] = (unsigned long)arg9; \
3485 _argvec[10] = (unsigned long)arg10; \
3486 _argvec[11] = (unsigned long)arg11; \
3487 __asm__ volatile( \
3488 VALGRIND_CFI_PROLOGUE \
3489 "aghi 15,-208\n\t" \
3490 "lg 2, 8(1)\n\t" \
3491 "lg 3,16(1)\n\t" \
3492 "lg 4,24(1)\n\t" \
3493 "lg 5,32(1)\n\t" \
3494 "lg 6,40(1)\n\t" \
3495 "mvc 160(8,15), 48(1)\n\t" \
3496 "mvc 168(8,15), 56(1)\n\t" \
3497 "mvc 176(8,15), 64(1)\n\t" \
3498 "mvc 184(8,15), 72(1)\n\t" \
3499 "mvc 192(8,15), 80(1)\n\t" \
3500 "mvc 200(8,15), 88(1)\n\t" \
3501 "lg 1, 0(1)\n\t" \
3502 VALGRIND_CALL_NOREDIR_R1 \
3503 "lgr %0, 2\n\t" \
3504 "aghi 15,208\n\t" \
3505 VALGRIND_CFI_EPILOGUE \
3506 : /*out*/ "=d" (_res) \
3507 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3508 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3509 ); \
3510 lval = (__typeof__(lval)) _res; \
3511 } while (0)
3512
3513#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3514 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
3515 do { \
3516 volatile OrigFn _orig = (orig); \
3517 volatile unsigned long _argvec[13]; \
3518 volatile unsigned long _res; \
3519 _argvec[0] = (unsigned long)_orig.nraddr; \
3520 _argvec[1] = (unsigned long)arg1; \
3521 _argvec[2] = (unsigned long)arg2; \
3522 _argvec[3] = (unsigned long)arg3; \
3523 _argvec[4] = (unsigned long)arg4; \
3524 _argvec[5] = (unsigned long)arg5; \
3525 _argvec[6] = (unsigned long)arg6; \
3526 _argvec[7] = (unsigned long)arg7; \
3527 _argvec[8] = (unsigned long)arg8; \
3528 _argvec[9] = (unsigned long)arg9; \
3529 _argvec[10] = (unsigned long)arg10; \
3530 _argvec[11] = (unsigned long)arg11; \
3531 _argvec[12] = (unsigned long)arg12; \
3532 __asm__ volatile( \
3533 VALGRIND_CFI_PROLOGUE \
3534 "aghi 15,-216\n\t" \
3535 "lg 2, 8(1)\n\t" \
3536 "lg 3,16(1)\n\t" \
3537 "lg 4,24(1)\n\t" \
3538 "lg 5,32(1)\n\t" \
3539 "lg 6,40(1)\n\t" \
3540 "mvc 160(8,15), 48(1)\n\t" \
3541 "mvc 168(8,15), 56(1)\n\t" \
3542 "mvc 176(8,15), 64(1)\n\t" \
3543 "mvc 184(8,15), 72(1)\n\t" \
3544 "mvc 192(8,15), 80(1)\n\t" \
3545 "mvc 200(8,15), 88(1)\n\t" \
3546 "mvc 208(8,15), 96(1)\n\t" \
3547 "lg 1, 0(1)\n\t" \
3548 VALGRIND_CALL_NOREDIR_R1 \
3549 "lgr %0, 2\n\t" \
3550 "aghi 15,216\n\t" \
3551 VALGRIND_CFI_EPILOGUE \
3552 : /*out*/ "=d" (_res) \
3553 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3554 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3555 ); \
3556 lval = (__typeof__(lval)) _res; \
3557 } while (0)
3558
3559
3560#endif /* PLAT_s390x_linux */
3561
sewardj0ec07f32006-01-12 12:32:32 +00003562
3563/* ------------------------------------------------------------------ */
3564/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
3565/* */
njn30d76c62005-06-18 15:07:39 +00003566/* ------------------------------------------------------------------ */
3567
sewardj2e93c502002-04-12 11:12:52 +00003568/* Some request codes. There are many more of these, but most are not
3569 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00003570 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00003571
sewardj0ec07f32006-01-12 12:32:32 +00003572 Core ones are in the range 0x00000000--0x0000ffff. The non-public
3573 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00003574*/
3575
sewardj0ec07f32006-01-12 12:32:32 +00003576/* These macros are used by tools -- they must be public, but don't
3577 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00003578#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00003579 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00003580#define VG_IS_TOOL_USERREQ(a, b, v) \
3581 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00003582
sewardj5ce4b152006-03-11 12:57:41 +00003583/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3584 This enum comprises an ABI exported by Valgrind to programs
3585 which use client requests. DO NOT CHANGE THE ORDER OF THESE
3586 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00003587typedef
njn4c791212003-05-02 17:53:54 +00003588 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
3589 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00003590
sewardj0ec07f32006-01-12 12:32:32 +00003591 /* These allow any function to be called from the simulated
3592 CPU but run on the real CPU. Nb: the first arg passed to
3593 the function is always the ThreadId of the running
3594 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00003595 function, etc. */
njn4c791212003-05-02 17:53:54 +00003596 VG_USERREQ__CLIENT_CALL0 = 0x1101,
3597 VG_USERREQ__CLIENT_CALL1 = 0x1102,
3598 VG_USERREQ__CLIENT_CALL2 = 0x1103,
3599 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00003600
sewardj0ec07f32006-01-12 12:32:32 +00003601 /* Can be useful in regression testing suites -- eg. can
3602 send Valgrind's output to /dev/null and still count
3603 errors. */
njn4c791212003-05-02 17:53:54 +00003604 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00003605
sewardj3b290482011-05-06 21:02:55 +00003606 /* Allows a string (gdb monitor command) to be passed to the tool
3607 Used for interaction with vgdb/gdb */
3608 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
3609
sewardj0ec07f32006-01-12 12:32:32 +00003610 /* These are useful and can be interpreted by any tool that
3611 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00003612 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00003613 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00003614 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00003615 /* Memory pool support. */
3616 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
3617 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
3618 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
3619 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00003620 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00003621 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
3622 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
3623 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00003624
fitzhardinge39de4b42003-10-31 07:12:21 +00003625 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00003626 /* The first two pass the va_list argument by value, which
3627 assumes it is the same size as or smaller than a UWord,
3628 which generally isn't the case. Hence are deprecated.
3629 The second two pass the vargs by reference and so are
3630 immune to this problem. */
3631 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00003632 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00003633 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00003634 /* both :: char* fmt, va_list* vargs */
3635 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
3636 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00003637
3638 /* Stack support. */
3639 VG_USERREQ__STACK_REGISTER = 0x1501,
3640 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00003641 VG_USERREQ__STACK_CHANGE = 0x1503,
3642
3643 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00003644 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
3645
3646 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00003647 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
3648
3649 /* Disable/enable error reporting level. Takes a single
3650 Word arg which is the delta to this thread's error
3651 disablement indicator. Hence 1 disables or further
3652 disables errors, and -1 moves back towards enablement.
3653 Other values are not allowed. */
3654 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801
njn25e49d8e72002-09-23 09:36:25 +00003655 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00003656
sewardj0ec07f32006-01-12 12:32:32 +00003657#if !defined(__GNUC__)
3658# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00003659#endif
sewardj2e93c502002-04-12 11:12:52 +00003660
bartfa5115a2010-09-02 09:33:02 +00003661
sewardj0ec07f32006-01-12 12:32:32 +00003662/* Returns the number of Valgrinds this code is running under. That
3663 is, 0 if running natively, 1 if running under Valgrind, 2 if
3664 running under Valgrind which is running under another Valgrind,
3665 etc. */
bartfa5115a2010-09-02 09:33:02 +00003666#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00003667 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00003668 VG_USERREQ__RUNNING_ON_VALGRIND, \
3669 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00003670
3671
sewardj18d75132002-05-16 11:06:21 +00003672/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3673 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
3674 since it provides a way to make sure valgrind will retranslate the
3675 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00003676#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
bart575ce8e2011-05-15 07:04:03 +00003677 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003678 VG_USERREQ__DISCARD_TRANSLATIONS, \
bart575ce8e2011-05-15 07:04:03 +00003679 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00003680
njn26aba4d2005-05-16 13:31:23 +00003681
sewardj0ec07f32006-01-12 12:32:32 +00003682/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00003683 Possibly with a backtrace. This is a really ugly hack. The return value
3684 is the number of characters printed, excluding the "**<pid>** " part at the
3685 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00003686
bart8c7e25f2011-03-04 16:55:56 +00003687#if defined(__GNUC__) || defined(__INTEL_COMPILER)
sewardj7eca0cc2006-04-12 17:15:35 +00003688/* Modern GCC will optimize the static routine out if unused,
3689 and unused attribute will shut down warnings about it. */
3690static int VALGRIND_PRINTF(const char *format, ...)
3691 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00003692#endif
sewardj7eca0cc2006-04-12 17:15:35 +00003693static int
bart0da2c772010-09-01 10:18:36 +00003694#if defined(_MSC_VER)
3695__inline
3696#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00003697VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003698{
bart8c7e25f2011-03-04 16:55:56 +00003699#if defined(NVALGRIND)
3700 return 0;
3701#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00003702#if defined(_MSC_VER)
3703 uintptr_t _qzz_res;
3704#else
njnc6168192004-11-29 13:54:10 +00003705 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00003706#endif
sewardjc560fb32010-01-28 15:23:54 +00003707 va_list vargs;
3708 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00003709#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00003710 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00003711 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00003712 (uintptr_t)format,
3713 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00003714 0, 0, 0);
3715#else
bart575ce8e2011-05-15 07:04:03 +00003716 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00003717 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00003718 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00003719 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00003720 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00003721#endif
sewardjc560fb32010-01-28 15:23:54 +00003722 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003723 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00003724#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00003725}
3726
bart8c7e25f2011-03-04 16:55:56 +00003727#if defined(__GNUC__) || defined(__INTEL_COMPILER)
sewardj7eca0cc2006-04-12 17:15:35 +00003728static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3729 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00003730#endif
sewardj7eca0cc2006-04-12 17:15:35 +00003731static int
bart0da2c772010-09-01 10:18:36 +00003732#if defined(_MSC_VER)
3733__inline
3734#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00003735VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003736{
bart8c7e25f2011-03-04 16:55:56 +00003737#if defined(NVALGRIND)
3738 return 0;
3739#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00003740#if defined(_MSC_VER)
3741 uintptr_t _qzz_res;
3742#else
njnc6168192004-11-29 13:54:10 +00003743 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00003744#endif
sewardjc560fb32010-01-28 15:23:54 +00003745 va_list vargs;
3746 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00003747#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00003748 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00003749 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00003750 (uintptr_t)format,
3751 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00003752 0, 0, 0);
3753#else
bart575ce8e2011-05-15 07:04:03 +00003754 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00003755 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00003756 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00003757 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00003758 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00003759#endif
sewardjc560fb32010-01-28 15:23:54 +00003760 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003761 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003762#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00003763}
sewardj18d75132002-05-16 11:06:21 +00003764
sewardj0ec07f32006-01-12 12:32:32 +00003765
njn3e884182003-04-15 13:03:23 +00003766/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00003767 real CPU, calling an arbitary function.
3768
3769 Note that the current ThreadId is inserted as the first argument.
3770 So this call:
3771
3772 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3773
3774 requires f to have this signature:
3775
3776 Word f(Word tid, Word arg1, Word arg2)
3777
3778 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00003779
3780 Note that these client requests are not entirely reliable. For example,
3781 if you call a function with them that subsequently calls printf(),
3782 there's a high chance Valgrind will crash. Generally, your prospects of
3783 these working are made higher if the called function does not refer to
3784 any global variables, and does not refer to any libc or other functions
3785 (printf et al). Any kind of entanglement with libc or dynamic linking is
3786 likely to have a bad outcome, for tricky reasons which we've grappled
3787 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00003788*/
sewardj0ec07f32006-01-12 12:32:32 +00003789#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00003790 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3791 VG_USERREQ__CLIENT_CALL0, \
3792 _qyy_fn, \
3793 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00003794
bart575ce8e2011-05-15 07:04:03 +00003795#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
3796 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3797 VG_USERREQ__CLIENT_CALL1, \
3798 _qyy_fn, \
3799 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00003800
bart575ce8e2011-05-15 07:04:03 +00003801#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
3802 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3803 VG_USERREQ__CLIENT_CALL2, \
3804 _qyy_fn, \
3805 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00003806
sewardj0ec07f32006-01-12 12:32:32 +00003807#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00003808 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
3809 VG_USERREQ__CLIENT_CALL3, \
3810 _qyy_fn, \
3811 _qyy_arg1, _qyy_arg2, \
3812 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00003813
3814
nethercote7cc9c232004-01-21 15:08:04 +00003815/* Counts the number of errors that have been recorded by a tool. Nb:
3816 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00003817 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00003818#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00003819 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
3820 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00003821 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00003822 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00003823
njn3ac96952009-07-09 23:35:44 +00003824/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
3825 when heap blocks are allocated in order to give accurate results. This
3826 happens automatically for the standard allocator functions such as
3827 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
3828 delete[], etc.
njnd7994182003-10-02 13:44:04 +00003829
njn3ac96952009-07-09 23:35:44 +00003830 But if your program uses a custom allocator, this doesn't automatically
3831 happen, and Valgrind will not do as well. For example, if you allocate
3832 superblocks with mmap() and then allocates chunks of the superblocks, all
3833 Valgrind's observations will be at the mmap() level and it won't know that
3834 the chunks should be considered separate entities. In Memcheck's case,
3835 that means you probably won't get heap block overrun detection (because
3836 there won't be redzones marked as unaddressable) and you definitely won't
3837 get any leak detection.
3838
3839 The following client requests allow a custom allocator to be annotated so
3840 that it can be handled accurately by Valgrind.
3841
3842 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
3843 by a malloc()-like function. For Memcheck (an illustrative case), this
3844 does two things:
3845
3846 - It records that the block has been allocated. This means any addresses
3847 within the block mentioned in error messages will be
3848 identified as belonging to the block. It also means that if the block
3849 isn't freed it will be detected by the leak checker.
3850
3851 - It marks the block as being addressable and undefined (if 'is_zeroed' is
3852 not set), or addressable and defined (if 'is_zeroed' is set). This
3853 controls how accesses to the block by the program are handled.
3854
3855 'addr' is the start of the usable block (ie. after any
3856 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
3857 can apply redzones -- these are blocks of padding at the start and end of
3858 each block. Adding redzones is recommended as it makes it much more likely
3859 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
3860 zeroed (or filled with another predictable value), as is the case for
3861 calloc().
3862
3863 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
3864 heap block -- that will be used by the client program -- is allocated.
3865 It's best to put it at the outermost level of the allocator if possible;
3866 for example, if you have a function my_alloc() which calls
3867 internal_alloc(), and the client request is put inside internal_alloc(),
3868 stack traces relating to the heap block will contain entries for both
3869 my_alloc() and internal_alloc(), which is probably not what you want.
3870
njnb965efb2009-08-10 07:36:54 +00003871 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
3872 custom blocks from within a heap block, B, that has been allocated with
3873 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
3874 -- the custom blocks will take precedence.
3875
njn3ac96952009-07-09 23:35:44 +00003876 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
3877 Memcheck, it does two things:
3878
3879 - It records that the block has been deallocated. This assumes that the
3880 block was annotated as having been allocated via
3881 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3882
3883 - It marks the block as being unaddressable.
3884
3885 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
3886 heap block is deallocated.
3887
bart91347382011-03-25 20:07:25 +00003888 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
3889 Memcheck, it does four things:
3890
3891 - It records that the size of a block has been changed. This assumes that
3892 the block was annotated as having been allocated via
3893 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
3894
3895 - If the block shrunk, it marks the freed memory as being unaddressable.
3896
3897 - If the block grew, it marks the new area as undefined and defines a red
3898 zone past the end of the new block.
3899
3900 - The V-bits of the overlap between the old and the new block are preserved.
3901
3902 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
3903 and before deallocation of the old block.
3904
3905 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00003906 allocator working well with Memcheck. More specifically, if your allocator
3907 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
3908 will be necessary to mark the memory as addressable just before the zeroing
3909 occurs, otherwise you'll get a lot of invalid write errors. For example,
3910 you'll need to do this if your allocator recycles freed blocks, but it
3911 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
3912 Alternatively, if your allocator reuses freed blocks for allocator-internal
3913 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
3914
3915 Really, what's happening is a blurring of the lines between the client
3916 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
3917 memory should be considered unaddressable to the client program, but the
3918 allocator knows more than the rest of the client program and so may be able
3919 to safely access it. Extra client requests are necessary for Valgrind to
3920 understand the distinction between the allocator and the rest of the
3921 program.
3922
njn32f8d8c2009-07-15 02:31:45 +00003923 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00003924*/
sewardj0ec07f32006-01-12 12:32:32 +00003925#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
bart575ce8e2011-05-15 07:04:03 +00003926 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003927 VG_USERREQ__MALLOCLIKE_BLOCK, \
bart575ce8e2011-05-15 07:04:03 +00003928 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00003929
njn32f8d8c2009-07-15 02:31:45 +00003930/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3931 Ignored if addr == 0.
3932*/
sewardj66304e22011-03-28 21:19:00 +00003933#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
bart575ce8e2011-05-15 07:04:03 +00003934 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj66304e22011-03-28 21:19:00 +00003935 VG_USERREQ__RESIZEINPLACE_BLOCK, \
bart575ce8e2011-05-15 07:04:03 +00003936 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00003937
3938/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
3939 Ignored if addr == 0.
3940*/
sewardj0ec07f32006-01-12 12:32:32 +00003941#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
bart575ce8e2011-05-15 07:04:03 +00003942 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003943 VG_USERREQ__FREELIKE_BLOCK, \
bart575ce8e2011-05-15 07:04:03 +00003944 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00003945
rjwalshbc0bb832004-06-19 18:12:36 +00003946/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003947#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
bart575ce8e2011-05-15 07:04:03 +00003948 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003949 VG_USERREQ__CREATE_MEMPOOL, \
bart575ce8e2011-05-15 07:04:03 +00003950 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003951
3952/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003953#define VALGRIND_DESTROY_MEMPOOL(pool) \
bart575ce8e2011-05-15 07:04:03 +00003954 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003955 VG_USERREQ__DESTROY_MEMPOOL, \
bart575ce8e2011-05-15 07:04:03 +00003956 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003957
3958/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003959#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
bart575ce8e2011-05-15 07:04:03 +00003960 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003961 VG_USERREQ__MEMPOOL_ALLOC, \
bart575ce8e2011-05-15 07:04:03 +00003962 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003963
3964/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003965#define VALGRIND_MEMPOOL_FREE(pool, addr) \
bart575ce8e2011-05-15 07:04:03 +00003966 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003967 VG_USERREQ__MEMPOOL_FREE, \
bart575ce8e2011-05-15 07:04:03 +00003968 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00003969
sewardj2c1c9df2006-07-28 00:06:37 +00003970/* Disassociate any pieces outside a particular range. */
3971#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
bart575ce8e2011-05-15 07:04:03 +00003972 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj2c1c9df2006-07-28 00:06:37 +00003973 VG_USERREQ__MEMPOOL_TRIM, \
bart575ce8e2011-05-15 07:04:03 +00003974 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00003975
sewardjc740d762006-10-05 17:59:23 +00003976/* Resize and/or move a piece associated with a memory pool. */
3977#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
bart575ce8e2011-05-15 07:04:03 +00003978 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00003979 VG_USERREQ__MOVE_MEMPOOL, \
bart575ce8e2011-05-15 07:04:03 +00003980 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00003981
3982/* Resize and/or move a piece associated with a memory pool. */
3983#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
bart575ce8e2011-05-15 07:04:03 +00003984 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00003985 VG_USERREQ__MEMPOOL_CHANGE, \
bart575ce8e2011-05-15 07:04:03 +00003986 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00003987
3988/* Return 1 if a mempool exists, else 0. */
3989#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00003990 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00003991 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00003992 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00003993
rjwalsh0140af52005-06-04 20:42:33 +00003994/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00003995#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00003996 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00003997 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00003998 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00003999
4000/* Unmark the piece of memory associated with a stack id as being a
4001 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004002#define VALGRIND_STACK_DEREGISTER(id) \
bart575ce8e2011-05-15 07:04:03 +00004003 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004004 VG_USERREQ__STACK_DEREGISTER, \
bart575ce8e2011-05-15 07:04:03 +00004005 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004006
4007/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004008#define VALGRIND_STACK_CHANGE(id, start, end) \
bart575ce8e2011-05-15 07:04:03 +00004009 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004010 VG_USERREQ__STACK_CHANGE, \
bart575ce8e2011-05-15 07:04:03 +00004011 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004012
sewardjc8259b82009-04-22 22:42:10 +00004013/* Load PDB debug info for Wine PE image_map. */
4014#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
bart575ce8e2011-05-15 07:04:03 +00004015 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc8259b82009-04-22 22:42:10 +00004016 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
bart575ce8e2011-05-15 07:04:03 +00004017 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00004018
sewardj5c659622010-08-20 18:22:07 +00004019/* Map a code address to a source file name and line number. buf64
4020 must point to a 64-byte buffer in the caller's address space. The
4021 result will be dumped in there and is guaranteed to be zero
4022 terminated. If no info is found, the first byte is set to zero. */
4023#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00004024 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00004025 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00004026 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00004027
sewardjdc873c02011-07-24 16:02:33 +00004028/* Disable error reporting for this thread. Behaves in a stack like
4029 way, so you can safely call this multiple times provided that
4030 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
4031 to re-enable reporting. The first call of this macro disables
4032 reporting. Subsequent calls have no effect except to increase the
4033 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
4034 reporting. Child threads do not inherit this setting from their
4035 parents -- they are always created with reporting enabled. */
4036#define VALGRIND_DISABLE_ERROR_REPORTING \
4037 {unsigned int _qzz_res; \
4038 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4039 VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4040 1, 0, 0, 0, 0); \
4041 }
4042
4043/* Re-enable error reporting, as per comments on
4044 VALGRIND_DISABLE_ERROR_REPORTING. */
4045#define VALGRIND_ENABLE_ERROR_REPORTING \
4046 {unsigned int _qzz_res; \
4047 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4048 VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4049 (-1), 0, 0, 0, 0); \
4050 }
4051
sewardj0ec07f32006-01-12 12:32:32 +00004052
sewardjc112c8e2011-06-24 18:26:11 +00004053#undef PLAT_x86_darwin
4054#undef PLAT_amd64_darwin
4055#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +00004056#undef PLAT_x86_linux
4057#undef PLAT_amd64_linux
4058#undef PLAT_ppc32_linux
4059#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004060#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00004061#undef PLAT_s390x_linux
sewardj0ec07f32006-01-12 12:32:32 +00004062
njn3e884182003-04-15 13:03:23 +00004063#endif /* __VALGRIND_H */