blob: afb4681dbf69f97554fec6ea646e9c5b0f074999 [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001/* -*- c -*-
njn25e49d8e72002-09-23 09:36:25 +00002 ----------------------------------------------------------------
3
4 Notice that the following BSD-style license applies to this one
njn7fd15d62006-03-31 12:05:04 +00005 file (valgrind.h) only. The rest of Valgrind is licensed under the
6 terms of the GNU General Public License, version 2, unless
7 otherwise indicated. See the COPYING file in the source
8 distribution for details.
njn25e49d8e72002-09-23 09:36:25 +00009
10 ----------------------------------------------------------------
11
njnb9c427c2004-12-01 14:14:42 +000012 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
sewardjde4a1d02002-03-22 01:27:54 +000014
sewardjec062e82011-10-23 07:32:08 +000015 Copyright (C) 2000-2011 Julian Seward. All rights reserved.
sewardjde4a1d02002-03-22 01:27:54 +000016
njn25e49d8e72002-09-23 09:36:25 +000017 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
sewardjde4a1d02002-03-22 01:27:54 +000020
njn25e49d8e72002-09-23 09:36:25 +000021 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
sewardjde4a1d02002-03-22 01:27:54 +000023
njn25e49d8e72002-09-23 09:36:25 +000024 2. The origin of this software must not be misrepresented; you must
25 not claim that you wrote the original software. If you use this
26 software in a product, an acknowledgment in the product
27 documentation would be appreciated but is not required.
sewardjde4a1d02002-03-22 01:27:54 +000028
njn25e49d8e72002-09-23 09:36:25 +000029 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
31
32 4. The name of the author may not be used to endorse or promote
33 products derived from this software without specific prior written
34 permission.
35
36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48 ----------------------------------------------------------------
49
50 Notice that the above BSD-style license applies to this one file
51 (valgrind.h) only. The entire rest of Valgrind is licensed under
52 the terms of the GNU General Public License, version 2. See the
53 COPYING file in the source distribution for details.
54
55 ----------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000056*/
57
58
njn30d76c62005-06-18 15:07:39 +000059/* This file is for inclusion into client (your!) code.
60
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
63
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
sewardj0ec07f32006-01-12 12:32:32 +000067 consumes very few (eg. 7) instructions, so the resulting performance
njn30d76c62005-06-18 15:07:39 +000068 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
72
sewardjde4a1d02002-03-22 01:27:54 +000073#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
sewardj71044162010-03-03 22:57:47 +000076
77/* ------------------------------------------------------------------ */
78/* VERSION NUMBER OF VALGRIND */
79/* ------------------------------------------------------------------ */
80
81/* Specify Valgrind's version number, so that user code can
sewardj0fe1d4c2010-04-19 08:43:26 +000082 conditionally compile based on our version number. Note that these
83 were introduced at version 3.6 and so do not exist in version 3.5
84 or earlier. The recommended way to use them to check for "version
85 X.Y or later" is (eg)
86
87#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
88 && (__VALGRIND_MAJOR__ > 3 \
89 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
90*/
91#define __VALGRIND_MAJOR__ 3
sewardj7d79e0b2012-05-21 21:57:05 +000092#define __VALGRIND_MINOR__ 8
sewardj71044162010-03-03 22:57:47 +000093
94
fitzhardinge39de4b42003-10-31 07:12:21 +000095#include <stdarg.h>
96
njn3dd0a912005-06-28 19:44:10 +000097/* Nb: this file might be included in a file compiled with -ansi. So
98 we can't use C++ style "//" comments nor the "asm" keyword (instead
99 use "__asm__"). */
100
sewardjf5c1a7f2006-10-17 01:32:48 +0000101/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +0000102 that in this file we're using the compiler's CPP symbols for
103 identifying architectures, which are different to the ones we use
104 within the rest of Valgrind. Note, __powerpc__ is active for both
105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardj59570ff2010-01-01 11:59:33 +0000106 latter (on Linux, that is).
107
108 Misc note: how to find out what's predefined in gcc by default:
109 gcc -Wp,-dM somefile.c
110*/
sewardj7af32302010-01-02 10:37:58 +0000111#undef PLAT_x86_darwin
112#undef PLAT_amd64_darwin
bart7f489812010-08-27 10:05:27 +0000113#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +0000114#undef PLAT_x86_linux
115#undef PLAT_amd64_linux
116#undef PLAT_ppc32_linux
117#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000118#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +0000119#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +0000120#undef PLAT_mips32_linux
sewardjb5b87402011-03-07 16:05:35 +0000121
sewardj0ec07f32006-01-12 12:32:32 +0000122
sewardj6e9de462011-06-28 07:25:29 +0000123#if defined(__APPLE__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000124# define PLAT_x86_darwin 1
125#elif defined(__APPLE__) && defined(__x86_64__)
126# define PLAT_amd64_darwin 1
sewardj6e9de462011-06-28 07:25:29 +0000127#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
128 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000129# define PLAT_x86_win32 1
sewardj59570ff2010-01-01 11:59:33 +0000130#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000131# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000132#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000133# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000134#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000135# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000136#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000137# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000138#elif defined(__linux__) && defined(__arm__)
139# define PLAT_arm_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000140#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
141# define PLAT_s390x_linux 1
sewardj5db15402012-06-07 09:13:21 +0000142#elif defined(__linux__) && defined(__mips__)
143# define PLAT_mips32_linux 1
njnf76d27a2009-05-28 01:53:07 +0000144#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000145/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000146 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000147# if !defined(NVALGRIND)
148# define NVALGRIND 1
149# endif
150#endif
151
152
njn30d76c62005-06-18 15:07:39 +0000153/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000154/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
155/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000156/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000157
bart575ce8e2011-05-15 07:04:03 +0000158/*
159 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
160 * request. Accepts both pointers and integers as arguments.
161 *
sewardj4b3a7422011-10-24 13:21:57 +0000162 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
163 * client request that does not return a value.
164
bart575ce8e2011-05-15 07:04:03 +0000165 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000166 * client request and whose value equals the client request result. Accepts
167 * both pointers and integers as arguments. Note that such calls are not
168 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000169 */
170
171#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
172 _zzq_request, _zzq_arg1, _zzq_arg2, \
173 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000174 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000175 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000176 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000177
sewardj4b3a7422011-10-24 13:21:57 +0000178#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
179 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
180 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
181 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
182 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
183
sewardj0ec07f32006-01-12 12:32:32 +0000184#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000185
186/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000187 from the compiled code (analogous to NDEBUG's effects on
188 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000189#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
190 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000191 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000192 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000193
sewardj0ec07f32006-01-12 12:32:32 +0000194#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000195
sewardj0ec07f32006-01-12 12:32:32 +0000196/* The following defines the magic code sequences which the JITter
197 spots and handles magically. Don't look too closely at them as
198 they will rot your brain.
199
200 The assembly code sequences for all architectures is in this one
201 file. This is because this file must be stand-alone, and we don't
202 want to have multiple files.
203
204 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
205 value gets put in the return slot, so that everything works when
206 this is executed not under Valgrind. Args are passed in a memory
207 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000208 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000209
nethercote54265442004-10-26 12:56:58 +0000210 The macro args are:
211 _zzq_rlval result lvalue
212 _zzq_default default value (result returned when running on real CPU)
213 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000214 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000215
sewardj0ec07f32006-01-12 12:32:32 +0000216 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000217 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
218 guest's NRADDR pseudo-register and whatever other information is
219 needed to safely run the call original from the wrapper: on
220 ppc64-linux, the R2 value at the divert point is also needed. This
221 information is abstracted into a user-visible type, OrigFn.
222
223 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
224 guest, but guarantees that the branch instruction will not be
225 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
226 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
227 complete inline asm, since it needs to be combined with more magic
228 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000229*/
230
njnf76d27a2009-05-28 01:53:07 +0000231/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000232
sewardj520a03a2010-10-07 10:46:15 +0000233#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000234 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000235
236typedef
237 struct {
238 unsigned int nraddr; /* where's the code? */
239 }
240 OrigFn;
241
sewardj0ec07f32006-01-12 12:32:32 +0000242#define __SPECIAL_INSTRUCTION_PREAMBLE \
243 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000244 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000245
bart575ce8e2011-05-15 07:04:03 +0000246#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
247 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000248 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000249 __extension__ \
250 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000251 volatile unsigned int _zzq_result; \
252 _zzq_args[0] = (unsigned int)(_zzq_request); \
253 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
254 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
255 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
256 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000257 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000258 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
259 /* %EDX = client_request ( %EAX ) */ \
260 "xchgl %%ebx,%%ebx" \
261 : "=d" (_zzq_result) \
262 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
263 : "cc", "memory" \
264 ); \
bart575ce8e2011-05-15 07:04:03 +0000265 _zzq_result; \
266 })
sewardj2c48c7b2005-11-29 13:05:56 +0000267
sewardjc8858442006-01-20 15:17:20 +0000268#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
269 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
270 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000271 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
272 /* %EAX = guest_NRADDR */ \
273 "xchgl %%ecx,%%ecx" \
274 : "=a" (__addr) \
275 : \
276 : "cc", "memory" \
277 ); \
sewardjc8858442006-01-20 15:17:20 +0000278 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000279 }
sewardj0ec07f32006-01-12 12:32:32 +0000280
281#define VALGRIND_CALL_NOREDIR_EAX \
282 __SPECIAL_INSTRUCTION_PREAMBLE \
283 /* call-noredir *%EAX */ \
284 "xchgl %%edx,%%edx\n\t"
sewardj60227842010-10-07 10:00:56 +0000285#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000286
287/* ------------------------- x86-Win32 ------------------------- */
288
289#if defined(PLAT_x86_win32) && !defined(__GNUC__)
290
291typedef
292 struct {
293 unsigned int nraddr; /* where's the code? */
294 }
295 OrigFn;
296
297#if defined(_MSC_VER)
298
299#define __SPECIAL_INSTRUCTION_PREAMBLE \
300 __asm rol edi, 3 __asm rol edi, 13 \
301 __asm rol edi, 29 __asm rol edi, 19
302
bart575ce8e2011-05-15 07:04:03 +0000303#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
304 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000305 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000306 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
307 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
308 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
309 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
310
311static __inline uintptr_t
312valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
313 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
314 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
315 uintptr_t _zzq_arg5)
316{
317 volatile uintptr_t _zzq_args[6];
318 volatile unsigned int _zzq_result;
319 _zzq_args[0] = (uintptr_t)(_zzq_request);
320 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
321 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
322 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
323 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
324 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
325 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
326 __SPECIAL_INSTRUCTION_PREAMBLE
327 /* %EDX = client_request ( %EAX ) */
328 __asm xchg ebx,ebx
329 __asm mov _zzq_result, edx
330 }
331 return _zzq_result;
332}
bart7f489812010-08-27 10:05:27 +0000333
334#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
335 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
336 volatile unsigned int __addr; \
337 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
338 /* %EAX = guest_NRADDR */ \
339 __asm xchg ecx,ecx \
340 __asm mov __addr, eax \
341 } \
342 _zzq_orig->nraddr = __addr; \
343 }
344
345#define VALGRIND_CALL_NOREDIR_EAX ERROR
346
347#else
348#error Unsupported compiler.
349#endif
350
351#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000352
njnf76d27a2009-05-28 01:53:07 +0000353/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000354
njnf76d27a2009-05-28 01:53:07 +0000355#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000356
357typedef
358 struct {
359 unsigned long long int nraddr; /* where's the code? */
360 }
361 OrigFn;
362
sewardj0ec07f32006-01-12 12:32:32 +0000363#define __SPECIAL_INSTRUCTION_PREAMBLE \
364 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000365 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000366
bart575ce8e2011-05-15 07:04:03 +0000367#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
368 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000369 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000370 __extension__ \
371 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000372 volatile unsigned long long int _zzq_result; \
373 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
374 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
375 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
376 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
377 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000378 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000379 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
380 /* %RDX = client_request ( %RAX ) */ \
381 "xchgq %%rbx,%%rbx" \
382 : "=d" (_zzq_result) \
383 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
384 : "cc", "memory" \
385 ); \
bart575ce8e2011-05-15 07:04:03 +0000386 _zzq_result; \
387 })
sewardj0ec07f32006-01-12 12:32:32 +0000388
sewardjc8858442006-01-20 15:17:20 +0000389#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
390 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
391 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000392 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
393 /* %RAX = guest_NRADDR */ \
394 "xchgq %%rcx,%%rcx" \
395 : "=a" (__addr) \
396 : \
397 : "cc", "memory" \
398 ); \
sewardjc8858442006-01-20 15:17:20 +0000399 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000400 }
401
402#define VALGRIND_CALL_NOREDIR_RAX \
403 __SPECIAL_INSTRUCTION_PREAMBLE \
404 /* call-noredir *%RAX */ \
405 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000406#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000407
sewardjf5c1a7f2006-10-17 01:32:48 +0000408/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000409
sewardjf5c1a7f2006-10-17 01:32:48 +0000410#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000411
412typedef
413 struct {
sewardjc8858442006-01-20 15:17:20 +0000414 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000415 }
416 OrigFn;
417
sewardj0ec07f32006-01-12 12:32:32 +0000418#define __SPECIAL_INSTRUCTION_PREAMBLE \
419 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000420 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000421
bart575ce8e2011-05-15 07:04:03 +0000422#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
423 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000424 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000425 \
bart575ce8e2011-05-15 07:04:03 +0000426 __extension__ \
427 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000428 unsigned int _zzq_result; \
429 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000430 _zzq_args[0] = (unsigned int)(_zzq_request); \
431 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
432 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
433 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
434 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000435 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000436 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000437 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
438 "mr 4,%2\n\t" /*ptr*/ \
439 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000440 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000441 "or 1,1,1\n\t" \
442 "mr %0,3" /*result*/ \
443 : "=b" (_zzq_result) \
444 : "b" (_zzq_default), "b" (_zzq_ptr) \
445 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000446 _zzq_result; \
447 })
sewardj0ec07f32006-01-12 12:32:32 +0000448
sewardjd68ac3e2006-01-20 14:31:57 +0000449#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
450 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000451 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000452 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
453 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000454 "or 2,2,2\n\t" \
455 "mr %0,3" \
456 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000457 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000458 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000459 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000460 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000461 }
462
463#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
464 __SPECIAL_INSTRUCTION_PREAMBLE \
465 /* branch-and-link-to-noredir *%R11 */ \
466 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000467#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000468
sewardjf5c1a7f2006-10-17 01:32:48 +0000469/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000470
sewardjf5c1a7f2006-10-17 01:32:48 +0000471#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000472
473typedef
474 struct {
475 unsigned long long int nraddr; /* where's the code? */
476 unsigned long long int r2; /* what tocptr do we need? */
477 }
478 OrigFn;
479
sewardj1a85f4f2006-01-12 21:15:35 +0000480#define __SPECIAL_INSTRUCTION_PREAMBLE \
481 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
482 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
483
bart575ce8e2011-05-15 07:04:03 +0000484#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
485 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000486 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000487 \
bart575ce8e2011-05-15 07:04:03 +0000488 __extension__ \
489 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000490 unsigned long long int _zzq_result; \
491 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000492 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
493 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
494 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
495 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
496 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000497 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000498 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000499 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
500 "mr 4,%2\n\t" /*ptr*/ \
501 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000502 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000503 "or 1,1,1\n\t" \
504 "mr %0,3" /*result*/ \
505 : "=b" (_zzq_result) \
506 : "b" (_zzq_default), "b" (_zzq_ptr) \
507 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000508 _zzq_result; \
509 })
sewardj1a85f4f2006-01-12 21:15:35 +0000510
sewardjd68ac3e2006-01-20 14:31:57 +0000511#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
512 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000513 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000514 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
515 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000516 "or 2,2,2\n\t" \
517 "mr %0,3" \
518 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000519 : \
sewardj8258a3a2011-10-05 07:39:07 +0000520 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000521 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000522 _zzq_orig->nraddr = __addr; \
523 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
524 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000525 "or 4,4,4\n\t" \
526 "mr %0,3" \
527 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000528 : \
sewardj8258a3a2011-10-05 07:39:07 +0000529 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000530 ); \
531 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000532 }
533
534#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
535 __SPECIAL_INSTRUCTION_PREAMBLE \
536 /* branch-and-link-to-noredir *%R11 */ \
537 "or 3,3,3\n\t"
538
sewardjf5c1a7f2006-10-17 01:32:48 +0000539#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000540
sewardj59570ff2010-01-01 11:59:33 +0000541/* ------------------------- arm-linux ------------------------- */
542
543#if defined(PLAT_arm_linux)
544
545typedef
546 struct {
547 unsigned int nraddr; /* where's the code? */
548 }
549 OrigFn;
550
551#define __SPECIAL_INSTRUCTION_PREAMBLE \
552 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
553 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
554
bart575ce8e2011-05-15 07:04:03 +0000555#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
556 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000557 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
558 \
bart575ce8e2011-05-15 07:04:03 +0000559 __extension__ \
560 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000561 volatile unsigned int _zzq_result; \
562 _zzq_args[0] = (unsigned int)(_zzq_request); \
563 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
564 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
565 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
566 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
567 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
568 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
569 "mov r4, %2\n\t" /*ptr*/ \
570 __SPECIAL_INSTRUCTION_PREAMBLE \
571 /* R3 = client_request ( R4 ) */ \
572 "orr r10, r10, r10\n\t" \
573 "mov %0, r3" /*result*/ \
574 : "=r" (_zzq_result) \
575 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
576 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000577 _zzq_result; \
578 })
sewardj59570ff2010-01-01 11:59:33 +0000579
580#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
581 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
582 unsigned int __addr; \
583 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
584 /* R3 = guest_NRADDR */ \
585 "orr r11, r11, r11\n\t" \
586 "mov %0, r3" \
587 : "=r" (__addr) \
588 : \
589 : "cc", "memory", "r3" \
590 ); \
591 _zzq_orig->nraddr = __addr; \
592 }
593
594#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
595 __SPECIAL_INSTRUCTION_PREAMBLE \
596 /* branch-and-link-to-noredir *%R4 */ \
597 "orr r12, r12, r12\n\t"
598
599#endif /* PLAT_arm_linux */
600
sewardjb5b87402011-03-07 16:05:35 +0000601/* ------------------------ s390x-linux ------------------------ */
602
603#if defined(PLAT_s390x_linux)
604
605typedef
606 struct {
607 unsigned long long int nraddr; /* where's the code? */
608 }
609 OrigFn;
610
611/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
612 * code. This detection is implemented in platform specific toIR.c
613 * (e.g. VEX/priv/guest_s390_decoder.c).
614 */
615#define __SPECIAL_INSTRUCTION_PREAMBLE \
616 "lr 15,15\n\t" \
617 "lr 1,1\n\t" \
618 "lr 2,2\n\t" \
619 "lr 3,3\n\t"
620
621#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
622#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
623#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
624
bart575ce8e2011-05-15 07:04:03 +0000625#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
626 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000627 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000628 __extension__ \
629 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000630 volatile unsigned long long int _zzq_result; \
631 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
632 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
633 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
634 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
635 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
636 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
637 __asm__ volatile(/* r2 = args */ \
638 "lgr 2,%1\n\t" \
639 /* r3 = default */ \
640 "lgr 3,%2\n\t" \
641 __SPECIAL_INSTRUCTION_PREAMBLE \
642 __CLIENT_REQUEST_CODE \
643 /* results = r3 */ \
644 "lgr %0, 3\n\t" \
645 : "=d" (_zzq_result) \
646 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
647 : "cc", "2", "3", "memory" \
648 ); \
bart575ce8e2011-05-15 07:04:03 +0000649 _zzq_result; \
650 })
sewardjb5b87402011-03-07 16:05:35 +0000651
652#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
653 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
654 volatile unsigned long long int __addr; \
655 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
656 __GET_NR_CONTEXT_CODE \
657 "lgr %0, 3\n\t" \
658 : "=a" (__addr) \
659 : \
660 : "cc", "3", "memory" \
661 ); \
662 _zzq_orig->nraddr = __addr; \
663 }
664
665#define VALGRIND_CALL_NOREDIR_R1 \
666 __SPECIAL_INSTRUCTION_PREAMBLE \
667 __CALL_NO_REDIR_CODE
668
669#endif /* PLAT_s390x_linux */
670
sewardj5db15402012-06-07 09:13:21 +0000671/* ------------------------- mips32-linux ---------------- */
672
673#if defined(PLAT_mips32_linux)
674
675typedef
676 struct {
677 unsigned int nraddr; /* where's the code? */
678 }
679 OrigFn;
680
681/* .word 0x342
682 * .word 0x742
683 * .word 0xC2
684 * .word 0x4C2*/
685#define __SPECIAL_INSTRUCTION_PREAMBLE \
686 "srl $0, $0, 13\n\t" \
687 "srl $0, $0, 29\n\t" \
688 "srl $0, $0, 3\n\t" \
689 "srl $0, $0, 19\n\t"
690
691#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
692 _zzq_default, _zzq_request, \
693 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
694 __extension__ \
695 ({ volatile unsigned int _zzq_args[6]; \
696 volatile unsigned int _zzq_result; \
697 _zzq_args[0] = (unsigned int)(_zzq_request); \
698 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
699 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
700 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
701 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
702 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
703 __asm__ volatile("move $11, %1\n\t" /*default*/ \
704 "move $12, %2\n\t" /*ptr*/ \
705 __SPECIAL_INSTRUCTION_PREAMBLE \
706 /* T3 = client_request ( T4 ) */ \
707 "or $13, $13, $13\n\t" \
708 "move %0, $11\n\t" /*result*/ \
709 : "=r" (_zzq_result) \
710 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
711 : "cc","memory", "t3", "t4"); \
712 _zzq_result; \
713 })
714
715#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
716 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
717 volatile unsigned int __addr; \
718 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
719 /* %t9 = guest_NRADDR */ \
720 "or $14, $14, $14\n\t" \
721 "move %0, $11" /*result*/ \
722 : "=r" (__addr) \
723 : \
724 : "cc", "memory" , "t3" \
725 ); \
726 _zzq_orig->nraddr = __addr; \
727 }
728
729#define VALGRIND_CALL_NOREDIR_T9 \
730 __SPECIAL_INSTRUCTION_PREAMBLE \
731 /* call-noredir *%t9 */ \
732 "or $15, $15, $15\n\t"
733#endif /* PLAT_mips32_linux */
734
sewardjf5c1a7f2006-10-17 01:32:48 +0000735/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000736
sewardj37091fb2002-11-16 11:06:50 +0000737#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000738
nethercote69d9c462004-10-26 13:00:12 +0000739
njn30d76c62005-06-18 15:07:39 +0000740/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000741/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000742/* ugly. It's the least-worst tradeoff I can think of. */
743/* ------------------------------------------------------------------ */
744
745/* This section defines magic (a.k.a appalling-hack) macros for doing
746 guaranteed-no-redirection macros, so as to get from function
747 wrappers to the functions they are wrapping. The whole point is to
748 construct standard call sequences, but to do the call itself with a
749 special no-redirect call pseudo-instruction that the JIT
750 understands and handles specially. This section is long and
751 repetitious, and I can't see a way to make it shorter.
752
753 The naming scheme is as follows:
754
755 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
756
757 'W' stands for "word" and 'v' for "void". Hence there are
758 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
759 and for each, the possibility of returning a word-typed result, or
760 no result.
761*/
762
763/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +0000764 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
765 the default behaviour equivalance class tag "0000" into the name.
766 See pub_tool_redir.h for details -- normally you don't need to
767 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +0000768
njn5f5ef2a2009-05-11 08:01:09 +0000769/* Use an extra level of macroisation so as to ensure the soname/fnname
770 args are fully macro-expanded before pasting them together. */
771#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
772
sewardj0ec07f32006-01-12 12:32:32 +0000773#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000774 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000775
776#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000777 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000778
sewardjd68ac3e2006-01-20 14:31:57 +0000779/* Use this macro from within a wrapper function to collect the
780 context (address and possibly other info) of the original function.
781 Once you have that you can then use it in one of the CALL_FN_
782 macros. The type of the argument _lval is OrigFn. */
783#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000784
sewardj573f8bc2012-06-05 07:12:15 +0000785/* Also provide end-user facilities for function replacement, rather
786 than wrapping. A replacement function differs from a wrapper in
787 that it has no way to get hold of the original function being
788 called, and hence no way to call onwards to it. In a replacement
789 function, VALGRIND_GET_ORIG_FN always returns zero. */
790
791#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
792 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
793
794#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
795 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
796
sewardj0ec07f32006-01-12 12:32:32 +0000797/* Derivatives of the main macros below, for calling functions
798 returning void. */
799
800#define CALL_FN_v_v(fnptr) \
801 do { volatile unsigned long _junk; \
802 CALL_FN_W_v(_junk,fnptr); } while (0)
803
804#define CALL_FN_v_W(fnptr, arg1) \
805 do { volatile unsigned long _junk; \
806 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
807
808#define CALL_FN_v_WW(fnptr, arg1,arg2) \
809 do { volatile unsigned long _junk; \
810 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
811
sewardj5ce4b152006-03-11 12:57:41 +0000812#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
813 do { volatile unsigned long _junk; \
814 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
815
njn2b5f0a92009-05-19 01:24:50 +0000816#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
817 do { volatile unsigned long _junk; \
818 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
819
820#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
821 do { volatile unsigned long _junk; \
822 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
823
824#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
825 do { volatile unsigned long _junk; \
826 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
827
828#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
829 do { volatile unsigned long _junk; \
830 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
831
njnf76d27a2009-05-28 01:53:07 +0000832/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000833
njnf76d27a2009-05-28 01:53:07 +0000834#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000835
836/* These regs are trashed by the hidden call. No need to mention eax
837 as gcc can already see that, plus causes gcc to bomb. */
838#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
839
840/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
841 long) == 4. */
842
sewardj66226cc2006-01-20 15:46:46 +0000843#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000844 do { \
sewardj66226cc2006-01-20 15:46:46 +0000845 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000846 volatile unsigned long _argvec[1]; \
847 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000848 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000849 __asm__ volatile( \
850 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
851 VALGRIND_CALL_NOREDIR_EAX \
852 : /*out*/ "=a" (_res) \
853 : /*in*/ "a" (&_argvec[0]) \
854 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
855 ); \
856 lval = (__typeof__(lval)) _res; \
857 } while (0)
858
sewardj66226cc2006-01-20 15:46:46 +0000859#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000860 do { \
sewardj66226cc2006-01-20 15:46:46 +0000861 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000862 volatile unsigned long _argvec[2]; \
863 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000864 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000865 _argvec[1] = (unsigned long)(arg1); \
866 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000867 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000868 "pushl 4(%%eax)\n\t" \
869 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
870 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000871 "addl $16, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000872 : /*out*/ "=a" (_res) \
873 : /*in*/ "a" (&_argvec[0]) \
874 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
875 ); \
876 lval = (__typeof__(lval)) _res; \
877 } while (0)
878
sewardj66226cc2006-01-20 15:46:46 +0000879#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000880 do { \
sewardj66226cc2006-01-20 15:46:46 +0000881 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000882 volatile unsigned long _argvec[3]; \
883 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000884 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000885 _argvec[1] = (unsigned long)(arg1); \
886 _argvec[2] = (unsigned long)(arg2); \
887 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000888 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000889 "pushl 8(%%eax)\n\t" \
890 "pushl 4(%%eax)\n\t" \
891 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
892 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000893 "addl $16, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000894 : /*out*/ "=a" (_res) \
895 : /*in*/ "a" (&_argvec[0]) \
896 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
897 ); \
898 lval = (__typeof__(lval)) _res; \
899 } while (0)
900
sewardj9e8b07a2006-02-18 21:13:29 +0000901#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
902 do { \
903 volatile OrigFn _orig = (orig); \
904 volatile unsigned long _argvec[4]; \
905 volatile unsigned long _res; \
906 _argvec[0] = (unsigned long)_orig.nraddr; \
907 _argvec[1] = (unsigned long)(arg1); \
908 _argvec[2] = (unsigned long)(arg2); \
909 _argvec[3] = (unsigned long)(arg3); \
910 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000911 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +0000912 "pushl 12(%%eax)\n\t" \
913 "pushl 8(%%eax)\n\t" \
914 "pushl 4(%%eax)\n\t" \
915 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
916 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +0000917 "addl $16, %%esp\n" \
sewardj9e8b07a2006-02-18 21:13:29 +0000918 : /*out*/ "=a" (_res) \
919 : /*in*/ "a" (&_argvec[0]) \
920 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
921 ); \
922 lval = (__typeof__(lval)) _res; \
923 } while (0)
924
sewardj66226cc2006-01-20 15:46:46 +0000925#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000926 do { \
sewardj66226cc2006-01-20 15:46:46 +0000927 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000928 volatile unsigned long _argvec[5]; \
929 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000930 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000931 _argvec[1] = (unsigned long)(arg1); \
932 _argvec[2] = (unsigned long)(arg2); \
933 _argvec[3] = (unsigned long)(arg3); \
934 _argvec[4] = (unsigned long)(arg4); \
935 __asm__ volatile( \
936 "pushl 16(%%eax)\n\t" \
937 "pushl 12(%%eax)\n\t" \
938 "pushl 8(%%eax)\n\t" \
939 "pushl 4(%%eax)\n\t" \
940 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
941 VALGRIND_CALL_NOREDIR_EAX \
942 "addl $16, %%esp\n" \
943 : /*out*/ "=a" (_res) \
944 : /*in*/ "a" (&_argvec[0]) \
945 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
946 ); \
947 lval = (__typeof__(lval)) _res; \
948 } while (0)
949
sewardj66226cc2006-01-20 15:46:46 +0000950#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000951 do { \
sewardj66226cc2006-01-20 15:46:46 +0000952 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000953 volatile unsigned long _argvec[6]; \
954 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000955 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000956 _argvec[1] = (unsigned long)(arg1); \
957 _argvec[2] = (unsigned long)(arg2); \
958 _argvec[3] = (unsigned long)(arg3); \
959 _argvec[4] = (unsigned long)(arg4); \
960 _argvec[5] = (unsigned long)(arg5); \
961 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000962 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000963 "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 \
sewardj87a287b2010-10-20 15:58:09 +0000970 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +0000971 : /*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
sewardj66226cc2006-01-20 15:46:46 +0000978#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000979 do { \
sewardj66226cc2006-01-20 15:46:46 +0000980 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000981 volatile unsigned long _argvec[7]; \
982 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000983 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000984 _argvec[1] = (unsigned long)(arg1); \
985 _argvec[2] = (unsigned long)(arg2); \
986 _argvec[3] = (unsigned long)(arg3); \
987 _argvec[4] = (unsigned long)(arg4); \
988 _argvec[5] = (unsigned long)(arg5); \
989 _argvec[6] = (unsigned long)(arg6); \
990 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +0000991 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000992 "pushl 24(%%eax)\n\t" \
993 "pushl 20(%%eax)\n\t" \
994 "pushl 16(%%eax)\n\t" \
995 "pushl 12(%%eax)\n\t" \
996 "pushl 8(%%eax)\n\t" \
997 "pushl 4(%%eax)\n\t" \
998 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
999 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001000 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +00001001 : /*out*/ "=a" (_res) \
1002 : /*in*/ "a" (&_argvec[0]) \
1003 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1004 ); \
1005 lval = (__typeof__(lval)) _res; \
1006 } while (0)
1007
sewardj66226cc2006-01-20 15:46:46 +00001008#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1009 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +00001010 do { \
sewardj66226cc2006-01-20 15:46:46 +00001011 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001012 volatile unsigned long _argvec[8]; \
1013 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001014 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001015 _argvec[1] = (unsigned long)(arg1); \
1016 _argvec[2] = (unsigned long)(arg2); \
1017 _argvec[3] = (unsigned long)(arg3); \
1018 _argvec[4] = (unsigned long)(arg4); \
1019 _argvec[5] = (unsigned long)(arg5); \
1020 _argvec[6] = (unsigned long)(arg6); \
1021 _argvec[7] = (unsigned long)(arg7); \
1022 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001023 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001024 "pushl 28(%%eax)\n\t" \
1025 "pushl 24(%%eax)\n\t" \
1026 "pushl 20(%%eax)\n\t" \
1027 "pushl 16(%%eax)\n\t" \
1028 "pushl 12(%%eax)\n\t" \
1029 "pushl 8(%%eax)\n\t" \
1030 "pushl 4(%%eax)\n\t" \
1031 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1032 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001033 "addl $32, %%esp\n" \
sewardj0ec07f32006-01-12 12:32:32 +00001034 : /*out*/ "=a" (_res) \
1035 : /*in*/ "a" (&_argvec[0]) \
1036 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1037 ); \
1038 lval = (__typeof__(lval)) _res; \
1039 } while (0)
1040
sewardj66226cc2006-01-20 15:46:46 +00001041#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1042 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +00001043 do { \
sewardj66226cc2006-01-20 15:46:46 +00001044 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001045 volatile unsigned long _argvec[9]; \
1046 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001047 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001048 _argvec[1] = (unsigned long)(arg1); \
1049 _argvec[2] = (unsigned long)(arg2); \
1050 _argvec[3] = (unsigned long)(arg3); \
1051 _argvec[4] = (unsigned long)(arg4); \
1052 _argvec[5] = (unsigned long)(arg5); \
1053 _argvec[6] = (unsigned long)(arg6); \
1054 _argvec[7] = (unsigned long)(arg7); \
1055 _argvec[8] = (unsigned long)(arg8); \
1056 __asm__ volatile( \
1057 "pushl 32(%%eax)\n\t" \
1058 "pushl 28(%%eax)\n\t" \
1059 "pushl 24(%%eax)\n\t" \
1060 "pushl 20(%%eax)\n\t" \
1061 "pushl 16(%%eax)\n\t" \
1062 "pushl 12(%%eax)\n\t" \
1063 "pushl 8(%%eax)\n\t" \
1064 "pushl 4(%%eax)\n\t" \
1065 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1066 VALGRIND_CALL_NOREDIR_EAX \
1067 "addl $32, %%esp\n" \
1068 : /*out*/ "=a" (_res) \
1069 : /*in*/ "a" (&_argvec[0]) \
1070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1071 ); \
1072 lval = (__typeof__(lval)) _res; \
1073 } while (0)
1074
sewardj45fa5b02006-03-09 19:06:23 +00001075#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1076 arg7,arg8,arg9) \
1077 do { \
1078 volatile OrigFn _orig = (orig); \
1079 volatile unsigned long _argvec[10]; \
1080 volatile unsigned long _res; \
1081 _argvec[0] = (unsigned long)_orig.nraddr; \
1082 _argvec[1] = (unsigned long)(arg1); \
1083 _argvec[2] = (unsigned long)(arg2); \
1084 _argvec[3] = (unsigned long)(arg3); \
1085 _argvec[4] = (unsigned long)(arg4); \
1086 _argvec[5] = (unsigned long)(arg5); \
1087 _argvec[6] = (unsigned long)(arg6); \
1088 _argvec[7] = (unsigned long)(arg7); \
1089 _argvec[8] = (unsigned long)(arg8); \
1090 _argvec[9] = (unsigned long)(arg9); \
1091 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001092 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001093 "pushl 36(%%eax)\n\t" \
1094 "pushl 32(%%eax)\n\t" \
1095 "pushl 28(%%eax)\n\t" \
1096 "pushl 24(%%eax)\n\t" \
1097 "pushl 20(%%eax)\n\t" \
1098 "pushl 16(%%eax)\n\t" \
1099 "pushl 12(%%eax)\n\t" \
1100 "pushl 8(%%eax)\n\t" \
1101 "pushl 4(%%eax)\n\t" \
1102 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1103 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001104 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001105 : /*out*/ "=a" (_res) \
1106 : /*in*/ "a" (&_argvec[0]) \
1107 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1108 ); \
1109 lval = (__typeof__(lval)) _res; \
1110 } while (0)
1111
1112#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1113 arg7,arg8,arg9,arg10) \
1114 do { \
1115 volatile OrigFn _orig = (orig); \
1116 volatile unsigned long _argvec[11]; \
1117 volatile unsigned long _res; \
1118 _argvec[0] = (unsigned long)_orig.nraddr; \
1119 _argvec[1] = (unsigned long)(arg1); \
1120 _argvec[2] = (unsigned long)(arg2); \
1121 _argvec[3] = (unsigned long)(arg3); \
1122 _argvec[4] = (unsigned long)(arg4); \
1123 _argvec[5] = (unsigned long)(arg5); \
1124 _argvec[6] = (unsigned long)(arg6); \
1125 _argvec[7] = (unsigned long)(arg7); \
1126 _argvec[8] = (unsigned long)(arg8); \
1127 _argvec[9] = (unsigned long)(arg9); \
1128 _argvec[10] = (unsigned long)(arg10); \
1129 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001130 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001131 "pushl 40(%%eax)\n\t" \
1132 "pushl 36(%%eax)\n\t" \
1133 "pushl 32(%%eax)\n\t" \
1134 "pushl 28(%%eax)\n\t" \
1135 "pushl 24(%%eax)\n\t" \
1136 "pushl 20(%%eax)\n\t" \
1137 "pushl 16(%%eax)\n\t" \
1138 "pushl 12(%%eax)\n\t" \
1139 "pushl 8(%%eax)\n\t" \
1140 "pushl 4(%%eax)\n\t" \
1141 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1142 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001143 "addl $48, %%esp\n" \
sewardj45fa5b02006-03-09 19:06:23 +00001144 : /*out*/ "=a" (_res) \
1145 : /*in*/ "a" (&_argvec[0]) \
1146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1147 ); \
1148 lval = (__typeof__(lval)) _res; \
1149 } while (0)
1150
sewardj5ce4b152006-03-11 12:57:41 +00001151#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1152 arg6,arg7,arg8,arg9,arg10, \
1153 arg11) \
1154 do { \
1155 volatile OrigFn _orig = (orig); \
1156 volatile unsigned long _argvec[12]; \
1157 volatile unsigned long _res; \
1158 _argvec[0] = (unsigned long)_orig.nraddr; \
1159 _argvec[1] = (unsigned long)(arg1); \
1160 _argvec[2] = (unsigned long)(arg2); \
1161 _argvec[3] = (unsigned long)(arg3); \
1162 _argvec[4] = (unsigned long)(arg4); \
1163 _argvec[5] = (unsigned long)(arg5); \
1164 _argvec[6] = (unsigned long)(arg6); \
1165 _argvec[7] = (unsigned long)(arg7); \
1166 _argvec[8] = (unsigned long)(arg8); \
1167 _argvec[9] = (unsigned long)(arg9); \
1168 _argvec[10] = (unsigned long)(arg10); \
1169 _argvec[11] = (unsigned long)(arg11); \
1170 __asm__ volatile( \
sewardj87a287b2010-10-20 15:58:09 +00001171 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001172 "pushl 44(%%eax)\n\t" \
1173 "pushl 40(%%eax)\n\t" \
1174 "pushl 36(%%eax)\n\t" \
1175 "pushl 32(%%eax)\n\t" \
1176 "pushl 28(%%eax)\n\t" \
1177 "pushl 24(%%eax)\n\t" \
1178 "pushl 20(%%eax)\n\t" \
1179 "pushl 16(%%eax)\n\t" \
1180 "pushl 12(%%eax)\n\t" \
1181 "pushl 8(%%eax)\n\t" \
1182 "pushl 4(%%eax)\n\t" \
1183 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1184 VALGRIND_CALL_NOREDIR_EAX \
sewardj87a287b2010-10-20 15:58:09 +00001185 "addl $48, %%esp\n" \
sewardj5ce4b152006-03-11 12:57:41 +00001186 : /*out*/ "=a" (_res) \
1187 : /*in*/ "a" (&_argvec[0]) \
1188 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1189 ); \
1190 lval = (__typeof__(lval)) _res; \
1191 } while (0)
1192
sewardj66226cc2006-01-20 15:46:46 +00001193#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1194 arg6,arg7,arg8,arg9,arg10, \
1195 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001196 do { \
sewardj66226cc2006-01-20 15:46:46 +00001197 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001198 volatile unsigned long _argvec[13]; \
1199 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001200 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001201 _argvec[1] = (unsigned long)(arg1); \
1202 _argvec[2] = (unsigned long)(arg2); \
1203 _argvec[3] = (unsigned long)(arg3); \
1204 _argvec[4] = (unsigned long)(arg4); \
1205 _argvec[5] = (unsigned long)(arg5); \
1206 _argvec[6] = (unsigned long)(arg6); \
1207 _argvec[7] = (unsigned long)(arg7); \
1208 _argvec[8] = (unsigned long)(arg8); \
1209 _argvec[9] = (unsigned long)(arg9); \
1210 _argvec[10] = (unsigned long)(arg10); \
1211 _argvec[11] = (unsigned long)(arg11); \
1212 _argvec[12] = (unsigned long)(arg12); \
1213 __asm__ volatile( \
1214 "pushl 48(%%eax)\n\t" \
1215 "pushl 44(%%eax)\n\t" \
1216 "pushl 40(%%eax)\n\t" \
1217 "pushl 36(%%eax)\n\t" \
1218 "pushl 32(%%eax)\n\t" \
1219 "pushl 28(%%eax)\n\t" \
1220 "pushl 24(%%eax)\n\t" \
1221 "pushl 20(%%eax)\n\t" \
1222 "pushl 16(%%eax)\n\t" \
1223 "pushl 12(%%eax)\n\t" \
1224 "pushl 8(%%eax)\n\t" \
1225 "pushl 4(%%eax)\n\t" \
1226 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1227 VALGRIND_CALL_NOREDIR_EAX \
1228 "addl $48, %%esp\n" \
1229 : /*out*/ "=a" (_res) \
1230 : /*in*/ "a" (&_argvec[0]) \
1231 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1232 ); \
1233 lval = (__typeof__(lval)) _res; \
1234 } while (0)
1235
njnf76d27a2009-05-28 01:53:07 +00001236#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001237
njnf76d27a2009-05-28 01:53:07 +00001238/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001239
njnf76d27a2009-05-28 01:53:07 +00001240#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001241
1242/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1243
1244/* These regs are trashed by the hidden call. */
1245#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1246 "rdi", "r8", "r9", "r10", "r11"
1247
sewardjdfa55cf2010-10-06 22:07:06 +00001248/* This is all pretty complex. It's so as to make stack unwinding
1249 work reliably. See bug 243270. The basic problem is the sub and
1250 add of 128 of %rsp in all of the following macros. If gcc believes
1251 the CFA is in %rsp, then unwinding may fail, because what's at the
1252 CFA is not what gcc "expected" when it constructs the CFIs for the
1253 places where the macros are instantiated.
1254
1255 But we can't just add a CFI annotation to increase the CFA offset
1256 by 128, to match the sub of 128 from %rsp, because we don't know
1257 whether gcc has chosen %rsp as the CFA at that point, or whether it
1258 has chosen some other register (eg, %rbp). In the latter case,
1259 adding a CFI annotation to change the CFA offset is simply wrong.
1260
1261 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001262 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001263 CFI annotation to say what the register is. We choose %rbp for
1264 this (perhaps perversely), because:
1265
1266 (1) %rbp is already subject to unwinding. If a new register was
1267 chosen then the unwinder would have to unwind it in all stack
1268 traces, which is expensive, and
1269
1270 (2) %rbp is already subject to precise exception updates in the
1271 JIT. If a new register was chosen, we'd have to have precise
1272 exceptions for it too, which reduces performance of the
1273 generated code.
1274
1275 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001276 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001277 list of trashed registers at the end of the inline assembly
1278 fragments; gcc won't allow %rbp to appear in that list. Hence
1279 instead we need to stash %rbp in %r15 for the duration of the asm,
1280 and say that %r15 is trashed instead. gcc seems happy to go with
1281 that.
1282
1283 Oh .. and this all needs to be conditionalised so that it is
1284 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001285 that don't support __builtin_dwarf_cfa. Furthermore, since
1286 this header file is freestanding, it has to be independent of
1287 config.h, and so the following conditionalisation cannot depend on
1288 configure time checks.
1289
1290 Although it's not clear from
1291 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1292 this expression excludes Darwin.
1293 .cfi directives in Darwin assembly appear to be completely
1294 different and I haven't investigated how they work.
1295
1296 For even more entertainment value, note we have to use the
1297 completely undocumented __builtin_dwarf_cfa(), which appears to
1298 really compute the CFA, whereas __builtin_frame_address(0) claims
1299 to but actually doesn't. See
1300 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001301*/
sewardj8d1dc152010-10-08 17:43:26 +00001302#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001303# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001304 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001305# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001306 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001307 "movq %2, %%rbp\n\t" \
1308 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001309 ".cfi_def_cfa rbp, 0\n\t"
1310# define VALGRIND_CFI_EPILOGUE \
1311 "movq %%r15, %%rbp\n\t" \
1312 ".cfi_restore_state\n\t"
1313#else
1314# define __FRAME_POINTER
1315# define VALGRIND_CFI_PROLOGUE
1316# define VALGRIND_CFI_EPILOGUE
1317#endif
1318
1319
sewardj0ec07f32006-01-12 12:32:32 +00001320/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1321 long) == 8. */
1322
sewardja07c2e12007-11-09 23:09:50 +00001323/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1324 macros. In order not to trash the stack redzone, we need to drop
1325 %rsp by 128 before the hidden call, and restore afterwards. The
1326 nastyness is that it is only by luck that the stack still appears
1327 to be unwindable during the hidden call - since then the behaviour
1328 of any routine using this macro does not match what the CFI data
1329 says. Sigh.
1330
1331 Why is this important? Imagine that a wrapper has a stack
1332 allocated local, and passes to the hidden call, a pointer to it.
1333 Because gcc does not know about the hidden call, it may allocate
1334 that local in the redzone. Unfortunately the hidden call may then
1335 trash it before it comes to use it. So we must step clear of the
1336 redzone, for the duration of the hidden call, to make it safe.
1337
1338 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001339 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001340 self describing (none of this CFI nonsense) so at least messing
1341 with the stack pointer doesn't give a danger of non-unwindable
1342 stack. */
1343
sewardjc8858442006-01-20 15:17:20 +00001344#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001345 do { \
sewardjc8858442006-01-20 15:17:20 +00001346 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001347 volatile unsigned long _argvec[1]; \
1348 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001349 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001350 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001351 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001352 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001353 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1354 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001355 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001356 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001357 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001358 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1359 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001360 ); \
1361 lval = (__typeof__(lval)) _res; \
1362 } while (0)
1363
sewardjc8858442006-01-20 15:17:20 +00001364#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001365 do { \
sewardjc8858442006-01-20 15:17:20 +00001366 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001367 volatile unsigned long _argvec[2]; \
1368 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001369 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001370 _argvec[1] = (unsigned long)(arg1); \
1371 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001372 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001373 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001374 "movq 8(%%rax), %%rdi\n\t" \
1375 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1376 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001377 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001378 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001379 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001380 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1381 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001382 ); \
1383 lval = (__typeof__(lval)) _res; \
1384 } while (0)
1385
sewardjc8858442006-01-20 15:17:20 +00001386#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001387 do { \
sewardjc8858442006-01-20 15:17:20 +00001388 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001389 volatile unsigned long _argvec[3]; \
1390 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001391 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001392 _argvec[1] = (unsigned long)(arg1); \
1393 _argvec[2] = (unsigned long)(arg2); \
1394 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001395 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001396 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001397 "movq 16(%%rax), %%rsi\n\t" \
1398 "movq 8(%%rax), %%rdi\n\t" \
1399 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1400 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001401 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001402 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001403 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001404 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1405 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001406 ); \
1407 lval = (__typeof__(lval)) _res; \
1408 } while (0)
1409
sewardja50f9dc2006-03-11 16:19:14 +00001410#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1411 do { \
1412 volatile OrigFn _orig = (orig); \
1413 volatile unsigned long _argvec[4]; \
1414 volatile unsigned long _res; \
1415 _argvec[0] = (unsigned long)_orig.nraddr; \
1416 _argvec[1] = (unsigned long)(arg1); \
1417 _argvec[2] = (unsigned long)(arg2); \
1418 _argvec[3] = (unsigned long)(arg3); \
1419 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001420 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001421 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001422 "movq 24(%%rax), %%rdx\n\t" \
1423 "movq 16(%%rax), %%rsi\n\t" \
1424 "movq 8(%%rax), %%rdi\n\t" \
1425 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1426 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001427 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001428 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001429 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001430 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1431 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001432 ); \
1433 lval = (__typeof__(lval)) _res; \
1434 } while (0)
1435
1436#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1437 do { \
1438 volatile OrigFn _orig = (orig); \
1439 volatile unsigned long _argvec[5]; \
1440 volatile unsigned long _res; \
1441 _argvec[0] = (unsigned long)_orig.nraddr; \
1442 _argvec[1] = (unsigned long)(arg1); \
1443 _argvec[2] = (unsigned long)(arg2); \
1444 _argvec[3] = (unsigned long)(arg3); \
1445 _argvec[4] = (unsigned long)(arg4); \
1446 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001447 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001448 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001449 "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 \
sewardja07c2e12007-11-09 23:09:50 +00001455 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001456 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001457 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001458 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1459 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001460 ); \
1461 lval = (__typeof__(lval)) _res; \
1462 } while (0)
1463
1464#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1465 do { \
1466 volatile OrigFn _orig = (orig); \
1467 volatile unsigned long _argvec[6]; \
1468 volatile unsigned long _res; \
1469 _argvec[0] = (unsigned long)_orig.nraddr; \
1470 _argvec[1] = (unsigned long)(arg1); \
1471 _argvec[2] = (unsigned long)(arg2); \
1472 _argvec[3] = (unsigned long)(arg3); \
1473 _argvec[4] = (unsigned long)(arg4); \
1474 _argvec[5] = (unsigned long)(arg5); \
1475 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001476 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001477 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001478 "movq 40(%%rax), %%r8\n\t" \
1479 "movq 32(%%rax), %%rcx\n\t" \
1480 "movq 24(%%rax), %%rdx\n\t" \
1481 "movq 16(%%rax), %%rsi\n\t" \
1482 "movq 8(%%rax), %%rdi\n\t" \
1483 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1484 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001485 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001486 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001487 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001488 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1489 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001490 ); \
1491 lval = (__typeof__(lval)) _res; \
1492 } while (0)
1493
1494#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1495 do { \
1496 volatile OrigFn _orig = (orig); \
1497 volatile unsigned long _argvec[7]; \
1498 volatile unsigned long _res; \
1499 _argvec[0] = (unsigned long)_orig.nraddr; \
1500 _argvec[1] = (unsigned long)(arg1); \
1501 _argvec[2] = (unsigned long)(arg2); \
1502 _argvec[3] = (unsigned long)(arg3); \
1503 _argvec[4] = (unsigned long)(arg4); \
1504 _argvec[5] = (unsigned long)(arg5); \
1505 _argvec[6] = (unsigned long)(arg6); \
1506 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001507 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001508 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001509 "movq 48(%%rax), %%r9\n\t" \
1510 "movq 40(%%rax), %%r8\n\t" \
1511 "movq 32(%%rax), %%rcx\n\t" \
1512 "movq 24(%%rax), %%rdx\n\t" \
1513 "movq 16(%%rax), %%rsi\n\t" \
1514 "movq 8(%%rax), %%rdi\n\t" \
1515 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1516 VALGRIND_CALL_NOREDIR_RAX \
bart2823aac2010-09-05 12:10:25 +00001517 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001518 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001519 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001520 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1521 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001522 ); \
1523 lval = (__typeof__(lval)) _res; \
1524 } while (0)
1525
1526#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1527 arg7) \
1528 do { \
1529 volatile OrigFn _orig = (orig); \
1530 volatile unsigned long _argvec[8]; \
1531 volatile unsigned long _res; \
1532 _argvec[0] = (unsigned long)_orig.nraddr; \
1533 _argvec[1] = (unsigned long)(arg1); \
1534 _argvec[2] = (unsigned long)(arg2); \
1535 _argvec[3] = (unsigned long)(arg3); \
1536 _argvec[4] = (unsigned long)(arg4); \
1537 _argvec[5] = (unsigned long)(arg5); \
1538 _argvec[6] = (unsigned long)(arg6); \
1539 _argvec[7] = (unsigned long)(arg7); \
1540 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001541 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001542 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001543 "pushq 56(%%rax)\n\t" \
1544 "movq 48(%%rax), %%r9\n\t" \
1545 "movq 40(%%rax), %%r8\n\t" \
1546 "movq 32(%%rax), %%rcx\n\t" \
1547 "movq 24(%%rax), %%rdx\n\t" \
1548 "movq 16(%%rax), %%rsi\n\t" \
1549 "movq 8(%%rax), %%rdi\n\t" \
1550 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1551 VALGRIND_CALL_NOREDIR_RAX \
1552 "addq $8, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001553 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001554 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001555 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001556 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1557 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001558 ); \
1559 lval = (__typeof__(lval)) _res; \
1560 } while (0)
1561
1562#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1563 arg7,arg8) \
1564 do { \
1565 volatile OrigFn _orig = (orig); \
1566 volatile unsigned long _argvec[9]; \
1567 volatile unsigned long _res; \
1568 _argvec[0] = (unsigned long)_orig.nraddr; \
1569 _argvec[1] = (unsigned long)(arg1); \
1570 _argvec[2] = (unsigned long)(arg2); \
1571 _argvec[3] = (unsigned long)(arg3); \
1572 _argvec[4] = (unsigned long)(arg4); \
1573 _argvec[5] = (unsigned long)(arg5); \
1574 _argvec[6] = (unsigned long)(arg6); \
1575 _argvec[7] = (unsigned long)(arg7); \
1576 _argvec[8] = (unsigned long)(arg8); \
1577 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001578 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001579 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001580 "pushq 64(%%rax)\n\t" \
1581 "pushq 56(%%rax)\n\t" \
1582 "movq 48(%%rax), %%r9\n\t" \
1583 "movq 40(%%rax), %%r8\n\t" \
1584 "movq 32(%%rax), %%rcx\n\t" \
1585 "movq 24(%%rax), %%rdx\n\t" \
1586 "movq 16(%%rax), %%rsi\n\t" \
1587 "movq 8(%%rax), %%rdi\n\t" \
1588 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1589 VALGRIND_CALL_NOREDIR_RAX \
1590 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001591 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001592 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001593 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001594 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1595 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001596 ); \
1597 lval = (__typeof__(lval)) _res; \
1598 } while (0)
1599
1600#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1601 arg7,arg8,arg9) \
1602 do { \
1603 volatile OrigFn _orig = (orig); \
1604 volatile unsigned long _argvec[10]; \
1605 volatile unsigned long _res; \
1606 _argvec[0] = (unsigned long)_orig.nraddr; \
1607 _argvec[1] = (unsigned long)(arg1); \
1608 _argvec[2] = (unsigned long)(arg2); \
1609 _argvec[3] = (unsigned long)(arg3); \
1610 _argvec[4] = (unsigned long)(arg4); \
1611 _argvec[5] = (unsigned long)(arg5); \
1612 _argvec[6] = (unsigned long)(arg6); \
1613 _argvec[7] = (unsigned long)(arg7); \
1614 _argvec[8] = (unsigned long)(arg8); \
1615 _argvec[9] = (unsigned long)(arg9); \
1616 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001617 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001618 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001619 "pushq 72(%%rax)\n\t" \
1620 "pushq 64(%%rax)\n\t" \
1621 "pushq 56(%%rax)\n\t" \
1622 "movq 48(%%rax), %%r9\n\t" \
1623 "movq 40(%%rax), %%r8\n\t" \
1624 "movq 32(%%rax), %%rcx\n\t" \
1625 "movq 24(%%rax), %%rdx\n\t" \
1626 "movq 16(%%rax), %%rsi\n\t" \
1627 "movq 8(%%rax), %%rdi\n\t" \
1628 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1629 VALGRIND_CALL_NOREDIR_RAX \
1630 "addq $24, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001631 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001632 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001633 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001634 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1635 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001636 ); \
1637 lval = (__typeof__(lval)) _res; \
1638 } while (0)
1639
1640#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1641 arg7,arg8,arg9,arg10) \
1642 do { \
1643 volatile OrigFn _orig = (orig); \
1644 volatile unsigned long _argvec[11]; \
1645 volatile unsigned long _res; \
1646 _argvec[0] = (unsigned long)_orig.nraddr; \
1647 _argvec[1] = (unsigned long)(arg1); \
1648 _argvec[2] = (unsigned long)(arg2); \
1649 _argvec[3] = (unsigned long)(arg3); \
1650 _argvec[4] = (unsigned long)(arg4); \
1651 _argvec[5] = (unsigned long)(arg5); \
1652 _argvec[6] = (unsigned long)(arg6); \
1653 _argvec[7] = (unsigned long)(arg7); \
1654 _argvec[8] = (unsigned long)(arg8); \
1655 _argvec[9] = (unsigned long)(arg9); \
1656 _argvec[10] = (unsigned long)(arg10); \
1657 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001658 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001659 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001660 "pushq 80(%%rax)\n\t" \
1661 "pushq 72(%%rax)\n\t" \
1662 "pushq 64(%%rax)\n\t" \
1663 "pushq 56(%%rax)\n\t" \
1664 "movq 48(%%rax), %%r9\n\t" \
1665 "movq 40(%%rax), %%r8\n\t" \
1666 "movq 32(%%rax), %%rcx\n\t" \
1667 "movq 24(%%rax), %%rdx\n\t" \
1668 "movq 16(%%rax), %%rsi\n\t" \
1669 "movq 8(%%rax), %%rdi\n\t" \
1670 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1671 VALGRIND_CALL_NOREDIR_RAX \
1672 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001673 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001674 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001675 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001676 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1677 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001678 ); \
1679 lval = (__typeof__(lval)) _res; \
1680 } while (0)
1681
1682#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1683 arg7,arg8,arg9,arg10,arg11) \
1684 do { \
1685 volatile OrigFn _orig = (orig); \
1686 volatile unsigned long _argvec[12]; \
1687 volatile unsigned long _res; \
1688 _argvec[0] = (unsigned long)_orig.nraddr; \
1689 _argvec[1] = (unsigned long)(arg1); \
1690 _argvec[2] = (unsigned long)(arg2); \
1691 _argvec[3] = (unsigned long)(arg3); \
1692 _argvec[4] = (unsigned long)(arg4); \
1693 _argvec[5] = (unsigned long)(arg5); \
1694 _argvec[6] = (unsigned long)(arg6); \
1695 _argvec[7] = (unsigned long)(arg7); \
1696 _argvec[8] = (unsigned long)(arg8); \
1697 _argvec[9] = (unsigned long)(arg9); \
1698 _argvec[10] = (unsigned long)(arg10); \
1699 _argvec[11] = (unsigned long)(arg11); \
1700 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001701 VALGRIND_CFI_PROLOGUE \
sewardj87a287b2010-10-20 15:58:09 +00001702 "subq $136,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001703 "pushq 88(%%rax)\n\t" \
1704 "pushq 80(%%rax)\n\t" \
1705 "pushq 72(%%rax)\n\t" \
1706 "pushq 64(%%rax)\n\t" \
1707 "pushq 56(%%rax)\n\t" \
1708 "movq 48(%%rax), %%r9\n\t" \
1709 "movq 40(%%rax), %%r8\n\t" \
1710 "movq 32(%%rax), %%rcx\n\t" \
1711 "movq 24(%%rax), %%rdx\n\t" \
1712 "movq 16(%%rax), %%rsi\n\t" \
1713 "movq 8(%%rax), %%rdi\n\t" \
1714 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1715 VALGRIND_CALL_NOREDIR_RAX \
1716 "addq $40, %%rsp\n" \
sewardj87a287b2010-10-20 15:58:09 +00001717 "addq $136,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001718 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001719 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001720 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1721 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001722 ); \
1723 lval = (__typeof__(lval)) _res; \
1724 } while (0)
1725
1726#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1727 arg7,arg8,arg9,arg10,arg11,arg12) \
1728 do { \
1729 volatile OrigFn _orig = (orig); \
1730 volatile unsigned long _argvec[13]; \
1731 volatile unsigned long _res; \
1732 _argvec[0] = (unsigned long)_orig.nraddr; \
1733 _argvec[1] = (unsigned long)(arg1); \
1734 _argvec[2] = (unsigned long)(arg2); \
1735 _argvec[3] = (unsigned long)(arg3); \
1736 _argvec[4] = (unsigned long)(arg4); \
1737 _argvec[5] = (unsigned long)(arg5); \
1738 _argvec[6] = (unsigned long)(arg6); \
1739 _argvec[7] = (unsigned long)(arg7); \
1740 _argvec[8] = (unsigned long)(arg8); \
1741 _argvec[9] = (unsigned long)(arg9); \
1742 _argvec[10] = (unsigned long)(arg10); \
1743 _argvec[11] = (unsigned long)(arg11); \
1744 _argvec[12] = (unsigned long)(arg12); \
1745 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001746 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001747 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001748 "pushq 96(%%rax)\n\t" \
1749 "pushq 88(%%rax)\n\t" \
1750 "pushq 80(%%rax)\n\t" \
1751 "pushq 72(%%rax)\n\t" \
1752 "pushq 64(%%rax)\n\t" \
1753 "pushq 56(%%rax)\n\t" \
1754 "movq 48(%%rax), %%r9\n\t" \
1755 "movq 40(%%rax), %%r8\n\t" \
1756 "movq 32(%%rax), %%rcx\n\t" \
1757 "movq 24(%%rax), %%rdx\n\t" \
1758 "movq 16(%%rax), %%rsi\n\t" \
1759 "movq 8(%%rax), %%rdi\n\t" \
1760 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1761 VALGRIND_CALL_NOREDIR_RAX \
1762 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001763 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001764 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001765 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001766 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1767 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001768 ); \
1769 lval = (__typeof__(lval)) _res; \
1770 } while (0)
1771
njnf76d27a2009-05-28 01:53:07 +00001772#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001773
sewardjf5c1a7f2006-10-17 01:32:48 +00001774/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001775
sewardjf5c1a7f2006-10-17 01:32:48 +00001776#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001777
sewardjead61df2006-03-12 13:39:15 +00001778/* This is useful for finding out about the on-stack stuff:
1779
1780 extern int f9 ( int,int,int,int,int,int,int,int,int );
1781 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1782 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1783 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1784
1785 int g9 ( void ) {
1786 return f9(11,22,33,44,55,66,77,88,99);
1787 }
1788 int g10 ( void ) {
1789 return f10(11,22,33,44,55,66,77,88,99,110);
1790 }
1791 int g11 ( void ) {
1792 return f11(11,22,33,44,55,66,77,88,99,110,121);
1793 }
1794 int g12 ( void ) {
1795 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1796 }
1797*/
1798
sewardj0ec07f32006-01-12 12:32:32 +00001799/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1800
1801/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001802#define __CALLER_SAVED_REGS \
1803 "lr", "ctr", "xer", \
1804 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1805 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1806 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001807
sewardjead61df2006-03-12 13:39:15 +00001808/* These CALL_FN_ macros assume that on ppc32-linux,
1809 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001810
sewardj38de0992006-01-20 16:46:34 +00001811#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001812 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001813 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001814 volatile unsigned long _argvec[1]; \
1815 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001816 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001817 __asm__ volatile( \
1818 "mr 11,%1\n\t" \
1819 "lwz 11,0(11)\n\t" /* target->r11 */ \
1820 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1821 "mr %0,3" \
1822 : /*out*/ "=r" (_res) \
1823 : /*in*/ "r" (&_argvec[0]) \
1824 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1825 ); \
1826 lval = (__typeof__(lval)) _res; \
1827 } while (0)
1828
sewardj38de0992006-01-20 16:46:34 +00001829#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001830 do { \
sewardj38de0992006-01-20 16:46:34 +00001831 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001832 volatile unsigned long _argvec[2]; \
1833 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001834 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001835 _argvec[1] = (unsigned long)arg1; \
1836 __asm__ volatile( \
1837 "mr 11,%1\n\t" \
1838 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1839 "lwz 11,0(11)\n\t" /* target->r11 */ \
1840 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1841 "mr %0,3" \
1842 : /*out*/ "=r" (_res) \
1843 : /*in*/ "r" (&_argvec[0]) \
1844 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1845 ); \
1846 lval = (__typeof__(lval)) _res; \
1847 } while (0)
1848
sewardj38de0992006-01-20 16:46:34 +00001849#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001850 do { \
sewardj38de0992006-01-20 16:46:34 +00001851 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001852 volatile unsigned long _argvec[3]; \
1853 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001854 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001855 _argvec[1] = (unsigned long)arg1; \
1856 _argvec[2] = (unsigned long)arg2; \
1857 __asm__ volatile( \
1858 "mr 11,%1\n\t" \
1859 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1860 "lwz 4,8(11)\n\t" \
1861 "lwz 11,0(11)\n\t" /* target->r11 */ \
1862 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1863 "mr %0,3" \
1864 : /*out*/ "=r" (_res) \
1865 : /*in*/ "r" (&_argvec[0]) \
1866 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1867 ); \
1868 lval = (__typeof__(lval)) _res; \
1869 } while (0)
1870
sewardjead61df2006-03-12 13:39:15 +00001871#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1872 do { \
1873 volatile OrigFn _orig = (orig); \
1874 volatile unsigned long _argvec[4]; \
1875 volatile unsigned long _res; \
1876 _argvec[0] = (unsigned long)_orig.nraddr; \
1877 _argvec[1] = (unsigned long)arg1; \
1878 _argvec[2] = (unsigned long)arg2; \
1879 _argvec[3] = (unsigned long)arg3; \
1880 __asm__ volatile( \
1881 "mr 11,%1\n\t" \
1882 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1883 "lwz 4,8(11)\n\t" \
1884 "lwz 5,12(11)\n\t" \
1885 "lwz 11,0(11)\n\t" /* target->r11 */ \
1886 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1887 "mr %0,3" \
1888 : /*out*/ "=r" (_res) \
1889 : /*in*/ "r" (&_argvec[0]) \
1890 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1891 ); \
1892 lval = (__typeof__(lval)) _res; \
1893 } while (0)
1894
1895#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1896 do { \
1897 volatile OrigFn _orig = (orig); \
1898 volatile unsigned long _argvec[5]; \
1899 volatile unsigned long _res; \
1900 _argvec[0] = (unsigned long)_orig.nraddr; \
1901 _argvec[1] = (unsigned long)arg1; \
1902 _argvec[2] = (unsigned long)arg2; \
1903 _argvec[3] = (unsigned long)arg3; \
1904 _argvec[4] = (unsigned long)arg4; \
1905 __asm__ volatile( \
1906 "mr 11,%1\n\t" \
1907 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1908 "lwz 4,8(11)\n\t" \
1909 "lwz 5,12(11)\n\t" \
1910 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1911 "lwz 11,0(11)\n\t" /* target->r11 */ \
1912 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1913 "mr %0,3" \
1914 : /*out*/ "=r" (_res) \
1915 : /*in*/ "r" (&_argvec[0]) \
1916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1917 ); \
1918 lval = (__typeof__(lval)) _res; \
1919 } while (0)
1920
1921#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1922 do { \
1923 volatile OrigFn _orig = (orig); \
1924 volatile unsigned long _argvec[6]; \
1925 volatile unsigned long _res; \
1926 _argvec[0] = (unsigned long)_orig.nraddr; \
1927 _argvec[1] = (unsigned long)arg1; \
1928 _argvec[2] = (unsigned long)arg2; \
1929 _argvec[3] = (unsigned long)arg3; \
1930 _argvec[4] = (unsigned long)arg4; \
1931 _argvec[5] = (unsigned long)arg5; \
1932 __asm__ volatile( \
1933 "mr 11,%1\n\t" \
1934 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1935 "lwz 4,8(11)\n\t" \
1936 "lwz 5,12(11)\n\t" \
1937 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1938 "lwz 7,20(11)\n\t" \
1939 "lwz 11,0(11)\n\t" /* target->r11 */ \
1940 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1941 "mr %0,3" \
1942 : /*out*/ "=r" (_res) \
1943 : /*in*/ "r" (&_argvec[0]) \
1944 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1945 ); \
1946 lval = (__typeof__(lval)) _res; \
1947 } while (0)
1948
1949#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1950 do { \
1951 volatile OrigFn _orig = (orig); \
1952 volatile unsigned long _argvec[7]; \
1953 volatile unsigned long _res; \
1954 _argvec[0] = (unsigned long)_orig.nraddr; \
1955 _argvec[1] = (unsigned long)arg1; \
1956 _argvec[2] = (unsigned long)arg2; \
1957 _argvec[3] = (unsigned long)arg3; \
1958 _argvec[4] = (unsigned long)arg4; \
1959 _argvec[5] = (unsigned long)arg5; \
1960 _argvec[6] = (unsigned long)arg6; \
1961 __asm__ volatile( \
1962 "mr 11,%1\n\t" \
1963 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1964 "lwz 4,8(11)\n\t" \
1965 "lwz 5,12(11)\n\t" \
1966 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1967 "lwz 7,20(11)\n\t" \
1968 "lwz 8,24(11)\n\t" \
1969 "lwz 11,0(11)\n\t" /* target->r11 */ \
1970 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1971 "mr %0,3" \
1972 : /*out*/ "=r" (_res) \
1973 : /*in*/ "r" (&_argvec[0]) \
1974 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1975 ); \
1976 lval = (__typeof__(lval)) _res; \
1977 } while (0)
1978
1979#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1980 arg7) \
1981 do { \
1982 volatile OrigFn _orig = (orig); \
1983 volatile unsigned long _argvec[8]; \
1984 volatile unsigned long _res; \
1985 _argvec[0] = (unsigned long)_orig.nraddr; \
1986 _argvec[1] = (unsigned long)arg1; \
1987 _argvec[2] = (unsigned long)arg2; \
1988 _argvec[3] = (unsigned long)arg3; \
1989 _argvec[4] = (unsigned long)arg4; \
1990 _argvec[5] = (unsigned long)arg5; \
1991 _argvec[6] = (unsigned long)arg6; \
1992 _argvec[7] = (unsigned long)arg7; \
1993 __asm__ volatile( \
1994 "mr 11,%1\n\t" \
1995 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1996 "lwz 4,8(11)\n\t" \
1997 "lwz 5,12(11)\n\t" \
1998 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1999 "lwz 7,20(11)\n\t" \
2000 "lwz 8,24(11)\n\t" \
2001 "lwz 9,28(11)\n\t" \
2002 "lwz 11,0(11)\n\t" /* target->r11 */ \
2003 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2004 "mr %0,3" \
2005 : /*out*/ "=r" (_res) \
2006 : /*in*/ "r" (&_argvec[0]) \
2007 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2008 ); \
2009 lval = (__typeof__(lval)) _res; \
2010 } while (0)
2011
2012#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2013 arg7,arg8) \
2014 do { \
2015 volatile OrigFn _orig = (orig); \
2016 volatile unsigned long _argvec[9]; \
2017 volatile unsigned long _res; \
2018 _argvec[0] = (unsigned long)_orig.nraddr; \
2019 _argvec[1] = (unsigned long)arg1; \
2020 _argvec[2] = (unsigned long)arg2; \
2021 _argvec[3] = (unsigned long)arg3; \
2022 _argvec[4] = (unsigned long)arg4; \
2023 _argvec[5] = (unsigned long)arg5; \
2024 _argvec[6] = (unsigned long)arg6; \
2025 _argvec[7] = (unsigned long)arg7; \
2026 _argvec[8] = (unsigned long)arg8; \
2027 __asm__ volatile( \
2028 "mr 11,%1\n\t" \
2029 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2030 "lwz 4,8(11)\n\t" \
2031 "lwz 5,12(11)\n\t" \
2032 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2033 "lwz 7,20(11)\n\t" \
2034 "lwz 8,24(11)\n\t" \
2035 "lwz 9,28(11)\n\t" \
2036 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2037 "lwz 11,0(11)\n\t" /* target->r11 */ \
2038 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2039 "mr %0,3" \
2040 : /*out*/ "=r" (_res) \
2041 : /*in*/ "r" (&_argvec[0]) \
2042 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2043 ); \
2044 lval = (__typeof__(lval)) _res; \
2045 } while (0)
2046
2047#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2048 arg7,arg8,arg9) \
2049 do { \
2050 volatile OrigFn _orig = (orig); \
2051 volatile unsigned long _argvec[10]; \
2052 volatile unsigned long _res; \
2053 _argvec[0] = (unsigned long)_orig.nraddr; \
2054 _argvec[1] = (unsigned long)arg1; \
2055 _argvec[2] = (unsigned long)arg2; \
2056 _argvec[3] = (unsigned long)arg3; \
2057 _argvec[4] = (unsigned long)arg4; \
2058 _argvec[5] = (unsigned long)arg5; \
2059 _argvec[6] = (unsigned long)arg6; \
2060 _argvec[7] = (unsigned long)arg7; \
2061 _argvec[8] = (unsigned long)arg8; \
2062 _argvec[9] = (unsigned long)arg9; \
2063 __asm__ volatile( \
2064 "mr 11,%1\n\t" \
2065 "addi 1,1,-16\n\t" \
2066 /* arg9 */ \
2067 "lwz 3,36(11)\n\t" \
2068 "stw 3,8(1)\n\t" \
2069 /* args1-8 */ \
2070 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2071 "lwz 4,8(11)\n\t" \
2072 "lwz 5,12(11)\n\t" \
2073 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2074 "lwz 7,20(11)\n\t" \
2075 "lwz 8,24(11)\n\t" \
2076 "lwz 9,28(11)\n\t" \
2077 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2078 "lwz 11,0(11)\n\t" /* target->r11 */ \
2079 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2080 "addi 1,1,16\n\t" \
2081 "mr %0,3" \
2082 : /*out*/ "=r" (_res) \
2083 : /*in*/ "r" (&_argvec[0]) \
2084 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2085 ); \
2086 lval = (__typeof__(lval)) _res; \
2087 } while (0)
2088
2089#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2090 arg7,arg8,arg9,arg10) \
2091 do { \
2092 volatile OrigFn _orig = (orig); \
2093 volatile unsigned long _argvec[11]; \
2094 volatile unsigned long _res; \
2095 _argvec[0] = (unsigned long)_orig.nraddr; \
2096 _argvec[1] = (unsigned long)arg1; \
2097 _argvec[2] = (unsigned long)arg2; \
2098 _argvec[3] = (unsigned long)arg3; \
2099 _argvec[4] = (unsigned long)arg4; \
2100 _argvec[5] = (unsigned long)arg5; \
2101 _argvec[6] = (unsigned long)arg6; \
2102 _argvec[7] = (unsigned long)arg7; \
2103 _argvec[8] = (unsigned long)arg8; \
2104 _argvec[9] = (unsigned long)arg9; \
2105 _argvec[10] = (unsigned long)arg10; \
2106 __asm__ volatile( \
2107 "mr 11,%1\n\t" \
2108 "addi 1,1,-16\n\t" \
2109 /* arg10 */ \
2110 "lwz 3,40(11)\n\t" \
2111 "stw 3,12(1)\n\t" \
2112 /* arg9 */ \
2113 "lwz 3,36(11)\n\t" \
2114 "stw 3,8(1)\n\t" \
2115 /* args1-8 */ \
2116 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2117 "lwz 4,8(11)\n\t" \
2118 "lwz 5,12(11)\n\t" \
2119 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2120 "lwz 7,20(11)\n\t" \
2121 "lwz 8,24(11)\n\t" \
2122 "lwz 9,28(11)\n\t" \
2123 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2124 "lwz 11,0(11)\n\t" /* target->r11 */ \
2125 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2126 "addi 1,1,16\n\t" \
2127 "mr %0,3" \
2128 : /*out*/ "=r" (_res) \
2129 : /*in*/ "r" (&_argvec[0]) \
2130 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2131 ); \
2132 lval = (__typeof__(lval)) _res; \
2133 } while (0)
2134
2135#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2136 arg7,arg8,arg9,arg10,arg11) \
2137 do { \
2138 volatile OrigFn _orig = (orig); \
2139 volatile unsigned long _argvec[12]; \
2140 volatile unsigned long _res; \
2141 _argvec[0] = (unsigned long)_orig.nraddr; \
2142 _argvec[1] = (unsigned long)arg1; \
2143 _argvec[2] = (unsigned long)arg2; \
2144 _argvec[3] = (unsigned long)arg3; \
2145 _argvec[4] = (unsigned long)arg4; \
2146 _argvec[5] = (unsigned long)arg5; \
2147 _argvec[6] = (unsigned long)arg6; \
2148 _argvec[7] = (unsigned long)arg7; \
2149 _argvec[8] = (unsigned long)arg8; \
2150 _argvec[9] = (unsigned long)arg9; \
2151 _argvec[10] = (unsigned long)arg10; \
2152 _argvec[11] = (unsigned long)arg11; \
2153 __asm__ volatile( \
2154 "mr 11,%1\n\t" \
2155 "addi 1,1,-32\n\t" \
2156 /* arg11 */ \
2157 "lwz 3,44(11)\n\t" \
2158 "stw 3,16(1)\n\t" \
2159 /* arg10 */ \
2160 "lwz 3,40(11)\n\t" \
2161 "stw 3,12(1)\n\t" \
2162 /* arg9 */ \
2163 "lwz 3,36(11)\n\t" \
2164 "stw 3,8(1)\n\t" \
2165 /* args1-8 */ \
2166 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2167 "lwz 4,8(11)\n\t" \
2168 "lwz 5,12(11)\n\t" \
2169 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2170 "lwz 7,20(11)\n\t" \
2171 "lwz 8,24(11)\n\t" \
2172 "lwz 9,28(11)\n\t" \
2173 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2174 "lwz 11,0(11)\n\t" /* target->r11 */ \
2175 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2176 "addi 1,1,32\n\t" \
2177 "mr %0,3" \
2178 : /*out*/ "=r" (_res) \
2179 : /*in*/ "r" (&_argvec[0]) \
2180 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2181 ); \
2182 lval = (__typeof__(lval)) _res; \
2183 } while (0)
2184
2185#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2186 arg7,arg8,arg9,arg10,arg11,arg12) \
2187 do { \
2188 volatile OrigFn _orig = (orig); \
2189 volatile unsigned long _argvec[13]; \
2190 volatile unsigned long _res; \
2191 _argvec[0] = (unsigned long)_orig.nraddr; \
2192 _argvec[1] = (unsigned long)arg1; \
2193 _argvec[2] = (unsigned long)arg2; \
2194 _argvec[3] = (unsigned long)arg3; \
2195 _argvec[4] = (unsigned long)arg4; \
2196 _argvec[5] = (unsigned long)arg5; \
2197 _argvec[6] = (unsigned long)arg6; \
2198 _argvec[7] = (unsigned long)arg7; \
2199 _argvec[8] = (unsigned long)arg8; \
2200 _argvec[9] = (unsigned long)arg9; \
2201 _argvec[10] = (unsigned long)arg10; \
2202 _argvec[11] = (unsigned long)arg11; \
2203 _argvec[12] = (unsigned long)arg12; \
2204 __asm__ volatile( \
2205 "mr 11,%1\n\t" \
2206 "addi 1,1,-32\n\t" \
2207 /* arg12 */ \
2208 "lwz 3,48(11)\n\t" \
2209 "stw 3,20(1)\n\t" \
2210 /* arg11 */ \
2211 "lwz 3,44(11)\n\t" \
2212 "stw 3,16(1)\n\t" \
2213 /* arg10 */ \
2214 "lwz 3,40(11)\n\t" \
2215 "stw 3,12(1)\n\t" \
2216 /* arg9 */ \
2217 "lwz 3,36(11)\n\t" \
2218 "stw 3,8(1)\n\t" \
2219 /* args1-8 */ \
2220 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2221 "lwz 4,8(11)\n\t" \
2222 "lwz 5,12(11)\n\t" \
2223 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2224 "lwz 7,20(11)\n\t" \
2225 "lwz 8,24(11)\n\t" \
2226 "lwz 9,28(11)\n\t" \
2227 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2228 "lwz 11,0(11)\n\t" /* target->r11 */ \
2229 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2230 "addi 1,1,32\n\t" \
2231 "mr %0,3" \
2232 : /*out*/ "=r" (_res) \
2233 : /*in*/ "r" (&_argvec[0]) \
2234 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2235 ); \
2236 lval = (__typeof__(lval)) _res; \
2237 } while (0)
2238
sewardjf5c1a7f2006-10-17 01:32:48 +00002239#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002240
sewardjf5c1a7f2006-10-17 01:32:48 +00002241/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002242
sewardjf5c1a7f2006-10-17 01:32:48 +00002243#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002244
2245/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2246
2247/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002248#define __CALLER_SAVED_REGS \
2249 "lr", "ctr", "xer", \
2250 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2251 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2252 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002253
2254/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2255 long) == 8. */
2256
sewardjd68ac3e2006-01-20 14:31:57 +00002257#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002258 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002259 volatile OrigFn _orig = (orig); \
2260 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002261 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002262 /* _argvec[0] holds current r2 across the call */ \
2263 _argvec[1] = (unsigned long)_orig.r2; \
2264 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002265 __asm__ volatile( \
2266 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002267 "std 2,-16(11)\n\t" /* save tocptr */ \
2268 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2269 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002270 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2271 "mr 11,%1\n\t" \
2272 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002273 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002274 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002275 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002276 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2277 ); \
2278 lval = (__typeof__(lval)) _res; \
2279 } while (0)
2280
sewardjd68ac3e2006-01-20 14:31:57 +00002281#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002282 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002283 volatile OrigFn _orig = (orig); \
2284 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002285 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002286 /* _argvec[0] holds current r2 across the call */ \
2287 _argvec[1] = (unsigned long)_orig.r2; \
2288 _argvec[2] = (unsigned long)_orig.nraddr; \
2289 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002290 __asm__ volatile( \
2291 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002292 "std 2,-16(11)\n\t" /* save tocptr */ \
2293 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2294 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2295 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002296 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2297 "mr 11,%1\n\t" \
2298 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002299 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002300 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002301 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002302 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2303 ); \
2304 lval = (__typeof__(lval)) _res; \
2305 } while (0)
2306
sewardjd68ac3e2006-01-20 14:31:57 +00002307#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002308 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002309 volatile OrigFn _orig = (orig); \
2310 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002311 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002312 /* _argvec[0] holds current r2 across the call */ \
2313 _argvec[1] = (unsigned long)_orig.r2; \
2314 _argvec[2] = (unsigned long)_orig.nraddr; \
2315 _argvec[2+1] = (unsigned long)arg1; \
2316 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002317 __asm__ volatile( \
2318 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002319 "std 2,-16(11)\n\t" /* save tocptr */ \
2320 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2321 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002322 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002323 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002324 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2325 "mr 11,%1\n\t" \
2326 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002327 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002328 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002329 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002330 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2331 ); \
2332 lval = (__typeof__(lval)) _res; \
2333 } while (0)
2334
sewardjcd636392006-03-12 16:48:14 +00002335#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2336 do { \
2337 volatile OrigFn _orig = (orig); \
2338 volatile unsigned long _argvec[3+3]; \
2339 volatile unsigned long _res; \
2340 /* _argvec[0] holds current r2 across the call */ \
2341 _argvec[1] = (unsigned long)_orig.r2; \
2342 _argvec[2] = (unsigned long)_orig.nraddr; \
2343 _argvec[2+1] = (unsigned long)arg1; \
2344 _argvec[2+2] = (unsigned long)arg2; \
2345 _argvec[2+3] = (unsigned long)arg3; \
2346 __asm__ volatile( \
2347 "mr 11,%1\n\t" \
2348 "std 2,-16(11)\n\t" /* save tocptr */ \
2349 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2350 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2351 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2352 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2353 "ld 11, 0(11)\n\t" /* target->r11 */ \
2354 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2355 "mr 11,%1\n\t" \
2356 "mr %0,3\n\t" \
2357 "ld 2,-16(11)" /* restore tocptr */ \
2358 : /*out*/ "=r" (_res) \
2359 : /*in*/ "r" (&_argvec[2]) \
2360 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2361 ); \
2362 lval = (__typeof__(lval)) _res; \
2363 } while (0)
2364
2365#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2366 do { \
2367 volatile OrigFn _orig = (orig); \
2368 volatile unsigned long _argvec[3+4]; \
2369 volatile unsigned long _res; \
2370 /* _argvec[0] holds current r2 across the call */ \
2371 _argvec[1] = (unsigned long)_orig.r2; \
2372 _argvec[2] = (unsigned long)_orig.nraddr; \
2373 _argvec[2+1] = (unsigned long)arg1; \
2374 _argvec[2+2] = (unsigned long)arg2; \
2375 _argvec[2+3] = (unsigned long)arg3; \
2376 _argvec[2+4] = (unsigned long)arg4; \
2377 __asm__ volatile( \
2378 "mr 11,%1\n\t" \
2379 "std 2,-16(11)\n\t" /* save tocptr */ \
2380 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2381 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2382 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2383 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2384 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2385 "ld 11, 0(11)\n\t" /* target->r11 */ \
2386 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2387 "mr 11,%1\n\t" \
2388 "mr %0,3\n\t" \
2389 "ld 2,-16(11)" /* restore tocptr */ \
2390 : /*out*/ "=r" (_res) \
2391 : /*in*/ "r" (&_argvec[2]) \
2392 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2393 ); \
2394 lval = (__typeof__(lval)) _res; \
2395 } while (0)
2396
2397#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2398 do { \
2399 volatile OrigFn _orig = (orig); \
2400 volatile unsigned long _argvec[3+5]; \
2401 volatile unsigned long _res; \
2402 /* _argvec[0] holds current r2 across the call */ \
2403 _argvec[1] = (unsigned long)_orig.r2; \
2404 _argvec[2] = (unsigned long)_orig.nraddr; \
2405 _argvec[2+1] = (unsigned long)arg1; \
2406 _argvec[2+2] = (unsigned long)arg2; \
2407 _argvec[2+3] = (unsigned long)arg3; \
2408 _argvec[2+4] = (unsigned long)arg4; \
2409 _argvec[2+5] = (unsigned long)arg5; \
2410 __asm__ volatile( \
2411 "mr 11,%1\n\t" \
2412 "std 2,-16(11)\n\t" /* save tocptr */ \
2413 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2414 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2415 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2416 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2417 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2418 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2419 "ld 11, 0(11)\n\t" /* target->r11 */ \
2420 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2421 "mr 11,%1\n\t" \
2422 "mr %0,3\n\t" \
2423 "ld 2,-16(11)" /* restore tocptr */ \
2424 : /*out*/ "=r" (_res) \
2425 : /*in*/ "r" (&_argvec[2]) \
2426 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2427 ); \
2428 lval = (__typeof__(lval)) _res; \
2429 } while (0)
2430
2431#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2432 do { \
2433 volatile OrigFn _orig = (orig); \
2434 volatile unsigned long _argvec[3+6]; \
2435 volatile unsigned long _res; \
2436 /* _argvec[0] holds current r2 across the call */ \
2437 _argvec[1] = (unsigned long)_orig.r2; \
2438 _argvec[2] = (unsigned long)_orig.nraddr; \
2439 _argvec[2+1] = (unsigned long)arg1; \
2440 _argvec[2+2] = (unsigned long)arg2; \
2441 _argvec[2+3] = (unsigned long)arg3; \
2442 _argvec[2+4] = (unsigned long)arg4; \
2443 _argvec[2+5] = (unsigned long)arg5; \
2444 _argvec[2+6] = (unsigned long)arg6; \
2445 __asm__ volatile( \
2446 "mr 11,%1\n\t" \
2447 "std 2,-16(11)\n\t" /* save tocptr */ \
2448 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2449 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2450 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2451 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2452 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2453 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2454 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2455 "ld 11, 0(11)\n\t" /* target->r11 */ \
2456 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2457 "mr 11,%1\n\t" \
2458 "mr %0,3\n\t" \
2459 "ld 2,-16(11)" /* restore tocptr */ \
2460 : /*out*/ "=r" (_res) \
2461 : /*in*/ "r" (&_argvec[2]) \
2462 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2463 ); \
2464 lval = (__typeof__(lval)) _res; \
2465 } while (0)
2466
2467#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2468 arg7) \
2469 do { \
2470 volatile OrigFn _orig = (orig); \
2471 volatile unsigned long _argvec[3+7]; \
2472 volatile unsigned long _res; \
2473 /* _argvec[0] holds current r2 across the call */ \
2474 _argvec[1] = (unsigned long)_orig.r2; \
2475 _argvec[2] = (unsigned long)_orig.nraddr; \
2476 _argvec[2+1] = (unsigned long)arg1; \
2477 _argvec[2+2] = (unsigned long)arg2; \
2478 _argvec[2+3] = (unsigned long)arg3; \
2479 _argvec[2+4] = (unsigned long)arg4; \
2480 _argvec[2+5] = (unsigned long)arg5; \
2481 _argvec[2+6] = (unsigned long)arg6; \
2482 _argvec[2+7] = (unsigned long)arg7; \
2483 __asm__ volatile( \
2484 "mr 11,%1\n\t" \
2485 "std 2,-16(11)\n\t" /* save tocptr */ \
2486 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2487 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2488 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2489 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2490 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2491 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2492 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2493 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2494 "ld 11, 0(11)\n\t" /* target->r11 */ \
2495 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2496 "mr 11,%1\n\t" \
2497 "mr %0,3\n\t" \
2498 "ld 2,-16(11)" /* restore tocptr */ \
2499 : /*out*/ "=r" (_res) \
2500 : /*in*/ "r" (&_argvec[2]) \
2501 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2502 ); \
2503 lval = (__typeof__(lval)) _res; \
2504 } while (0)
2505
2506#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2507 arg7,arg8) \
2508 do { \
2509 volatile OrigFn _orig = (orig); \
2510 volatile unsigned long _argvec[3+8]; \
2511 volatile unsigned long _res; \
2512 /* _argvec[0] holds current r2 across the call */ \
2513 _argvec[1] = (unsigned long)_orig.r2; \
2514 _argvec[2] = (unsigned long)_orig.nraddr; \
2515 _argvec[2+1] = (unsigned long)arg1; \
2516 _argvec[2+2] = (unsigned long)arg2; \
2517 _argvec[2+3] = (unsigned long)arg3; \
2518 _argvec[2+4] = (unsigned long)arg4; \
2519 _argvec[2+5] = (unsigned long)arg5; \
2520 _argvec[2+6] = (unsigned long)arg6; \
2521 _argvec[2+7] = (unsigned long)arg7; \
2522 _argvec[2+8] = (unsigned long)arg8; \
2523 __asm__ volatile( \
2524 "mr 11,%1\n\t" \
2525 "std 2,-16(11)\n\t" /* save tocptr */ \
2526 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2527 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2528 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2529 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2530 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2531 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2532 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2533 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2534 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2535 "ld 11, 0(11)\n\t" /* target->r11 */ \
2536 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2537 "mr 11,%1\n\t" \
2538 "mr %0,3\n\t" \
2539 "ld 2,-16(11)" /* restore tocptr */ \
2540 : /*out*/ "=r" (_res) \
2541 : /*in*/ "r" (&_argvec[2]) \
2542 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2543 ); \
2544 lval = (__typeof__(lval)) _res; \
2545 } while (0)
2546
2547#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2548 arg7,arg8,arg9) \
2549 do { \
2550 volatile OrigFn _orig = (orig); \
2551 volatile unsigned long _argvec[3+9]; \
2552 volatile unsigned long _res; \
2553 /* _argvec[0] holds current r2 across the call */ \
2554 _argvec[1] = (unsigned long)_orig.r2; \
2555 _argvec[2] = (unsigned long)_orig.nraddr; \
2556 _argvec[2+1] = (unsigned long)arg1; \
2557 _argvec[2+2] = (unsigned long)arg2; \
2558 _argvec[2+3] = (unsigned long)arg3; \
2559 _argvec[2+4] = (unsigned long)arg4; \
2560 _argvec[2+5] = (unsigned long)arg5; \
2561 _argvec[2+6] = (unsigned long)arg6; \
2562 _argvec[2+7] = (unsigned long)arg7; \
2563 _argvec[2+8] = (unsigned long)arg8; \
2564 _argvec[2+9] = (unsigned long)arg9; \
2565 __asm__ volatile( \
2566 "mr 11,%1\n\t" \
2567 "std 2,-16(11)\n\t" /* save tocptr */ \
2568 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2569 "addi 1,1,-128\n\t" /* expand stack frame */ \
2570 /* arg9 */ \
2571 "ld 3,72(11)\n\t" \
2572 "std 3,112(1)\n\t" \
2573 /* args1-8 */ \
2574 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2575 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2576 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2577 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2578 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2579 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2580 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2581 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2582 "ld 11, 0(11)\n\t" /* target->r11 */ \
2583 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2584 "mr 11,%1\n\t" \
2585 "mr %0,3\n\t" \
2586 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2587 "addi 1,1,128" /* restore frame */ \
2588 : /*out*/ "=r" (_res) \
2589 : /*in*/ "r" (&_argvec[2]) \
2590 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2591 ); \
2592 lval = (__typeof__(lval)) _res; \
2593 } while (0)
2594
2595#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2596 arg7,arg8,arg9,arg10) \
2597 do { \
2598 volatile OrigFn _orig = (orig); \
2599 volatile unsigned long _argvec[3+10]; \
2600 volatile unsigned long _res; \
2601 /* _argvec[0] holds current r2 across the call */ \
2602 _argvec[1] = (unsigned long)_orig.r2; \
2603 _argvec[2] = (unsigned long)_orig.nraddr; \
2604 _argvec[2+1] = (unsigned long)arg1; \
2605 _argvec[2+2] = (unsigned long)arg2; \
2606 _argvec[2+3] = (unsigned long)arg3; \
2607 _argvec[2+4] = (unsigned long)arg4; \
2608 _argvec[2+5] = (unsigned long)arg5; \
2609 _argvec[2+6] = (unsigned long)arg6; \
2610 _argvec[2+7] = (unsigned long)arg7; \
2611 _argvec[2+8] = (unsigned long)arg8; \
2612 _argvec[2+9] = (unsigned long)arg9; \
2613 _argvec[2+10] = (unsigned long)arg10; \
2614 __asm__ volatile( \
2615 "mr 11,%1\n\t" \
2616 "std 2,-16(11)\n\t" /* save tocptr */ \
2617 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2618 "addi 1,1,-128\n\t" /* expand stack frame */ \
2619 /* arg10 */ \
2620 "ld 3,80(11)\n\t" \
2621 "std 3,120(1)\n\t" \
2622 /* arg9 */ \
2623 "ld 3,72(11)\n\t" \
2624 "std 3,112(1)\n\t" \
2625 /* args1-8 */ \
2626 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2627 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2628 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2629 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2630 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2631 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2632 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2633 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2634 "ld 11, 0(11)\n\t" /* target->r11 */ \
2635 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2636 "mr 11,%1\n\t" \
2637 "mr %0,3\n\t" \
2638 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2639 "addi 1,1,128" /* restore frame */ \
2640 : /*out*/ "=r" (_res) \
2641 : /*in*/ "r" (&_argvec[2]) \
2642 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2643 ); \
2644 lval = (__typeof__(lval)) _res; \
2645 } while (0)
2646
2647#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2648 arg7,arg8,arg9,arg10,arg11) \
2649 do { \
2650 volatile OrigFn _orig = (orig); \
2651 volatile unsigned long _argvec[3+11]; \
2652 volatile unsigned long _res; \
2653 /* _argvec[0] holds current r2 across the call */ \
2654 _argvec[1] = (unsigned long)_orig.r2; \
2655 _argvec[2] = (unsigned long)_orig.nraddr; \
2656 _argvec[2+1] = (unsigned long)arg1; \
2657 _argvec[2+2] = (unsigned long)arg2; \
2658 _argvec[2+3] = (unsigned long)arg3; \
2659 _argvec[2+4] = (unsigned long)arg4; \
2660 _argvec[2+5] = (unsigned long)arg5; \
2661 _argvec[2+6] = (unsigned long)arg6; \
2662 _argvec[2+7] = (unsigned long)arg7; \
2663 _argvec[2+8] = (unsigned long)arg8; \
2664 _argvec[2+9] = (unsigned long)arg9; \
2665 _argvec[2+10] = (unsigned long)arg10; \
2666 _argvec[2+11] = (unsigned long)arg11; \
2667 __asm__ volatile( \
2668 "mr 11,%1\n\t" \
2669 "std 2,-16(11)\n\t" /* save tocptr */ \
2670 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2671 "addi 1,1,-144\n\t" /* expand stack frame */ \
2672 /* arg11 */ \
2673 "ld 3,88(11)\n\t" \
2674 "std 3,128(1)\n\t" \
2675 /* arg10 */ \
2676 "ld 3,80(11)\n\t" \
2677 "std 3,120(1)\n\t" \
2678 /* arg9 */ \
2679 "ld 3,72(11)\n\t" \
2680 "std 3,112(1)\n\t" \
2681 /* args1-8 */ \
2682 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2683 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2684 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2685 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2686 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2687 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2688 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2689 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2690 "ld 11, 0(11)\n\t" /* target->r11 */ \
2691 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2692 "mr 11,%1\n\t" \
2693 "mr %0,3\n\t" \
2694 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2695 "addi 1,1,144" /* restore frame */ \
2696 : /*out*/ "=r" (_res) \
2697 : /*in*/ "r" (&_argvec[2]) \
2698 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2699 ); \
2700 lval = (__typeof__(lval)) _res; \
2701 } while (0)
2702
2703#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2704 arg7,arg8,arg9,arg10,arg11,arg12) \
2705 do { \
2706 volatile OrigFn _orig = (orig); \
2707 volatile unsigned long _argvec[3+12]; \
2708 volatile unsigned long _res; \
2709 /* _argvec[0] holds current r2 across the call */ \
2710 _argvec[1] = (unsigned long)_orig.r2; \
2711 _argvec[2] = (unsigned long)_orig.nraddr; \
2712 _argvec[2+1] = (unsigned long)arg1; \
2713 _argvec[2+2] = (unsigned long)arg2; \
2714 _argvec[2+3] = (unsigned long)arg3; \
2715 _argvec[2+4] = (unsigned long)arg4; \
2716 _argvec[2+5] = (unsigned long)arg5; \
2717 _argvec[2+6] = (unsigned long)arg6; \
2718 _argvec[2+7] = (unsigned long)arg7; \
2719 _argvec[2+8] = (unsigned long)arg8; \
2720 _argvec[2+9] = (unsigned long)arg9; \
2721 _argvec[2+10] = (unsigned long)arg10; \
2722 _argvec[2+11] = (unsigned long)arg11; \
2723 _argvec[2+12] = (unsigned long)arg12; \
2724 __asm__ volatile( \
2725 "mr 11,%1\n\t" \
2726 "std 2,-16(11)\n\t" /* save tocptr */ \
2727 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2728 "addi 1,1,-144\n\t" /* expand stack frame */ \
2729 /* arg12 */ \
2730 "ld 3,96(11)\n\t" \
2731 "std 3,136(1)\n\t" \
2732 /* arg11 */ \
2733 "ld 3,88(11)\n\t" \
2734 "std 3,128(1)\n\t" \
2735 /* arg10 */ \
2736 "ld 3,80(11)\n\t" \
2737 "std 3,120(1)\n\t" \
2738 /* arg9 */ \
2739 "ld 3,72(11)\n\t" \
2740 "std 3,112(1)\n\t" \
2741 /* args1-8 */ \
2742 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2743 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2744 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2745 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2746 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2747 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2748 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2749 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2750 "ld 11, 0(11)\n\t" /* target->r11 */ \
2751 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2752 "mr 11,%1\n\t" \
2753 "mr %0,3\n\t" \
2754 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2755 "addi 1,1,144" /* restore frame */ \
2756 : /*out*/ "=r" (_res) \
2757 : /*in*/ "r" (&_argvec[2]) \
2758 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2759 ); \
2760 lval = (__typeof__(lval)) _res; \
2761 } while (0)
2762
sewardjf5c1a7f2006-10-17 01:32:48 +00002763#endif /* PLAT_ppc64_linux */
2764
sewardj59570ff2010-01-01 11:59:33 +00002765/* ------------------------- arm-linux ------------------------- */
2766
2767#if defined(PLAT_arm_linux)
2768
2769/* These regs are trashed by the hidden call. */
2770#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2771
2772/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2773 long) == 4. */
2774
2775#define CALL_FN_W_v(lval, orig) \
2776 do { \
2777 volatile OrigFn _orig = (orig); \
2778 volatile unsigned long _argvec[1]; \
2779 volatile unsigned long _res; \
2780 _argvec[0] = (unsigned long)_orig.nraddr; \
2781 __asm__ volatile( \
2782 "ldr r4, [%1] \n\t" /* target->r4 */ \
2783 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2784 "mov %0, r0\n" \
2785 : /*out*/ "=r" (_res) \
2786 : /*in*/ "0" (&_argvec[0]) \
2787 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2788 ); \
2789 lval = (__typeof__(lval)) _res; \
2790 } while (0)
2791
2792#define CALL_FN_W_W(lval, orig, arg1) \
2793 do { \
2794 volatile OrigFn _orig = (orig); \
2795 volatile unsigned long _argvec[2]; \
2796 volatile unsigned long _res; \
2797 _argvec[0] = (unsigned long)_orig.nraddr; \
2798 _argvec[1] = (unsigned long)(arg1); \
2799 __asm__ volatile( \
2800 "ldr r0, [%1, #4] \n\t" \
2801 "ldr r4, [%1] \n\t" /* target->r4 */ \
2802 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2803 "mov %0, r0\n" \
2804 : /*out*/ "=r" (_res) \
2805 : /*in*/ "0" (&_argvec[0]) \
2806 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2807 ); \
2808 lval = (__typeof__(lval)) _res; \
2809 } while (0)
2810
2811#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2812 do { \
2813 volatile OrigFn _orig = (orig); \
2814 volatile unsigned long _argvec[3]; \
2815 volatile unsigned long _res; \
2816 _argvec[0] = (unsigned long)_orig.nraddr; \
2817 _argvec[1] = (unsigned long)(arg1); \
2818 _argvec[2] = (unsigned long)(arg2); \
2819 __asm__ volatile( \
2820 "ldr r0, [%1, #4] \n\t" \
2821 "ldr r1, [%1, #8] \n\t" \
2822 "ldr r4, [%1] \n\t" /* target->r4 */ \
2823 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2824 "mov %0, r0\n" \
2825 : /*out*/ "=r" (_res) \
2826 : /*in*/ "0" (&_argvec[0]) \
2827 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2828 ); \
2829 lval = (__typeof__(lval)) _res; \
2830 } while (0)
2831
2832#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2833 do { \
2834 volatile OrigFn _orig = (orig); \
2835 volatile unsigned long _argvec[4]; \
2836 volatile unsigned long _res; \
2837 _argvec[0] = (unsigned long)_orig.nraddr; \
2838 _argvec[1] = (unsigned long)(arg1); \
2839 _argvec[2] = (unsigned long)(arg2); \
2840 _argvec[3] = (unsigned long)(arg3); \
2841 __asm__ volatile( \
2842 "ldr r0, [%1, #4] \n\t" \
2843 "ldr r1, [%1, #8] \n\t" \
2844 "ldr r2, [%1, #12] \n\t" \
2845 "ldr r4, [%1] \n\t" /* target->r4 */ \
2846 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2847 "mov %0, r0\n" \
2848 : /*out*/ "=r" (_res) \
2849 : /*in*/ "0" (&_argvec[0]) \
2850 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2851 ); \
2852 lval = (__typeof__(lval)) _res; \
2853 } while (0)
2854
2855#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2856 do { \
2857 volatile OrigFn _orig = (orig); \
2858 volatile unsigned long _argvec[5]; \
2859 volatile unsigned long _res; \
2860 _argvec[0] = (unsigned long)_orig.nraddr; \
2861 _argvec[1] = (unsigned long)(arg1); \
2862 _argvec[2] = (unsigned long)(arg2); \
2863 _argvec[3] = (unsigned long)(arg3); \
2864 _argvec[4] = (unsigned long)(arg4); \
2865 __asm__ volatile( \
2866 "ldr r0, [%1, #4] \n\t" \
2867 "ldr r1, [%1, #8] \n\t" \
2868 "ldr r2, [%1, #12] \n\t" \
2869 "ldr r3, [%1, #16] \n\t" \
2870 "ldr r4, [%1] \n\t" /* target->r4 */ \
2871 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2872 "mov %0, r0" \
2873 : /*out*/ "=r" (_res) \
2874 : /*in*/ "0" (&_argvec[0]) \
2875 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2876 ); \
2877 lval = (__typeof__(lval)) _res; \
2878 } while (0)
2879
2880#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2881 do { \
2882 volatile OrigFn _orig = (orig); \
2883 volatile unsigned long _argvec[6]; \
2884 volatile unsigned long _res; \
2885 _argvec[0] = (unsigned long)_orig.nraddr; \
2886 _argvec[1] = (unsigned long)(arg1); \
2887 _argvec[2] = (unsigned long)(arg2); \
2888 _argvec[3] = (unsigned long)(arg3); \
2889 _argvec[4] = (unsigned long)(arg4); \
2890 _argvec[5] = (unsigned long)(arg5); \
2891 __asm__ volatile( \
2892 "ldr r0, [%1, #20] \n\t" \
2893 "push {r0} \n\t" \
2894 "ldr r0, [%1, #4] \n\t" \
2895 "ldr r1, [%1, #8] \n\t" \
2896 "ldr r2, [%1, #12] \n\t" \
2897 "ldr r3, [%1, #16] \n\t" \
2898 "ldr r4, [%1] \n\t" /* target->r4 */ \
2899 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2900 "add sp, sp, #4 \n\t" \
2901 "mov %0, r0" \
2902 : /*out*/ "=r" (_res) \
2903 : /*in*/ "0" (&_argvec[0]) \
2904 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2905 ); \
2906 lval = (__typeof__(lval)) _res; \
2907 } while (0)
2908
2909#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2910 do { \
2911 volatile OrigFn _orig = (orig); \
2912 volatile unsigned long _argvec[7]; \
2913 volatile unsigned long _res; \
2914 _argvec[0] = (unsigned long)_orig.nraddr; \
2915 _argvec[1] = (unsigned long)(arg1); \
2916 _argvec[2] = (unsigned long)(arg2); \
2917 _argvec[3] = (unsigned long)(arg3); \
2918 _argvec[4] = (unsigned long)(arg4); \
2919 _argvec[5] = (unsigned long)(arg5); \
2920 _argvec[6] = (unsigned long)(arg6); \
2921 __asm__ volatile( \
2922 "ldr r0, [%1, #20] \n\t" \
2923 "ldr r1, [%1, #24] \n\t" \
2924 "push {r0, r1} \n\t" \
2925 "ldr r0, [%1, #4] \n\t" \
2926 "ldr r1, [%1, #8] \n\t" \
2927 "ldr r2, [%1, #12] \n\t" \
2928 "ldr r3, [%1, #16] \n\t" \
2929 "ldr r4, [%1] \n\t" /* target->r4 */ \
2930 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2931 "add sp, sp, #8 \n\t" \
2932 "mov %0, r0" \
2933 : /*out*/ "=r" (_res) \
2934 : /*in*/ "0" (&_argvec[0]) \
2935 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2936 ); \
2937 lval = (__typeof__(lval)) _res; \
2938 } while (0)
2939
2940#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2941 arg7) \
2942 do { \
2943 volatile OrigFn _orig = (orig); \
2944 volatile unsigned long _argvec[8]; \
2945 volatile unsigned long _res; \
2946 _argvec[0] = (unsigned long)_orig.nraddr; \
2947 _argvec[1] = (unsigned long)(arg1); \
2948 _argvec[2] = (unsigned long)(arg2); \
2949 _argvec[3] = (unsigned long)(arg3); \
2950 _argvec[4] = (unsigned long)(arg4); \
2951 _argvec[5] = (unsigned long)(arg5); \
2952 _argvec[6] = (unsigned long)(arg6); \
2953 _argvec[7] = (unsigned long)(arg7); \
2954 __asm__ volatile( \
2955 "ldr r0, [%1, #20] \n\t" \
2956 "ldr r1, [%1, #24] \n\t" \
2957 "ldr r2, [%1, #28] \n\t" \
2958 "push {r0, r1, r2} \n\t" \
2959 "ldr r0, [%1, #4] \n\t" \
2960 "ldr r1, [%1, #8] \n\t" \
2961 "ldr r2, [%1, #12] \n\t" \
2962 "ldr r3, [%1, #16] \n\t" \
2963 "ldr r4, [%1] \n\t" /* target->r4 */ \
2964 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2965 "add sp, sp, #12 \n\t" \
2966 "mov %0, r0" \
2967 : /*out*/ "=r" (_res) \
2968 : /*in*/ "0" (&_argvec[0]) \
2969 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2970 ); \
2971 lval = (__typeof__(lval)) _res; \
2972 } while (0)
2973
2974#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2975 arg7,arg8) \
2976 do { \
2977 volatile OrigFn _orig = (orig); \
2978 volatile unsigned long _argvec[9]; \
2979 volatile unsigned long _res; \
2980 _argvec[0] = (unsigned long)_orig.nraddr; \
2981 _argvec[1] = (unsigned long)(arg1); \
2982 _argvec[2] = (unsigned long)(arg2); \
2983 _argvec[3] = (unsigned long)(arg3); \
2984 _argvec[4] = (unsigned long)(arg4); \
2985 _argvec[5] = (unsigned long)(arg5); \
2986 _argvec[6] = (unsigned long)(arg6); \
2987 _argvec[7] = (unsigned long)(arg7); \
2988 _argvec[8] = (unsigned long)(arg8); \
2989 __asm__ volatile( \
2990 "ldr r0, [%1, #20] \n\t" \
2991 "ldr r1, [%1, #24] \n\t" \
2992 "ldr r2, [%1, #28] \n\t" \
2993 "ldr r3, [%1, #32] \n\t" \
2994 "push {r0, r1, r2, r3} \n\t" \
2995 "ldr r0, [%1, #4] \n\t" \
2996 "ldr r1, [%1, #8] \n\t" \
2997 "ldr r2, [%1, #12] \n\t" \
2998 "ldr r3, [%1, #16] \n\t" \
2999 "ldr r4, [%1] \n\t" /* target->r4 */ \
3000 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3001 "add sp, sp, #16 \n\t" \
3002 "mov %0, r0" \
3003 : /*out*/ "=r" (_res) \
3004 : /*in*/ "0" (&_argvec[0]) \
3005 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3006 ); \
3007 lval = (__typeof__(lval)) _res; \
3008 } while (0)
3009
3010#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3011 arg7,arg8,arg9) \
3012 do { \
3013 volatile OrigFn _orig = (orig); \
3014 volatile unsigned long _argvec[10]; \
3015 volatile unsigned long _res; \
3016 _argvec[0] = (unsigned long)_orig.nraddr; \
3017 _argvec[1] = (unsigned long)(arg1); \
3018 _argvec[2] = (unsigned long)(arg2); \
3019 _argvec[3] = (unsigned long)(arg3); \
3020 _argvec[4] = (unsigned long)(arg4); \
3021 _argvec[5] = (unsigned long)(arg5); \
3022 _argvec[6] = (unsigned long)(arg6); \
3023 _argvec[7] = (unsigned long)(arg7); \
3024 _argvec[8] = (unsigned long)(arg8); \
3025 _argvec[9] = (unsigned long)(arg9); \
3026 __asm__ volatile( \
3027 "ldr r0, [%1, #20] \n\t" \
3028 "ldr r1, [%1, #24] \n\t" \
3029 "ldr r2, [%1, #28] \n\t" \
3030 "ldr r3, [%1, #32] \n\t" \
3031 "ldr r4, [%1, #36] \n\t" \
3032 "push {r0, r1, r2, r3, r4} \n\t" \
3033 "ldr r0, [%1, #4] \n\t" \
3034 "ldr r1, [%1, #8] \n\t" \
3035 "ldr r2, [%1, #12] \n\t" \
3036 "ldr r3, [%1, #16] \n\t" \
3037 "ldr r4, [%1] \n\t" /* target->r4 */ \
3038 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3039 "add sp, sp, #20 \n\t" \
3040 "mov %0, r0" \
3041 : /*out*/ "=r" (_res) \
3042 : /*in*/ "0" (&_argvec[0]) \
3043 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3044 ); \
3045 lval = (__typeof__(lval)) _res; \
3046 } while (0)
3047
3048#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3049 arg7,arg8,arg9,arg10) \
3050 do { \
3051 volatile OrigFn _orig = (orig); \
3052 volatile unsigned long _argvec[11]; \
3053 volatile unsigned long _res; \
3054 _argvec[0] = (unsigned long)_orig.nraddr; \
3055 _argvec[1] = (unsigned long)(arg1); \
3056 _argvec[2] = (unsigned long)(arg2); \
3057 _argvec[3] = (unsigned long)(arg3); \
3058 _argvec[4] = (unsigned long)(arg4); \
3059 _argvec[5] = (unsigned long)(arg5); \
3060 _argvec[6] = (unsigned long)(arg6); \
3061 _argvec[7] = (unsigned long)(arg7); \
3062 _argvec[8] = (unsigned long)(arg8); \
3063 _argvec[9] = (unsigned long)(arg9); \
3064 _argvec[10] = (unsigned long)(arg10); \
3065 __asm__ volatile( \
3066 "ldr r0, [%1, #40] \n\t" \
3067 "push {r0} \n\t" \
3068 "ldr r0, [%1, #20] \n\t" \
3069 "ldr r1, [%1, #24] \n\t" \
3070 "ldr r2, [%1, #28] \n\t" \
3071 "ldr r3, [%1, #32] \n\t" \
3072 "ldr r4, [%1, #36] \n\t" \
3073 "push {r0, r1, r2, r3, r4} \n\t" \
3074 "ldr r0, [%1, #4] \n\t" \
3075 "ldr r1, [%1, #8] \n\t" \
3076 "ldr r2, [%1, #12] \n\t" \
3077 "ldr r3, [%1, #16] \n\t" \
3078 "ldr r4, [%1] \n\t" /* target->r4 */ \
3079 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3080 "add sp, sp, #24 \n\t" \
3081 "mov %0, r0" \
3082 : /*out*/ "=r" (_res) \
3083 : /*in*/ "0" (&_argvec[0]) \
3084 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3085 ); \
3086 lval = (__typeof__(lval)) _res; \
3087 } while (0)
3088
3089#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3090 arg6,arg7,arg8,arg9,arg10, \
3091 arg11) \
3092 do { \
3093 volatile OrigFn _orig = (orig); \
3094 volatile unsigned long _argvec[12]; \
3095 volatile unsigned long _res; \
3096 _argvec[0] = (unsigned long)_orig.nraddr; \
3097 _argvec[1] = (unsigned long)(arg1); \
3098 _argvec[2] = (unsigned long)(arg2); \
3099 _argvec[3] = (unsigned long)(arg3); \
3100 _argvec[4] = (unsigned long)(arg4); \
3101 _argvec[5] = (unsigned long)(arg5); \
3102 _argvec[6] = (unsigned long)(arg6); \
3103 _argvec[7] = (unsigned long)(arg7); \
3104 _argvec[8] = (unsigned long)(arg8); \
3105 _argvec[9] = (unsigned long)(arg9); \
3106 _argvec[10] = (unsigned long)(arg10); \
3107 _argvec[11] = (unsigned long)(arg11); \
3108 __asm__ volatile( \
3109 "ldr r0, [%1, #40] \n\t" \
3110 "ldr r1, [%1, #44] \n\t" \
3111 "push {r0, r1} \n\t" \
3112 "ldr r0, [%1, #20] \n\t" \
3113 "ldr r1, [%1, #24] \n\t" \
3114 "ldr r2, [%1, #28] \n\t" \
3115 "ldr r3, [%1, #32] \n\t" \
3116 "ldr r4, [%1, #36] \n\t" \
3117 "push {r0, r1, r2, r3, r4} \n\t" \
3118 "ldr r0, [%1, #4] \n\t" \
3119 "ldr r1, [%1, #8] \n\t" \
3120 "ldr r2, [%1, #12] \n\t" \
3121 "ldr r3, [%1, #16] \n\t" \
3122 "ldr r4, [%1] \n\t" /* target->r4 */ \
3123 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3124 "add sp, sp, #28 \n\t" \
3125 "mov %0, r0" \
3126 : /*out*/ "=r" (_res) \
3127 : /*in*/ "0" (&_argvec[0]) \
3128 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3129 ); \
3130 lval = (__typeof__(lval)) _res; \
3131 } while (0)
3132
3133#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3134 arg6,arg7,arg8,arg9,arg10, \
3135 arg11,arg12) \
3136 do { \
3137 volatile OrigFn _orig = (orig); \
3138 volatile unsigned long _argvec[13]; \
3139 volatile unsigned long _res; \
3140 _argvec[0] = (unsigned long)_orig.nraddr; \
3141 _argvec[1] = (unsigned long)(arg1); \
3142 _argvec[2] = (unsigned long)(arg2); \
3143 _argvec[3] = (unsigned long)(arg3); \
3144 _argvec[4] = (unsigned long)(arg4); \
3145 _argvec[5] = (unsigned long)(arg5); \
3146 _argvec[6] = (unsigned long)(arg6); \
3147 _argvec[7] = (unsigned long)(arg7); \
3148 _argvec[8] = (unsigned long)(arg8); \
3149 _argvec[9] = (unsigned long)(arg9); \
3150 _argvec[10] = (unsigned long)(arg10); \
3151 _argvec[11] = (unsigned long)(arg11); \
3152 _argvec[12] = (unsigned long)(arg12); \
3153 __asm__ volatile( \
3154 "ldr r0, [%1, #40] \n\t" \
3155 "ldr r1, [%1, #44] \n\t" \
3156 "ldr r2, [%1, #48] \n\t" \
3157 "push {r0, r1, r2} \n\t" \
3158 "ldr r0, [%1, #20] \n\t" \
3159 "ldr r1, [%1, #24] \n\t" \
3160 "ldr r2, [%1, #28] \n\t" \
3161 "ldr r3, [%1, #32] \n\t" \
3162 "ldr r4, [%1, #36] \n\t" \
3163 "push {r0, r1, r2, r3, r4} \n\t" \
3164 "ldr r0, [%1, #4] \n\t" \
3165 "ldr r1, [%1, #8] \n\t" \
3166 "ldr r2, [%1, #12] \n\t" \
3167 "ldr r3, [%1, #16] \n\t" \
3168 "ldr r4, [%1] \n\t" /* target->r4 */ \
3169 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3170 "add sp, sp, #32 \n\t" \
3171 "mov %0, r0" \
3172 : /*out*/ "=r" (_res) \
3173 : /*in*/ "0" (&_argvec[0]) \
3174 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3175 ); \
3176 lval = (__typeof__(lval)) _res; \
3177 } while (0)
3178
3179#endif /* PLAT_arm_linux */
3180
sewardjb5b87402011-03-07 16:05:35 +00003181/* ------------------------- s390x-linux ------------------------- */
3182
3183#if defined(PLAT_s390x_linux)
3184
3185/* Similar workaround as amd64 (see above), but we use r11 as frame
3186 pointer and save the old r11 in r7. r11 might be used for
3187 argvec, therefore we copy argvec in r1 since r1 is clobbered
3188 after the call anyway. */
3189#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
3190# define __FRAME_POINTER \
3191 ,"d"(__builtin_dwarf_cfa())
3192# define VALGRIND_CFI_PROLOGUE \
3193 ".cfi_remember_state\n\t" \
3194 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
3195 "lgr 7,11\n\t" \
3196 "lgr 11,%2\n\t" \
3197 ".cfi_def_cfa r11, 0\n\t"
3198# define VALGRIND_CFI_EPILOGUE \
3199 "lgr 11, 7\n\t" \
3200 ".cfi_restore_state\n\t"
3201#else
3202# define __FRAME_POINTER
3203# define VALGRIND_CFI_PROLOGUE \
3204 "lgr 1,%1\n\t"
3205# define VALGRIND_CFI_EPILOGUE
3206#endif
3207
3208
3209
3210
3211/* These regs are trashed by the hidden call. Note that we overwrite
3212 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
3213 function a proper return address. All others are ABI defined call
3214 clobbers. */
3215#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
3216 "f0","f1","f2","f3","f4","f5","f6","f7"
3217
3218
3219#define CALL_FN_W_v(lval, orig) \
3220 do { \
3221 volatile OrigFn _orig = (orig); \
3222 volatile unsigned long _argvec[1]; \
3223 volatile unsigned long _res; \
3224 _argvec[0] = (unsigned long)_orig.nraddr; \
3225 __asm__ volatile( \
3226 VALGRIND_CFI_PROLOGUE \
3227 "aghi 15,-160\n\t" \
3228 "lg 1, 0(1)\n\t" /* target->r1 */ \
3229 VALGRIND_CALL_NOREDIR_R1 \
3230 "lgr %0, 2\n\t" \
3231 "aghi 15,160\n\t" \
3232 VALGRIND_CFI_EPILOGUE \
3233 : /*out*/ "=d" (_res) \
3234 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
3235 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3236 ); \
3237 lval = (__typeof__(lval)) _res; \
3238 } while (0)
3239
3240/* The call abi has the arguments in r2-r6 and stack */
3241#define CALL_FN_W_W(lval, orig, arg1) \
3242 do { \
3243 volatile OrigFn _orig = (orig); \
3244 volatile unsigned long _argvec[2]; \
3245 volatile unsigned long _res; \
3246 _argvec[0] = (unsigned long)_orig.nraddr; \
3247 _argvec[1] = (unsigned long)arg1; \
3248 __asm__ volatile( \
3249 VALGRIND_CFI_PROLOGUE \
3250 "aghi 15,-160\n\t" \
3251 "lg 2, 8(1)\n\t" \
3252 "lg 1, 0(1)\n\t" \
3253 VALGRIND_CALL_NOREDIR_R1 \
3254 "lgr %0, 2\n\t" \
3255 "aghi 15,160\n\t" \
3256 VALGRIND_CFI_EPILOGUE \
3257 : /*out*/ "=d" (_res) \
3258 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3259 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3260 ); \
3261 lval = (__typeof__(lval)) _res; \
3262 } while (0)
3263
3264#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
3265 do { \
3266 volatile OrigFn _orig = (orig); \
3267 volatile unsigned long _argvec[3]; \
3268 volatile unsigned long _res; \
3269 _argvec[0] = (unsigned long)_orig.nraddr; \
3270 _argvec[1] = (unsigned long)arg1; \
3271 _argvec[2] = (unsigned long)arg2; \
3272 __asm__ volatile( \
3273 VALGRIND_CFI_PROLOGUE \
3274 "aghi 15,-160\n\t" \
3275 "lg 2, 8(1)\n\t" \
3276 "lg 3,16(1)\n\t" \
3277 "lg 1, 0(1)\n\t" \
3278 VALGRIND_CALL_NOREDIR_R1 \
3279 "lgr %0, 2\n\t" \
3280 "aghi 15,160\n\t" \
3281 VALGRIND_CFI_EPILOGUE \
3282 : /*out*/ "=d" (_res) \
3283 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3284 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3285 ); \
3286 lval = (__typeof__(lval)) _res; \
3287 } while (0)
3288
3289#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
3290 do { \
3291 volatile OrigFn _orig = (orig); \
3292 volatile unsigned long _argvec[4]; \
3293 volatile unsigned long _res; \
3294 _argvec[0] = (unsigned long)_orig.nraddr; \
3295 _argvec[1] = (unsigned long)arg1; \
3296 _argvec[2] = (unsigned long)arg2; \
3297 _argvec[3] = (unsigned long)arg3; \
3298 __asm__ volatile( \
3299 VALGRIND_CFI_PROLOGUE \
3300 "aghi 15,-160\n\t" \
3301 "lg 2, 8(1)\n\t" \
3302 "lg 3,16(1)\n\t" \
3303 "lg 4,24(1)\n\t" \
3304 "lg 1, 0(1)\n\t" \
3305 VALGRIND_CALL_NOREDIR_R1 \
3306 "lgr %0, 2\n\t" \
3307 "aghi 15,160\n\t" \
3308 VALGRIND_CFI_EPILOGUE \
3309 : /*out*/ "=d" (_res) \
3310 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3311 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3312 ); \
3313 lval = (__typeof__(lval)) _res; \
3314 } while (0)
3315
3316#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
3317 do { \
3318 volatile OrigFn _orig = (orig); \
3319 volatile unsigned long _argvec[5]; \
3320 volatile unsigned long _res; \
3321 _argvec[0] = (unsigned long)_orig.nraddr; \
3322 _argvec[1] = (unsigned long)arg1; \
3323 _argvec[2] = (unsigned long)arg2; \
3324 _argvec[3] = (unsigned long)arg3; \
3325 _argvec[4] = (unsigned long)arg4; \
3326 __asm__ volatile( \
3327 VALGRIND_CFI_PROLOGUE \
3328 "aghi 15,-160\n\t" \
3329 "lg 2, 8(1)\n\t" \
3330 "lg 3,16(1)\n\t" \
3331 "lg 4,24(1)\n\t" \
3332 "lg 5,32(1)\n\t" \
3333 "lg 1, 0(1)\n\t" \
3334 VALGRIND_CALL_NOREDIR_R1 \
3335 "lgr %0, 2\n\t" \
3336 "aghi 15,160\n\t" \
3337 VALGRIND_CFI_EPILOGUE \
3338 : /*out*/ "=d" (_res) \
3339 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3340 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3341 ); \
3342 lval = (__typeof__(lval)) _res; \
3343 } while (0)
3344
3345#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
3346 do { \
3347 volatile OrigFn _orig = (orig); \
3348 volatile unsigned long _argvec[6]; \
3349 volatile unsigned long _res; \
3350 _argvec[0] = (unsigned long)_orig.nraddr; \
3351 _argvec[1] = (unsigned long)arg1; \
3352 _argvec[2] = (unsigned long)arg2; \
3353 _argvec[3] = (unsigned long)arg3; \
3354 _argvec[4] = (unsigned long)arg4; \
3355 _argvec[5] = (unsigned long)arg5; \
3356 __asm__ volatile( \
3357 VALGRIND_CFI_PROLOGUE \
3358 "aghi 15,-160\n\t" \
3359 "lg 2, 8(1)\n\t" \
3360 "lg 3,16(1)\n\t" \
3361 "lg 4,24(1)\n\t" \
3362 "lg 5,32(1)\n\t" \
3363 "lg 6,40(1)\n\t" \
3364 "lg 1, 0(1)\n\t" \
3365 VALGRIND_CALL_NOREDIR_R1 \
3366 "lgr %0, 2\n\t" \
3367 "aghi 15,160\n\t" \
3368 VALGRIND_CFI_EPILOGUE \
3369 : /*out*/ "=d" (_res) \
3370 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3371 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3372 ); \
3373 lval = (__typeof__(lval)) _res; \
3374 } while (0)
3375
3376#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3377 arg6) \
3378 do { \
3379 volatile OrigFn _orig = (orig); \
3380 volatile unsigned long _argvec[7]; \
3381 volatile unsigned long _res; \
3382 _argvec[0] = (unsigned long)_orig.nraddr; \
3383 _argvec[1] = (unsigned long)arg1; \
3384 _argvec[2] = (unsigned long)arg2; \
3385 _argvec[3] = (unsigned long)arg3; \
3386 _argvec[4] = (unsigned long)arg4; \
3387 _argvec[5] = (unsigned long)arg5; \
3388 _argvec[6] = (unsigned long)arg6; \
3389 __asm__ volatile( \
3390 VALGRIND_CFI_PROLOGUE \
3391 "aghi 15,-168\n\t" \
3392 "lg 2, 8(1)\n\t" \
3393 "lg 3,16(1)\n\t" \
3394 "lg 4,24(1)\n\t" \
3395 "lg 5,32(1)\n\t" \
3396 "lg 6,40(1)\n\t" \
3397 "mvc 160(8,15), 48(1)\n\t" \
3398 "lg 1, 0(1)\n\t" \
3399 VALGRIND_CALL_NOREDIR_R1 \
3400 "lgr %0, 2\n\t" \
3401 "aghi 15,168\n\t" \
3402 VALGRIND_CFI_EPILOGUE \
3403 : /*out*/ "=d" (_res) \
3404 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3405 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3406 ); \
3407 lval = (__typeof__(lval)) _res; \
3408 } while (0)
3409
3410#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3411 arg6, arg7) \
3412 do { \
3413 volatile OrigFn _orig = (orig); \
3414 volatile unsigned long _argvec[8]; \
3415 volatile unsigned long _res; \
3416 _argvec[0] = (unsigned long)_orig.nraddr; \
3417 _argvec[1] = (unsigned long)arg1; \
3418 _argvec[2] = (unsigned long)arg2; \
3419 _argvec[3] = (unsigned long)arg3; \
3420 _argvec[4] = (unsigned long)arg4; \
3421 _argvec[5] = (unsigned long)arg5; \
3422 _argvec[6] = (unsigned long)arg6; \
3423 _argvec[7] = (unsigned long)arg7; \
3424 __asm__ volatile( \
3425 VALGRIND_CFI_PROLOGUE \
3426 "aghi 15,-176\n\t" \
3427 "lg 2, 8(1)\n\t" \
3428 "lg 3,16(1)\n\t" \
3429 "lg 4,24(1)\n\t" \
3430 "lg 5,32(1)\n\t" \
3431 "lg 6,40(1)\n\t" \
3432 "mvc 160(8,15), 48(1)\n\t" \
3433 "mvc 168(8,15), 56(1)\n\t" \
3434 "lg 1, 0(1)\n\t" \
3435 VALGRIND_CALL_NOREDIR_R1 \
3436 "lgr %0, 2\n\t" \
3437 "aghi 15,176\n\t" \
3438 VALGRIND_CFI_EPILOGUE \
3439 : /*out*/ "=d" (_res) \
3440 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3441 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3442 ); \
3443 lval = (__typeof__(lval)) _res; \
3444 } while (0)
3445
3446#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3447 arg6, arg7 ,arg8) \
3448 do { \
3449 volatile OrigFn _orig = (orig); \
3450 volatile unsigned long _argvec[9]; \
3451 volatile unsigned long _res; \
3452 _argvec[0] = (unsigned long)_orig.nraddr; \
3453 _argvec[1] = (unsigned long)arg1; \
3454 _argvec[2] = (unsigned long)arg2; \
3455 _argvec[3] = (unsigned long)arg3; \
3456 _argvec[4] = (unsigned long)arg4; \
3457 _argvec[5] = (unsigned long)arg5; \
3458 _argvec[6] = (unsigned long)arg6; \
3459 _argvec[7] = (unsigned long)arg7; \
3460 _argvec[8] = (unsigned long)arg8; \
3461 __asm__ volatile( \
3462 VALGRIND_CFI_PROLOGUE \
3463 "aghi 15,-184\n\t" \
3464 "lg 2, 8(1)\n\t" \
3465 "lg 3,16(1)\n\t" \
3466 "lg 4,24(1)\n\t" \
3467 "lg 5,32(1)\n\t" \
3468 "lg 6,40(1)\n\t" \
3469 "mvc 160(8,15), 48(1)\n\t" \
3470 "mvc 168(8,15), 56(1)\n\t" \
3471 "mvc 176(8,15), 64(1)\n\t" \
3472 "lg 1, 0(1)\n\t" \
3473 VALGRIND_CALL_NOREDIR_R1 \
3474 "lgr %0, 2\n\t" \
3475 "aghi 15,184\n\t" \
3476 VALGRIND_CFI_EPILOGUE \
3477 : /*out*/ "=d" (_res) \
3478 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3479 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3480 ); \
3481 lval = (__typeof__(lval)) _res; \
3482 } while (0)
3483
3484#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3485 arg6, arg7 ,arg8, arg9) \
3486 do { \
3487 volatile OrigFn _orig = (orig); \
3488 volatile unsigned long _argvec[10]; \
3489 volatile unsigned long _res; \
3490 _argvec[0] = (unsigned long)_orig.nraddr; \
3491 _argvec[1] = (unsigned long)arg1; \
3492 _argvec[2] = (unsigned long)arg2; \
3493 _argvec[3] = (unsigned long)arg3; \
3494 _argvec[4] = (unsigned long)arg4; \
3495 _argvec[5] = (unsigned long)arg5; \
3496 _argvec[6] = (unsigned long)arg6; \
3497 _argvec[7] = (unsigned long)arg7; \
3498 _argvec[8] = (unsigned long)arg8; \
3499 _argvec[9] = (unsigned long)arg9; \
3500 __asm__ volatile( \
3501 VALGRIND_CFI_PROLOGUE \
3502 "aghi 15,-192\n\t" \
3503 "lg 2, 8(1)\n\t" \
3504 "lg 3,16(1)\n\t" \
3505 "lg 4,24(1)\n\t" \
3506 "lg 5,32(1)\n\t" \
3507 "lg 6,40(1)\n\t" \
3508 "mvc 160(8,15), 48(1)\n\t" \
3509 "mvc 168(8,15), 56(1)\n\t" \
3510 "mvc 176(8,15), 64(1)\n\t" \
3511 "mvc 184(8,15), 72(1)\n\t" \
3512 "lg 1, 0(1)\n\t" \
3513 VALGRIND_CALL_NOREDIR_R1 \
3514 "lgr %0, 2\n\t" \
3515 "aghi 15,192\n\t" \
3516 VALGRIND_CFI_EPILOGUE \
3517 : /*out*/ "=d" (_res) \
3518 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3519 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3520 ); \
3521 lval = (__typeof__(lval)) _res; \
3522 } while (0)
3523
3524#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3525 arg6, arg7 ,arg8, arg9, arg10) \
3526 do { \
3527 volatile OrigFn _orig = (orig); \
3528 volatile unsigned long _argvec[11]; \
3529 volatile unsigned long _res; \
3530 _argvec[0] = (unsigned long)_orig.nraddr; \
3531 _argvec[1] = (unsigned long)arg1; \
3532 _argvec[2] = (unsigned long)arg2; \
3533 _argvec[3] = (unsigned long)arg3; \
3534 _argvec[4] = (unsigned long)arg4; \
3535 _argvec[5] = (unsigned long)arg5; \
3536 _argvec[6] = (unsigned long)arg6; \
3537 _argvec[7] = (unsigned long)arg7; \
3538 _argvec[8] = (unsigned long)arg8; \
3539 _argvec[9] = (unsigned long)arg9; \
3540 _argvec[10] = (unsigned long)arg10; \
3541 __asm__ volatile( \
3542 VALGRIND_CFI_PROLOGUE \
3543 "aghi 15,-200\n\t" \
3544 "lg 2, 8(1)\n\t" \
3545 "lg 3,16(1)\n\t" \
3546 "lg 4,24(1)\n\t" \
3547 "lg 5,32(1)\n\t" \
3548 "lg 6,40(1)\n\t" \
3549 "mvc 160(8,15), 48(1)\n\t" \
3550 "mvc 168(8,15), 56(1)\n\t" \
3551 "mvc 176(8,15), 64(1)\n\t" \
3552 "mvc 184(8,15), 72(1)\n\t" \
3553 "mvc 192(8,15), 80(1)\n\t" \
3554 "lg 1, 0(1)\n\t" \
3555 VALGRIND_CALL_NOREDIR_R1 \
3556 "lgr %0, 2\n\t" \
3557 "aghi 15,200\n\t" \
3558 VALGRIND_CFI_EPILOGUE \
3559 : /*out*/ "=d" (_res) \
3560 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3561 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3562 ); \
3563 lval = (__typeof__(lval)) _res; \
3564 } while (0)
3565
3566#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3567 arg6, arg7 ,arg8, arg9, arg10, arg11) \
3568 do { \
3569 volatile OrigFn _orig = (orig); \
3570 volatile unsigned long _argvec[12]; \
3571 volatile unsigned long _res; \
3572 _argvec[0] = (unsigned long)_orig.nraddr; \
3573 _argvec[1] = (unsigned long)arg1; \
3574 _argvec[2] = (unsigned long)arg2; \
3575 _argvec[3] = (unsigned long)arg3; \
3576 _argvec[4] = (unsigned long)arg4; \
3577 _argvec[5] = (unsigned long)arg5; \
3578 _argvec[6] = (unsigned long)arg6; \
3579 _argvec[7] = (unsigned long)arg7; \
3580 _argvec[8] = (unsigned long)arg8; \
3581 _argvec[9] = (unsigned long)arg9; \
3582 _argvec[10] = (unsigned long)arg10; \
3583 _argvec[11] = (unsigned long)arg11; \
3584 __asm__ volatile( \
3585 VALGRIND_CFI_PROLOGUE \
3586 "aghi 15,-208\n\t" \
3587 "lg 2, 8(1)\n\t" \
3588 "lg 3,16(1)\n\t" \
3589 "lg 4,24(1)\n\t" \
3590 "lg 5,32(1)\n\t" \
3591 "lg 6,40(1)\n\t" \
3592 "mvc 160(8,15), 48(1)\n\t" \
3593 "mvc 168(8,15), 56(1)\n\t" \
3594 "mvc 176(8,15), 64(1)\n\t" \
3595 "mvc 184(8,15), 72(1)\n\t" \
3596 "mvc 192(8,15), 80(1)\n\t" \
3597 "mvc 200(8,15), 88(1)\n\t" \
3598 "lg 1, 0(1)\n\t" \
3599 VALGRIND_CALL_NOREDIR_R1 \
3600 "lgr %0, 2\n\t" \
3601 "aghi 15,208\n\t" \
3602 VALGRIND_CFI_EPILOGUE \
3603 : /*out*/ "=d" (_res) \
3604 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3605 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3606 ); \
3607 lval = (__typeof__(lval)) _res; \
3608 } while (0)
3609
3610#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3611 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
3612 do { \
3613 volatile OrigFn _orig = (orig); \
3614 volatile unsigned long _argvec[13]; \
3615 volatile unsigned long _res; \
3616 _argvec[0] = (unsigned long)_orig.nraddr; \
3617 _argvec[1] = (unsigned long)arg1; \
3618 _argvec[2] = (unsigned long)arg2; \
3619 _argvec[3] = (unsigned long)arg3; \
3620 _argvec[4] = (unsigned long)arg4; \
3621 _argvec[5] = (unsigned long)arg5; \
3622 _argvec[6] = (unsigned long)arg6; \
3623 _argvec[7] = (unsigned long)arg7; \
3624 _argvec[8] = (unsigned long)arg8; \
3625 _argvec[9] = (unsigned long)arg9; \
3626 _argvec[10] = (unsigned long)arg10; \
3627 _argvec[11] = (unsigned long)arg11; \
3628 _argvec[12] = (unsigned long)arg12; \
3629 __asm__ volatile( \
3630 VALGRIND_CFI_PROLOGUE \
3631 "aghi 15,-216\n\t" \
3632 "lg 2, 8(1)\n\t" \
3633 "lg 3,16(1)\n\t" \
3634 "lg 4,24(1)\n\t" \
3635 "lg 5,32(1)\n\t" \
3636 "lg 6,40(1)\n\t" \
3637 "mvc 160(8,15), 48(1)\n\t" \
3638 "mvc 168(8,15), 56(1)\n\t" \
3639 "mvc 176(8,15), 64(1)\n\t" \
3640 "mvc 184(8,15), 72(1)\n\t" \
3641 "mvc 192(8,15), 80(1)\n\t" \
3642 "mvc 200(8,15), 88(1)\n\t" \
3643 "mvc 208(8,15), 96(1)\n\t" \
3644 "lg 1, 0(1)\n\t" \
3645 VALGRIND_CALL_NOREDIR_R1 \
3646 "lgr %0, 2\n\t" \
3647 "aghi 15,216\n\t" \
3648 VALGRIND_CFI_EPILOGUE \
3649 : /*out*/ "=d" (_res) \
3650 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3651 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3652 ); \
3653 lval = (__typeof__(lval)) _res; \
3654 } while (0)
3655
3656
3657#endif /* PLAT_s390x_linux */
3658
sewardj5db15402012-06-07 09:13:21 +00003659/* ------------------------- mips-linux ------------------------- */
3660
3661#if defined(PLAT_mips32_linux)
3662
3663/* These regs are trashed by the hidden call. */
3664#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
3665"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
3666"$25", "$31"
3667
3668/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
3669 long) == 4. */
3670
3671#define CALL_FN_W_v(lval, orig) \
3672 do { \
3673 volatile OrigFn _orig = (orig); \
3674 volatile unsigned long _argvec[1]; \
3675 volatile unsigned long _res; \
3676 _argvec[0] = (unsigned long)_orig.nraddr; \
3677 __asm__ volatile( \
3678 "subu $29, $29, 8 \n\t" \
3679 "sw $gp, 0($sp) \n\t" \
3680 "sw $ra, 4($sp) \n\t" \
3681 "subu $29, $29, 16 \n\t" \
3682 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3683 VALGRIND_CALL_NOREDIR_T9 \
3684 "addu $29, $29, 16\n\t" \
3685 "lw $gp, 0($sp) \n\t" \
3686 "lw $ra, 4($sp) \n\t" \
3687 "addu $29, $29, 8 \n\t" \
3688 "move %0, $v0\n" \
3689 : /*out*/ "=r" (_res) \
3690 : /*in*/ "0" (&_argvec[0]) \
3691 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3692 ); \
3693 lval = (__typeof__(lval)) _res; \
3694 } while (0)
3695
3696#define CALL_FN_W_W(lval, orig, arg1) \
3697 do { \
3698 volatile OrigFn _orig = (orig); \
3699 volatile unsigned long _argvec[2]; \
3700 volatile unsigned long _res; \
3701 _argvec[0] = (unsigned long)_orig.nraddr; \
3702 _argvec[1] = (unsigned long)(arg1); \
3703 __asm__ volatile( \
3704 "subu $29, $29, 8 \n\t" \
3705 "sw $gp, 0($sp) \n\t" \
3706 "sw $ra, 4($sp) \n\t" \
3707 "subu $29, $29, 16 \n\t" \
3708 "lw $a0, 4(%1) \n\t" /* arg1*/ \
3709 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3710 VALGRIND_CALL_NOREDIR_T9 \
3711 "addu $29, $29, 16 \n\t" \
3712 "lw $gp, 0($sp) \n\t" \
3713 "lw $ra, 4($sp) \n\t" \
3714 "addu $29, $29, 8 \n\t" \
3715 "move %0, $v0\n" \
3716 : /*out*/ "=r" (_res) \
3717 : /*in*/ "0" (&_argvec[0]) \
3718 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3719 ); \
3720 lval = (__typeof__(lval)) _res; \
3721 } while (0)
3722
3723#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3724 do { \
3725 volatile OrigFn _orig = (orig); \
3726 volatile unsigned long _argvec[3]; \
3727 volatile unsigned long _res; \
3728 _argvec[0] = (unsigned long)_orig.nraddr; \
3729 _argvec[1] = (unsigned long)(arg1); \
3730 _argvec[2] = (unsigned long)(arg2); \
3731 __asm__ volatile( \
3732 "subu $29, $29, 8 \n\t" \
3733 "sw $gp, 0($sp) \n\t" \
3734 "sw $ra, 4($sp) \n\t" \
3735 "subu $29, $29, 16 \n\t" \
3736 "lw $a0, 4(%1) \n\t" \
3737 "lw $a1, 8(%1) \n\t" \
3738 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3739 VALGRIND_CALL_NOREDIR_T9 \
3740 "addu $29, $29, 16 \n\t" \
3741 "lw $gp, 0($sp) \n\t" \
3742 "lw $ra, 4($sp) \n\t" \
3743 "addu $29, $29, 8 \n\t" \
3744 "move %0, $v0\n" \
3745 : /*out*/ "=r" (_res) \
3746 : /*in*/ "0" (&_argvec[0]) \
3747 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3748 ); \
3749 lval = (__typeof__(lval)) _res; \
3750 } while (0)
3751
3752#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3753 do { \
3754 volatile OrigFn _orig = (orig); \
3755 volatile unsigned long _argvec[4]; \
3756 volatile unsigned long _res; \
3757 _argvec[0] = (unsigned long)_orig.nraddr; \
3758 _argvec[1] = (unsigned long)(arg1); \
3759 _argvec[2] = (unsigned long)(arg2); \
3760 _argvec[3] = (unsigned long)(arg3); \
3761 __asm__ volatile( \
3762 "subu $29, $29, 8 \n\t" \
3763 "sw $gp, 0($sp) \n\t" \
3764 "sw $ra, 4($sp) \n\t" \
3765 "subu $29, $29, 16 \n\t" \
3766 "lw $a0, 4(%1) \n\t" \
3767 "lw $a1, 8(%1) \n\t" \
3768 "lw $a2, 12(%1) \n\t" \
3769 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3770 VALGRIND_CALL_NOREDIR_T9 \
3771 "addu $29, $29, 16 \n\t" \
3772 "lw $gp, 0($sp) \n\t" \
3773 "lw $ra, 4($sp) \n\t" \
3774 "addu $29, $29, 8 \n\t" \
3775 "move %0, $v0\n" \
3776 : /*out*/ "=r" (_res) \
3777 : /*in*/ "0" (&_argvec[0]) \
3778 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3779 ); \
3780 lval = (__typeof__(lval)) _res; \
3781 } while (0)
3782
3783#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3784 do { \
3785 volatile OrigFn _orig = (orig); \
3786 volatile unsigned long _argvec[5]; \
3787 volatile unsigned long _res; \
3788 _argvec[0] = (unsigned long)_orig.nraddr; \
3789 _argvec[1] = (unsigned long)(arg1); \
3790 _argvec[2] = (unsigned long)(arg2); \
3791 _argvec[3] = (unsigned long)(arg3); \
3792 _argvec[4] = (unsigned long)(arg4); \
3793 __asm__ volatile( \
3794 "subu $29, $29, 8 \n\t" \
3795 "sw $gp, 0($sp) \n\t" \
3796 "sw $ra, 4($sp) \n\t" \
3797 "subu $29, $29, 16 \n\t" \
3798 "lw $a0, 4(%1) \n\t" \
3799 "lw $a1, 8(%1) \n\t" \
3800 "lw $a2, 12(%1) \n\t" \
3801 "lw $a3, 16(%1) \n\t" \
3802 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3803 VALGRIND_CALL_NOREDIR_T9 \
3804 "addu $29, $29, 16 \n\t" \
3805 "lw $gp, 0($sp) \n\t" \
3806 "lw $ra, 4($sp) \n\t" \
3807 "addu $29, $29, 8 \n\t" \
3808 "move %0, $v0\n" \
3809 : /*out*/ "=r" (_res) \
3810 : /*in*/ "0" (&_argvec[0]) \
3811 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3812 ); \
3813 lval = (__typeof__(lval)) _res; \
3814 } while (0)
3815
3816#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3817 do { \
3818 volatile OrigFn _orig = (orig); \
3819 volatile unsigned long _argvec[6]; \
3820 volatile unsigned long _res; \
3821 _argvec[0] = (unsigned long)_orig.nraddr; \
3822 _argvec[1] = (unsigned long)(arg1); \
3823 _argvec[2] = (unsigned long)(arg2); \
3824 _argvec[3] = (unsigned long)(arg3); \
3825 _argvec[4] = (unsigned long)(arg4); \
3826 _argvec[5] = (unsigned long)(arg5); \
3827 __asm__ volatile( \
3828 "subu $29, $29, 8 \n\t" \
3829 "sw $gp, 0($sp) \n\t" \
3830 "sw $ra, 4($sp) \n\t" \
3831 "lw $a0, 20(%1) \n\t" \
3832 "subu $sp, $sp, 24\n\t" \
3833 "sw $a0, 16($sp) \n\t" \
3834 "lw $a0, 4(%1) \n\t" \
3835 "lw $a1, 8(%1) \n\t" \
3836 "lw $a2, 12(%1) \n\t" \
3837 "lw $a3, 16(%1) \n\t" \
3838 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3839 VALGRIND_CALL_NOREDIR_T9 \
3840 "addu $29, $29, 24 \n\t" \
3841 "lw $gp, 0($sp) \n\t" \
3842 "lw $ra, 4($sp) \n\t" \
3843 "addu $sp, $sp, 8 \n\t" \
3844 "move %0, $v0\n" \
3845 : /*out*/ "=r" (_res) \
3846 : /*in*/ "0" (&_argvec[0]) \
3847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3848 ); \
3849 lval = (__typeof__(lval)) _res; \
3850 } while (0)
3851#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3852 do { \
3853 volatile OrigFn _orig = (orig); \
3854 volatile unsigned long _argvec[7]; \
3855 volatile unsigned long _res; \
3856 _argvec[0] = (unsigned long)_orig.nraddr; \
3857 _argvec[1] = (unsigned long)(arg1); \
3858 _argvec[2] = (unsigned long)(arg2); \
3859 _argvec[3] = (unsigned long)(arg3); \
3860 _argvec[4] = (unsigned long)(arg4); \
3861 _argvec[5] = (unsigned long)(arg5); \
3862 _argvec[6] = (unsigned long)(arg6); \
3863 __asm__ volatile( \
3864 "subu $29, $29, 8 \n\t" \
3865 "sw $gp, 0($sp) \n\t" \
3866 "sw $ra, 4($sp) \n\t" \
3867 "lw $a0, 20(%1) \n\t" \
3868 "subu $sp, $sp, 32\n\t" \
3869 "sw $a0, 16($sp) \n\t" \
3870 "lw $a0, 24(%1) \n\t" \
3871 "nop\n\t" \
3872 "sw $a0, 20($sp) \n\t" \
3873 "lw $a0, 4(%1) \n\t" \
3874 "lw $a1, 8(%1) \n\t" \
3875 "lw $a2, 12(%1) \n\t" \
3876 "lw $a3, 16(%1) \n\t" \
3877 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3878 VALGRIND_CALL_NOREDIR_T9 \
3879 "addu $sp, $sp, 32 \n\t" \
3880 "lw $gp, 0($sp) \n\t" \
3881 "lw $ra, 4($sp) \n\t" \
3882 "addu $sp, $sp, 8 \n\t" \
3883 "move %0, $v0\n" \
3884 : /*out*/ "=r" (_res) \
3885 : /*in*/ "0" (&_argvec[0]) \
3886 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3887 ); \
3888 lval = (__typeof__(lval)) _res; \
3889 } while (0)
3890
3891#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3892 arg7) \
3893 do { \
3894 volatile OrigFn _orig = (orig); \
3895 volatile unsigned long _argvec[8]; \
3896 volatile unsigned long _res; \
3897 _argvec[0] = (unsigned long)_orig.nraddr; \
3898 _argvec[1] = (unsigned long)(arg1); \
3899 _argvec[2] = (unsigned long)(arg2); \
3900 _argvec[3] = (unsigned long)(arg3); \
3901 _argvec[4] = (unsigned long)(arg4); \
3902 _argvec[5] = (unsigned long)(arg5); \
3903 _argvec[6] = (unsigned long)(arg6); \
3904 _argvec[7] = (unsigned long)(arg7); \
3905 __asm__ volatile( \
3906 "subu $29, $29, 8 \n\t" \
3907 "sw $gp, 0($sp) \n\t" \
3908 "sw $ra, 4($sp) \n\t" \
3909 "lw $a0, 20(%1) \n\t" \
3910 "subu $sp, $sp, 32\n\t" \
3911 "sw $a0, 16($sp) \n\t" \
3912 "lw $a0, 24(%1) \n\t" \
3913 "sw $a0, 20($sp) \n\t" \
3914 "lw $a0, 28(%1) \n\t" \
3915 "sw $a0, 24($sp) \n\t" \
3916 "lw $a0, 4(%1) \n\t" \
3917 "lw $a1, 8(%1) \n\t" \
3918 "lw $a2, 12(%1) \n\t" \
3919 "lw $a3, 16(%1) \n\t" \
3920 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3921 VALGRIND_CALL_NOREDIR_T9 \
3922 "addu $sp, $sp, 32 \n\t" \
3923 "lw $gp, 0($sp) \n\t" \
3924 "lw $ra, 4($sp) \n\t" \
3925 "addu $sp, $sp, 8 \n\t" \
3926 "move %0, $v0\n" \
3927 : /*out*/ "=r" (_res) \
3928 : /*in*/ "0" (&_argvec[0]) \
3929 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3930 ); \
3931 lval = (__typeof__(lval)) _res; \
3932 } while (0)
3933
3934#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3935 arg7,arg8) \
3936 do { \
3937 volatile OrigFn _orig = (orig); \
3938 volatile unsigned long _argvec[9]; \
3939 volatile unsigned long _res; \
3940 _argvec[0] = (unsigned long)_orig.nraddr; \
3941 _argvec[1] = (unsigned long)(arg1); \
3942 _argvec[2] = (unsigned long)(arg2); \
3943 _argvec[3] = (unsigned long)(arg3); \
3944 _argvec[4] = (unsigned long)(arg4); \
3945 _argvec[5] = (unsigned long)(arg5); \
3946 _argvec[6] = (unsigned long)(arg6); \
3947 _argvec[7] = (unsigned long)(arg7); \
3948 _argvec[8] = (unsigned long)(arg8); \
3949 __asm__ volatile( \
3950 "subu $29, $29, 8 \n\t" \
3951 "sw $gp, 0($sp) \n\t" \
3952 "sw $ra, 4($sp) \n\t" \
3953 "lw $a0, 20(%1) \n\t" \
3954 "subu $sp, $sp, 40\n\t" \
3955 "sw $a0, 16($sp) \n\t" \
3956 "lw $a0, 24(%1) \n\t" \
3957 "sw $a0, 20($sp) \n\t" \
3958 "lw $a0, 28(%1) \n\t" \
3959 "sw $a0, 24($sp) \n\t" \
3960 "lw $a0, 32(%1) \n\t" \
3961 "sw $a0, 28($sp) \n\t" \
3962 "lw $a0, 4(%1) \n\t" \
3963 "lw $a1, 8(%1) \n\t" \
3964 "lw $a2, 12(%1) \n\t" \
3965 "lw $a3, 16(%1) \n\t" \
3966 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3967 VALGRIND_CALL_NOREDIR_T9 \
3968 "addu $sp, $sp, 40 \n\t" \
3969 "lw $gp, 0($sp) \n\t" \
3970 "lw $ra, 4($sp) \n\t" \
3971 "addu $sp, $sp, 8 \n\t" \
3972 "move %0, $v0\n" \
3973 : /*out*/ "=r" (_res) \
3974 : /*in*/ "0" (&_argvec[0]) \
3975 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3976 ); \
3977 lval = (__typeof__(lval)) _res; \
3978 } while (0)
3979
3980#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3981 arg7,arg8,arg9) \
3982 do { \
3983 volatile OrigFn _orig = (orig); \
3984 volatile unsigned long _argvec[10]; \
3985 volatile unsigned long _res; \
3986 _argvec[0] = (unsigned long)_orig.nraddr; \
3987 _argvec[1] = (unsigned long)(arg1); \
3988 _argvec[2] = (unsigned long)(arg2); \
3989 _argvec[3] = (unsigned long)(arg3); \
3990 _argvec[4] = (unsigned long)(arg4); \
3991 _argvec[5] = (unsigned long)(arg5); \
3992 _argvec[6] = (unsigned long)(arg6); \
3993 _argvec[7] = (unsigned long)(arg7); \
3994 _argvec[8] = (unsigned long)(arg8); \
3995 _argvec[9] = (unsigned long)(arg9); \
3996 __asm__ volatile( \
3997 "subu $29, $29, 8 \n\t" \
3998 "sw $gp, 0($sp) \n\t" \
3999 "sw $ra, 4($sp) \n\t" \
4000 "lw $a0, 20(%1) \n\t" \
4001 "subu $sp, $sp, 40\n\t" \
4002 "sw $a0, 16($sp) \n\t" \
4003 "lw $a0, 24(%1) \n\t" \
4004 "sw $a0, 20($sp) \n\t" \
4005 "lw $a0, 28(%1) \n\t" \
4006 "sw $a0, 24($sp) \n\t" \
4007 "lw $a0, 32(%1) \n\t" \
4008 "sw $a0, 28($sp) \n\t" \
4009 "lw $a0, 36(%1) \n\t" \
4010 "sw $a0, 32($sp) \n\t" \
4011 "lw $a0, 4(%1) \n\t" \
4012 "lw $a1, 8(%1) \n\t" \
4013 "lw $a2, 12(%1) \n\t" \
4014 "lw $a3, 16(%1) \n\t" \
4015 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4016 VALGRIND_CALL_NOREDIR_T9 \
4017 "addu $sp, $sp, 40 \n\t" \
4018 "lw $gp, 0($sp) \n\t" \
4019 "lw $ra, 4($sp) \n\t" \
4020 "addu $sp, $sp, 8 \n\t" \
4021 "move %0, $v0\n" \
4022 : /*out*/ "=r" (_res) \
4023 : /*in*/ "0" (&_argvec[0]) \
4024 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4025 ); \
4026 lval = (__typeof__(lval)) _res; \
4027 } while (0)
4028
4029#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4030 arg7,arg8,arg9,arg10) \
4031 do { \
4032 volatile OrigFn _orig = (orig); \
4033 volatile unsigned long _argvec[11]; \
4034 volatile unsigned long _res; \
4035 _argvec[0] = (unsigned long)_orig.nraddr; \
4036 _argvec[1] = (unsigned long)(arg1); \
4037 _argvec[2] = (unsigned long)(arg2); \
4038 _argvec[3] = (unsigned long)(arg3); \
4039 _argvec[4] = (unsigned long)(arg4); \
4040 _argvec[5] = (unsigned long)(arg5); \
4041 _argvec[6] = (unsigned long)(arg6); \
4042 _argvec[7] = (unsigned long)(arg7); \
4043 _argvec[8] = (unsigned long)(arg8); \
4044 _argvec[9] = (unsigned long)(arg9); \
4045 _argvec[10] = (unsigned long)(arg10); \
4046 __asm__ volatile( \
4047 "subu $29, $29, 8 \n\t" \
4048 "sw $gp, 0($sp) \n\t" \
4049 "sw $ra, 4($sp) \n\t" \
4050 "lw $a0, 20(%1) \n\t" \
4051 "subu $sp, $sp, 48\n\t" \
4052 "sw $a0, 16($sp) \n\t" \
4053 "lw $a0, 24(%1) \n\t" \
4054 "sw $a0, 20($sp) \n\t" \
4055 "lw $a0, 28(%1) \n\t" \
4056 "sw $a0, 24($sp) \n\t" \
4057 "lw $a0, 32(%1) \n\t" \
4058 "sw $a0, 28($sp) \n\t" \
4059 "lw $a0, 36(%1) \n\t" \
4060 "sw $a0, 32($sp) \n\t" \
4061 "lw $a0, 40(%1) \n\t" \
4062 "sw $a0, 36($sp) \n\t" \
4063 "lw $a0, 4(%1) \n\t" \
4064 "lw $a1, 8(%1) \n\t" \
4065 "lw $a2, 12(%1) \n\t" \
4066 "lw $a3, 16(%1) \n\t" \
4067 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4068 VALGRIND_CALL_NOREDIR_T9 \
4069 "addu $sp, $sp, 48 \n\t" \
4070 "lw $gp, 0($sp) \n\t" \
4071 "lw $ra, 4($sp) \n\t" \
4072 "addu $sp, $sp, 8 \n\t" \
4073 "move %0, $v0\n" \
4074 : /*out*/ "=r" (_res) \
4075 : /*in*/ "0" (&_argvec[0]) \
4076 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4077 ); \
4078 lval = (__typeof__(lval)) _res; \
4079 } while (0)
4080
4081#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4082 arg6,arg7,arg8,arg9,arg10, \
4083 arg11) \
4084 do { \
4085 volatile OrigFn _orig = (orig); \
4086 volatile unsigned long _argvec[12]; \
4087 volatile unsigned long _res; \
4088 _argvec[0] = (unsigned long)_orig.nraddr; \
4089 _argvec[1] = (unsigned long)(arg1); \
4090 _argvec[2] = (unsigned long)(arg2); \
4091 _argvec[3] = (unsigned long)(arg3); \
4092 _argvec[4] = (unsigned long)(arg4); \
4093 _argvec[5] = (unsigned long)(arg5); \
4094 _argvec[6] = (unsigned long)(arg6); \
4095 _argvec[7] = (unsigned long)(arg7); \
4096 _argvec[8] = (unsigned long)(arg8); \
4097 _argvec[9] = (unsigned long)(arg9); \
4098 _argvec[10] = (unsigned long)(arg10); \
4099 _argvec[11] = (unsigned long)(arg11); \
4100 __asm__ volatile( \
4101 "subu $29, $29, 8 \n\t" \
4102 "sw $gp, 0($sp) \n\t" \
4103 "sw $ra, 4($sp) \n\t" \
4104 "lw $a0, 20(%1) \n\t" \
4105 "subu $sp, $sp, 48\n\t" \
4106 "sw $a0, 16($sp) \n\t" \
4107 "lw $a0, 24(%1) \n\t" \
4108 "sw $a0, 20($sp) \n\t" \
4109 "lw $a0, 28(%1) \n\t" \
4110 "sw $a0, 24($sp) \n\t" \
4111 "lw $a0, 32(%1) \n\t" \
4112 "sw $a0, 28($sp) \n\t" \
4113 "lw $a0, 36(%1) \n\t" \
4114 "sw $a0, 32($sp) \n\t" \
4115 "lw $a0, 40(%1) \n\t" \
4116 "sw $a0, 36($sp) \n\t" \
4117 "lw $a0, 44(%1) \n\t" \
4118 "sw $a0, 40($sp) \n\t" \
4119 "lw $a0, 4(%1) \n\t" \
4120 "lw $a1, 8(%1) \n\t" \
4121 "lw $a2, 12(%1) \n\t" \
4122 "lw $a3, 16(%1) \n\t" \
4123 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4124 VALGRIND_CALL_NOREDIR_T9 \
4125 "addu $sp, $sp, 48 \n\t" \
4126 "lw $gp, 0($sp) \n\t" \
4127 "lw $ra, 4($sp) \n\t" \
4128 "addu $sp, $sp, 8 \n\t" \
4129 "move %0, $v0\n" \
4130 : /*out*/ "=r" (_res) \
4131 : /*in*/ "0" (&_argvec[0]) \
4132 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4133 ); \
4134 lval = (__typeof__(lval)) _res; \
4135 } while (0)
4136
4137#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4138 arg6,arg7,arg8,arg9,arg10, \
4139 arg11,arg12) \
4140 do { \
4141 volatile OrigFn _orig = (orig); \
4142 volatile unsigned long _argvec[13]; \
4143 volatile unsigned long _res; \
4144 _argvec[0] = (unsigned long)_orig.nraddr; \
4145 _argvec[1] = (unsigned long)(arg1); \
4146 _argvec[2] = (unsigned long)(arg2); \
4147 _argvec[3] = (unsigned long)(arg3); \
4148 _argvec[4] = (unsigned long)(arg4); \
4149 _argvec[5] = (unsigned long)(arg5); \
4150 _argvec[6] = (unsigned long)(arg6); \
4151 _argvec[7] = (unsigned long)(arg7); \
4152 _argvec[8] = (unsigned long)(arg8); \
4153 _argvec[9] = (unsigned long)(arg9); \
4154 _argvec[10] = (unsigned long)(arg10); \
4155 _argvec[11] = (unsigned long)(arg11); \
4156 _argvec[12] = (unsigned long)(arg12); \
4157 __asm__ volatile( \
4158 "subu $29, $29, 8 \n\t" \
4159 "sw $gp, 0($sp) \n\t" \
4160 "sw $ra, 4($sp) \n\t" \
4161 "lw $a0, 20(%1) \n\t" \
4162 "subu $sp, $sp, 56\n\t" \
4163 "sw $a0, 16($sp) \n\t" \
4164 "lw $a0, 24(%1) \n\t" \
4165 "sw $a0, 20($sp) \n\t" \
4166 "lw $a0, 28(%1) \n\t" \
4167 "sw $a0, 24($sp) \n\t" \
4168 "lw $a0, 32(%1) \n\t" \
4169 "sw $a0, 28($sp) \n\t" \
4170 "lw $a0, 36(%1) \n\t" \
4171 "sw $a0, 32($sp) \n\t" \
4172 "lw $a0, 40(%1) \n\t" \
4173 "sw $a0, 36($sp) \n\t" \
4174 "lw $a0, 44(%1) \n\t" \
4175 "sw $a0, 40($sp) \n\t" \
4176 "lw $a0, 48(%1) \n\t" \
4177 "sw $a0, 44($sp) \n\t" \
4178 "lw $a0, 4(%1) \n\t" \
4179 "lw $a1, 8(%1) \n\t" \
4180 "lw $a2, 12(%1) \n\t" \
4181 "lw $a3, 16(%1) \n\t" \
4182 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4183 VALGRIND_CALL_NOREDIR_T9 \
4184 "addu $sp, $sp, 56 \n\t" \
4185 "lw $gp, 0($sp) \n\t" \
4186 "lw $ra, 4($sp) \n\t" \
4187 "addu $sp, $sp, 8 \n\t" \
4188 "move %0, $v0\n" \
4189 : /*out*/ "=r" (_res) \
4190 : /*in*/ "0" (&_argvec[0]) \
4191 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4192 ); \
4193 lval = (__typeof__(lval)) _res; \
4194 } while (0)
4195
4196#endif /* PLAT_mips32_linux */
4197
sewardj0ec07f32006-01-12 12:32:32 +00004198
4199/* ------------------------------------------------------------------ */
4200/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4201/* */
njn30d76c62005-06-18 15:07:39 +00004202/* ------------------------------------------------------------------ */
4203
sewardj2e93c502002-04-12 11:12:52 +00004204/* Some request codes. There are many more of these, but most are not
4205 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004206 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004207
sewardj0ec07f32006-01-12 12:32:32 +00004208 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4209 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004210*/
4211
sewardj0ec07f32006-01-12 12:32:32 +00004212/* These macros are used by tools -- they must be public, but don't
4213 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004214#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004215 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004216#define VG_IS_TOOL_USERREQ(a, b, v) \
4217 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004218
sewardj5ce4b152006-03-11 12:57:41 +00004219/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4220 This enum comprises an ABI exported by Valgrind to programs
4221 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4222 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004223typedef
njn4c791212003-05-02 17:53:54 +00004224 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4225 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004226
sewardj0ec07f32006-01-12 12:32:32 +00004227 /* These allow any function to be called from the simulated
4228 CPU but run on the real CPU. Nb: the first arg passed to
4229 the function is always the ThreadId of the running
4230 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004231 function, etc. */
njn4c791212003-05-02 17:53:54 +00004232 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4233 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4234 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4235 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004236
sewardj0ec07f32006-01-12 12:32:32 +00004237 /* Can be useful in regression testing suites -- eg. can
4238 send Valgrind's output to /dev/null and still count
4239 errors. */
njn4c791212003-05-02 17:53:54 +00004240 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004241
sewardj3b290482011-05-06 21:02:55 +00004242 /* Allows a string (gdb monitor command) to be passed to the tool
4243 Used for interaction with vgdb/gdb */
4244 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
4245
sewardj0ec07f32006-01-12 12:32:32 +00004246 /* These are useful and can be interpreted by any tool that
4247 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004248 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00004249 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00004250 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004251 /* Memory pool support. */
4252 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4253 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4254 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4255 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004256 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004257 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4258 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4259 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004260
fitzhardinge39de4b42003-10-31 07:12:21 +00004261 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00004262 /* The first two pass the va_list argument by value, which
4263 assumes it is the same size as or smaller than a UWord,
4264 which generally isn't the case. Hence are deprecated.
4265 The second two pass the vargs by reference and so are
4266 immune to this problem. */
4267 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00004268 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004269 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00004270 /* both :: char* fmt, va_list* vargs */
4271 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4272 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00004273
4274 /* Stack support. */
4275 VG_USERREQ__STACK_REGISTER = 0x1501,
4276 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004277 VG_USERREQ__STACK_CHANGE = 0x1503,
4278
4279 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00004280 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
4281
4282 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00004283 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
4284
4285 /* Disable/enable error reporting level. Takes a single
4286 Word arg which is the delta to this thread's error
4287 disablement indicator. Hence 1 disables or further
4288 disables errors, and -1 moves back towards enablement.
4289 Other values are not allowed. */
4290 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801
njn25e49d8e72002-09-23 09:36:25 +00004291 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004292
sewardj0ec07f32006-01-12 12:32:32 +00004293#if !defined(__GNUC__)
4294# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004295#endif
sewardj2e93c502002-04-12 11:12:52 +00004296
bartfa5115a2010-09-02 09:33:02 +00004297
sewardj0ec07f32006-01-12 12:32:32 +00004298/* Returns the number of Valgrinds this code is running under. That
4299 is, 0 if running natively, 1 if running under Valgrind, 2 if
4300 running under Valgrind which is running under another Valgrind,
4301 etc. */
bartfa5115a2010-09-02 09:33:02 +00004302#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00004303 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00004304 VG_USERREQ__RUNNING_ON_VALGRIND, \
4305 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00004306
4307
sewardj18d75132002-05-16 11:06:21 +00004308/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4309 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4310 since it provides a way to make sure valgrind will retranslate the
4311 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00004312#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4313 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
4314 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00004315
njn26aba4d2005-05-16 13:31:23 +00004316
sewardj0ec07f32006-01-12 12:32:32 +00004317/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004318 Possibly with a backtrace. This is a really ugly hack. The return value
4319 is the number of characters printed, excluding the "**<pid>** " part at the
4320 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004321
bart42f83fe2012-01-31 10:13:51 +00004322#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004323/* Modern GCC will optimize the static routine out if unused,
4324 and unused attribute will shut down warnings about it. */
4325static int VALGRIND_PRINTF(const char *format, ...)
4326 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004327#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004328static int
bart0da2c772010-09-01 10:18:36 +00004329#if defined(_MSC_VER)
4330__inline
4331#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004332VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004333{
bart8c7e25f2011-03-04 16:55:56 +00004334#if defined(NVALGRIND)
4335 return 0;
4336#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00004337#if defined(_MSC_VER)
4338 uintptr_t _qzz_res;
4339#else
njnc6168192004-11-29 13:54:10 +00004340 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00004341#endif
sewardjc560fb32010-01-28 15:23:54 +00004342 va_list vargs;
4343 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004344#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00004345 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00004346 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004347 (uintptr_t)format,
4348 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004349 0, 0, 0);
4350#else
bart575ce8e2011-05-15 07:04:03 +00004351 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00004352 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004353 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004354 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004355 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004356#endif
sewardjc560fb32010-01-28 15:23:54 +00004357 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004358 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00004359#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004360}
4361
bart42f83fe2012-01-31 10:13:51 +00004362#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004363static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4364 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004365#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004366static int
bart0da2c772010-09-01 10:18:36 +00004367#if defined(_MSC_VER)
4368__inline
4369#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004370VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004371{
bart8c7e25f2011-03-04 16:55:56 +00004372#if defined(NVALGRIND)
4373 return 0;
4374#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00004375#if defined(_MSC_VER)
4376 uintptr_t _qzz_res;
4377#else
njnc6168192004-11-29 13:54:10 +00004378 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00004379#endif
sewardjc560fb32010-01-28 15:23:54 +00004380 va_list vargs;
4381 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004382#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00004383 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00004384 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004385 (uintptr_t)format,
4386 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004387 0, 0, 0);
4388#else
bart575ce8e2011-05-15 07:04:03 +00004389 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00004390 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004391 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004392 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004393 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004394#endif
sewardjc560fb32010-01-28 15:23:54 +00004395 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004396 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004397#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00004398}
sewardj18d75132002-05-16 11:06:21 +00004399
sewardj0ec07f32006-01-12 12:32:32 +00004400
njn3e884182003-04-15 13:03:23 +00004401/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004402 real CPU, calling an arbitary function.
4403
4404 Note that the current ThreadId is inserted as the first argument.
4405 So this call:
4406
4407 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4408
4409 requires f to have this signature:
4410
4411 Word f(Word tid, Word arg1, Word arg2)
4412
4413 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004414
4415 Note that these client requests are not entirely reliable. For example,
4416 if you call a function with them that subsequently calls printf(),
4417 there's a high chance Valgrind will crash. Generally, your prospects of
4418 these working are made higher if the called function does not refer to
4419 any global variables, and does not refer to any libc or other functions
4420 (printf et al). Any kind of entanglement with libc or dynamic linking is
4421 likely to have a bad outcome, for tricky reasons which we've grappled
4422 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004423*/
sewardj0ec07f32006-01-12 12:32:32 +00004424#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00004425 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4426 VG_USERREQ__CLIENT_CALL0, \
4427 _qyy_fn, \
4428 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00004429
bart575ce8e2011-05-15 07:04:03 +00004430#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
4431 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4432 VG_USERREQ__CLIENT_CALL1, \
4433 _qyy_fn, \
4434 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00004435
bart575ce8e2011-05-15 07:04:03 +00004436#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
4437 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4438 VG_USERREQ__CLIENT_CALL2, \
4439 _qyy_fn, \
4440 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00004441
sewardj0ec07f32006-01-12 12:32:32 +00004442#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00004443 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4444 VG_USERREQ__CLIENT_CALL3, \
4445 _qyy_fn, \
4446 _qyy_arg1, _qyy_arg2, \
4447 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00004448
4449
nethercote7cc9c232004-01-21 15:08:04 +00004450/* Counts the number of errors that have been recorded by a tool. Nb:
4451 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004452 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004453#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00004454 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4455 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00004456 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00004457 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00004458
njn3ac96952009-07-09 23:35:44 +00004459/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4460 when heap blocks are allocated in order to give accurate results. This
4461 happens automatically for the standard allocator functions such as
4462 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4463 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004464
njn3ac96952009-07-09 23:35:44 +00004465 But if your program uses a custom allocator, this doesn't automatically
4466 happen, and Valgrind will not do as well. For example, if you allocate
4467 superblocks with mmap() and then allocates chunks of the superblocks, all
4468 Valgrind's observations will be at the mmap() level and it won't know that
4469 the chunks should be considered separate entities. In Memcheck's case,
4470 that means you probably won't get heap block overrun detection (because
4471 there won't be redzones marked as unaddressable) and you definitely won't
4472 get any leak detection.
4473
4474 The following client requests allow a custom allocator to be annotated so
4475 that it can be handled accurately by Valgrind.
4476
4477 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4478 by a malloc()-like function. For Memcheck (an illustrative case), this
4479 does two things:
4480
4481 - It records that the block has been allocated. This means any addresses
4482 within the block mentioned in error messages will be
4483 identified as belonging to the block. It also means that if the block
4484 isn't freed it will be detected by the leak checker.
4485
4486 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4487 not set), or addressable and defined (if 'is_zeroed' is set). This
4488 controls how accesses to the block by the program are handled.
4489
4490 'addr' is the start of the usable block (ie. after any
4491 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4492 can apply redzones -- these are blocks of padding at the start and end of
4493 each block. Adding redzones is recommended as it makes it much more likely
4494 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4495 zeroed (or filled with another predictable value), as is the case for
4496 calloc().
4497
4498 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4499 heap block -- that will be used by the client program -- is allocated.
4500 It's best to put it at the outermost level of the allocator if possible;
4501 for example, if you have a function my_alloc() which calls
4502 internal_alloc(), and the client request is put inside internal_alloc(),
4503 stack traces relating to the heap block will contain entries for both
4504 my_alloc() and internal_alloc(), which is probably not what you want.
4505
njnb965efb2009-08-10 07:36:54 +00004506 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4507 custom blocks from within a heap block, B, that has been allocated with
4508 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4509 -- the custom blocks will take precedence.
4510
njn3ac96952009-07-09 23:35:44 +00004511 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4512 Memcheck, it does two things:
4513
4514 - It records that the block has been deallocated. This assumes that the
4515 block was annotated as having been allocated via
4516 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4517
4518 - It marks the block as being unaddressable.
4519
4520 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4521 heap block is deallocated.
4522
bart91347382011-03-25 20:07:25 +00004523 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
4524 Memcheck, it does four things:
4525
4526 - It records that the size of a block has been changed. This assumes that
4527 the block was annotated as having been allocated via
4528 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4529
4530 - If the block shrunk, it marks the freed memory as being unaddressable.
4531
4532 - If the block grew, it marks the new area as undefined and defines a red
4533 zone past the end of the new block.
4534
4535 - The V-bits of the overlap between the old and the new block are preserved.
4536
4537 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
4538 and before deallocation of the old block.
4539
4540 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00004541 allocator working well with Memcheck. More specifically, if your allocator
4542 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4543 will be necessary to mark the memory as addressable just before the zeroing
4544 occurs, otherwise you'll get a lot of invalid write errors. For example,
4545 you'll need to do this if your allocator recycles freed blocks, but it
4546 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4547 Alternatively, if your allocator reuses freed blocks for allocator-internal
4548 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4549
4550 Really, what's happening is a blurring of the lines between the client
4551 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4552 memory should be considered unaddressable to the client program, but the
4553 allocator knows more than the rest of the client program and so may be able
4554 to safely access it. Extra client requests are necessary for Valgrind to
4555 understand the distinction between the allocator and the rest of the
4556 program.
4557
njn32f8d8c2009-07-15 02:31:45 +00004558 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004559*/
sewardj4b3a7422011-10-24 13:21:57 +00004560#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4561 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
4562 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00004563
njn32f8d8c2009-07-15 02:31:45 +00004564/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4565 Ignored if addr == 0.
4566*/
sewardj4b3a7422011-10-24 13:21:57 +00004567#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
4568 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
4569 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00004570
4571/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4572 Ignored if addr == 0.
4573*/
sewardj4b3a7422011-10-24 13:21:57 +00004574#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4575 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
4576 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00004577
rjwalshbc0bb832004-06-19 18:12:36 +00004578/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004579#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00004580 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
4581 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004582
4583/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004584#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00004585 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
4586 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004587
4588/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004589#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00004590 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
4591 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004592
4593/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004594#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00004595 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
4596 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004597
sewardj2c1c9df2006-07-28 00:06:37 +00004598/* Disassociate any pieces outside a particular range. */
4599#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00004600 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
4601 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00004602
sewardjc740d762006-10-05 17:59:23 +00004603/* Resize and/or move a piece associated with a memory pool. */
4604#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00004605 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
4606 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00004607
4608/* Resize and/or move a piece associated with a memory pool. */
4609#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00004610 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
4611 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00004612
4613/* Return 1 if a mempool exists, else 0. */
4614#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00004615 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00004616 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00004617 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00004618
rjwalsh0140af52005-06-04 20:42:33 +00004619/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004620#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00004621 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004622 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00004623 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004624
4625/* Unmark the piece of memory associated with a stack id as being a
4626 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004627#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00004628 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
4629 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004630
4631/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004632#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00004633 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
4634 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004635
sewardjc8259b82009-04-22 22:42:10 +00004636/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00004637#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4638 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4639 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00004640
sewardj5c659622010-08-20 18:22:07 +00004641/* Map a code address to a source file name and line number. buf64
4642 must point to a 64-byte buffer in the caller's address space. The
4643 result will be dumped in there and is guaranteed to be zero
4644 terminated. If no info is found, the first byte is set to zero. */
4645#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00004646 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00004647 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00004648 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00004649
sewardjdc873c02011-07-24 16:02:33 +00004650/* Disable error reporting for this thread. Behaves in a stack like
4651 way, so you can safely call this multiple times provided that
4652 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
4653 to re-enable reporting. The first call of this macro disables
4654 reporting. Subsequent calls have no effect except to increase the
4655 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
4656 reporting. Child threads do not inherit this setting from their
4657 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00004658#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00004659 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4660 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00004661
4662/* Re-enable error reporting, as per comments on
4663 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00004664#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00004665 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4666 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00004667
sewardjc112c8e2011-06-24 18:26:11 +00004668#undef PLAT_x86_darwin
4669#undef PLAT_amd64_darwin
4670#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +00004671#undef PLAT_x86_linux
4672#undef PLAT_amd64_linux
4673#undef PLAT_ppc32_linux
4674#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004675#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00004676#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +00004677#undef PLAT_mips32_linux
sewardj0ec07f32006-01-12 12:32:32 +00004678
njn3e884182003-04-15 13:03:23 +00004679#endif /* __VALGRIND_H */