blob: a65f03a1a754a58f486eef1a83f755b79853d107 [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
sewardj0f157dd2013-10-18 14:27:36 +000015 Copyright (C) 2000-2013 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
sewardjbd830b42014-05-12 10:12:08 +000092#define __VALGRIND_MINOR__ 10
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
bartaaaf21d2013-08-25 06:10:24 +0000114#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +0000115#undef PLAT_x86_linux
116#undef PLAT_amd64_linux
117#undef PLAT_ppc32_linux
carllcae0cc22014-08-07 23:17:29 +0000118#undef PLAT_ppc64be_linux
carll582d5822014-08-07 23:35:54 +0000119#undef PLAT_ppc64le_linux
sewardj59570ff2010-01-01 11:59:33 +0000120#undef PLAT_arm_linux
sewardjf0c12502014-01-12 12:54:00 +0000121#undef PLAT_arm64_linux
sewardjb5b87402011-03-07 16:05:35 +0000122#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +0000123#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +0000124#undef PLAT_mips64_linux
sewardjb5b87402011-03-07 16:05:35 +0000125
sewardj0ec07f32006-01-12 12:32:32 +0000126
sewardj6e9de462011-06-28 07:25:29 +0000127#if defined(__APPLE__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000128# define PLAT_x86_darwin 1
129#elif defined(__APPLE__) && defined(__x86_64__)
130# define PLAT_amd64_darwin 1
sewardjc913c8e2014-05-15 13:50:47 +0000131#elif (defined(__MINGW32__) && !defined(__MINGW64__)) \
132 || defined(__CYGWIN32__) \
sewardj6e9de462011-06-28 07:25:29 +0000133 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000134# define PLAT_x86_win32 1
sewardjc913c8e2014-05-15 13:50:47 +0000135#elif defined(__MINGW64__) \
136 || (defined(_WIN64) && defined(_M_X64))
bartaaaf21d2013-08-25 06:10:24 +0000137# define PLAT_amd64_win64 1
sewardj59570ff2010-01-01 11:59:33 +0000138#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000139# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000140#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000141# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000142#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000143# define PLAT_ppc32_linux 1
carllcae0cc22014-08-07 23:17:29 +0000144#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
145/* Big Endian uses ELF version 1 */
146# define PLAT_ppc64be_linux 1
carll582d5822014-08-07 23:35:54 +0000147#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2
148/* Little Endian uses ELF version 2 */
149# define PLAT_ppc64le_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000150#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
sewardj59570ff2010-01-01 11:59:33 +0000151# define PLAT_arm_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000152#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
153# define PLAT_arm64_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000154#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
155# define PLAT_s390x_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000156#elif defined(__linux__) && defined(__mips__) && (__mips==64)
petarj4df0bfc2013-02-27 23:17:33 +0000157# define PLAT_mips64_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000158#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
sewardj5db15402012-06-07 09:13:21 +0000159# define PLAT_mips32_linux 1
njnf76d27a2009-05-28 01:53:07 +0000160#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000161/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000162 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000163# if !defined(NVALGRIND)
164# define NVALGRIND 1
165# endif
166#endif
167
168
njn30d76c62005-06-18 15:07:39 +0000169/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000170/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
171/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000172/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000173
bart575ce8e2011-05-15 07:04:03 +0000174/*
175 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
176 * request. Accepts both pointers and integers as arguments.
177 *
sewardj4b3a7422011-10-24 13:21:57 +0000178 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
179 * client request that does not return a value.
180
bart575ce8e2011-05-15 07:04:03 +0000181 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000182 * client request and whose value equals the client request result. Accepts
183 * both pointers and integers as arguments. Note that such calls are not
184 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000185 */
186
187#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
188 _zzq_request, _zzq_arg1, _zzq_arg2, \
189 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000190 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000191 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000192 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000193
sewardj4b3a7422011-10-24 13:21:57 +0000194#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
195 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
196 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
197 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
198 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
199
sewardj0ec07f32006-01-12 12:32:32 +0000200#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000201
202/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000203 from the compiled code (analogous to NDEBUG's effects on
204 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000205#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
206 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000207 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000208 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000209
sewardj0ec07f32006-01-12 12:32:32 +0000210#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000211
sewardj0ec07f32006-01-12 12:32:32 +0000212/* The following defines the magic code sequences which the JITter
213 spots and handles magically. Don't look too closely at them as
214 they will rot your brain.
215
216 The assembly code sequences for all architectures is in this one
217 file. This is because this file must be stand-alone, and we don't
218 want to have multiple files.
219
220 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
221 value gets put in the return slot, so that everything works when
222 this is executed not under Valgrind. Args are passed in a memory
223 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000224 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000225
nethercote54265442004-10-26 12:56:58 +0000226 The macro args are:
227 _zzq_rlval result lvalue
228 _zzq_default default value (result returned when running on real CPU)
229 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000230 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000231
sewardj0ec07f32006-01-12 12:32:32 +0000232 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000233 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
234 guest's NRADDR pseudo-register and whatever other information is
235 needed to safely run the call original from the wrapper: on
236 ppc64-linux, the R2 value at the divert point is also needed. This
237 information is abstracted into a user-visible type, OrigFn.
238
239 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
240 guest, but guarantees that the branch instruction will not be
241 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
242 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
243 complete inline asm, since it needs to be combined with more magic
244 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000245*/
246
njnf76d27a2009-05-28 01:53:07 +0000247/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000248
sewardj520a03a2010-10-07 10:46:15 +0000249#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000250 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000251
252typedef
253 struct {
254 unsigned int nraddr; /* where's the code? */
255 }
256 OrigFn;
257
sewardj0ec07f32006-01-12 12:32:32 +0000258#define __SPECIAL_INSTRUCTION_PREAMBLE \
259 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000260 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000261
bart575ce8e2011-05-15 07:04:03 +0000262#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
263 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000264 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000265 __extension__ \
266 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000267 volatile unsigned int _zzq_result; \
268 _zzq_args[0] = (unsigned int)(_zzq_request); \
269 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
270 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
271 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
272 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000273 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000274 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
275 /* %EDX = client_request ( %EAX ) */ \
276 "xchgl %%ebx,%%ebx" \
277 : "=d" (_zzq_result) \
278 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
279 : "cc", "memory" \
280 ); \
bart575ce8e2011-05-15 07:04:03 +0000281 _zzq_result; \
282 })
sewardj2c48c7b2005-11-29 13:05:56 +0000283
sewardjc8858442006-01-20 15:17:20 +0000284#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
285 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
286 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000287 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
288 /* %EAX = guest_NRADDR */ \
289 "xchgl %%ecx,%%ecx" \
290 : "=a" (__addr) \
291 : \
292 : "cc", "memory" \
293 ); \
sewardjc8858442006-01-20 15:17:20 +0000294 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000295 }
sewardj0ec07f32006-01-12 12:32:32 +0000296
297#define VALGRIND_CALL_NOREDIR_EAX \
298 __SPECIAL_INSTRUCTION_PREAMBLE \
299 /* call-noredir *%EAX */ \
300 "xchgl %%edx,%%edx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000301
302#define VALGRIND_VEX_INJECT_IR() \
303 do { \
304 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
305 "xchgl %%edi,%%edi\n\t" \
306 : : : "cc", "memory" \
307 ); \
308 } while (0)
309
sewardj60227842010-10-07 10:00:56 +0000310#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000311
312/* ------------------------- x86-Win32 ------------------------- */
313
314#if defined(PLAT_x86_win32) && !defined(__GNUC__)
315
316typedef
317 struct {
318 unsigned int nraddr; /* where's the code? */
319 }
320 OrigFn;
321
322#if defined(_MSC_VER)
323
324#define __SPECIAL_INSTRUCTION_PREAMBLE \
325 __asm rol edi, 3 __asm rol edi, 13 \
326 __asm rol edi, 29 __asm rol edi, 19
327
bart575ce8e2011-05-15 07:04:03 +0000328#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
329 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000330 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000331 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
332 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
333 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
334 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
335
336static __inline uintptr_t
337valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
338 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
339 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
340 uintptr_t _zzq_arg5)
341{
342 volatile uintptr_t _zzq_args[6];
343 volatile unsigned int _zzq_result;
344 _zzq_args[0] = (uintptr_t)(_zzq_request);
345 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
346 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
347 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
348 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
349 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
350 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
351 __SPECIAL_INSTRUCTION_PREAMBLE
352 /* %EDX = client_request ( %EAX ) */
353 __asm xchg ebx,ebx
354 __asm mov _zzq_result, edx
355 }
356 return _zzq_result;
357}
bart7f489812010-08-27 10:05:27 +0000358
359#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
360 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
361 volatile unsigned int __addr; \
362 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
363 /* %EAX = guest_NRADDR */ \
364 __asm xchg ecx,ecx \
365 __asm mov __addr, eax \
366 } \
367 _zzq_orig->nraddr = __addr; \
368 }
369
370#define VALGRIND_CALL_NOREDIR_EAX ERROR
371
florianbb913cd2012-08-28 16:50:39 +0000372#define VALGRIND_VEX_INJECT_IR() \
373 do { \
374 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
375 __asm xchg edi,edi \
376 } \
377 } while (0)
378
bart7f489812010-08-27 10:05:27 +0000379#else
380#error Unsupported compiler.
381#endif
382
383#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000384
njnf76d27a2009-05-28 01:53:07 +0000385/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000386
sewardjc913c8e2014-05-15 13:50:47 +0000387#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
388 || (defined(PLAT_amd64_win64) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000389
390typedef
391 struct {
392 unsigned long long int nraddr; /* where's the code? */
393 }
394 OrigFn;
395
sewardj0ec07f32006-01-12 12:32:32 +0000396#define __SPECIAL_INSTRUCTION_PREAMBLE \
397 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000398 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000399
bart575ce8e2011-05-15 07:04:03 +0000400#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
401 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000402 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000403 __extension__ \
404 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000405 volatile unsigned long long int _zzq_result; \
406 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
407 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
408 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
409 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
410 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000411 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000412 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
413 /* %RDX = client_request ( %RAX ) */ \
414 "xchgq %%rbx,%%rbx" \
415 : "=d" (_zzq_result) \
416 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
417 : "cc", "memory" \
418 ); \
bart575ce8e2011-05-15 07:04:03 +0000419 _zzq_result; \
420 })
sewardj0ec07f32006-01-12 12:32:32 +0000421
sewardjc8858442006-01-20 15:17:20 +0000422#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
423 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
424 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000425 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
426 /* %RAX = guest_NRADDR */ \
427 "xchgq %%rcx,%%rcx" \
428 : "=a" (__addr) \
429 : \
430 : "cc", "memory" \
431 ); \
sewardjc8858442006-01-20 15:17:20 +0000432 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000433 }
434
435#define VALGRIND_CALL_NOREDIR_RAX \
436 __SPECIAL_INSTRUCTION_PREAMBLE \
437 /* call-noredir *%RAX */ \
438 "xchgq %%rdx,%%rdx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000439
440#define VALGRIND_VEX_INJECT_IR() \
441 do { \
442 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
443 "xchgq %%rdi,%%rdi\n\t" \
444 : : : "cc", "memory" \
445 ); \
446 } while (0)
447
njnf76d27a2009-05-28 01:53:07 +0000448#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000449
sewardjc913c8e2014-05-15 13:50:47 +0000450/* ------------------------- amd64-Win64 ------------------------- */
451
452#if defined(PLAT_amd64_win64) && !defined(__GNUC__)
453
454#error Unsupported compiler.
455
456#endif /* PLAT_amd64_win64 */
457
sewardjf5c1a7f2006-10-17 01:32:48 +0000458/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000459
sewardjf5c1a7f2006-10-17 01:32:48 +0000460#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000461
462typedef
463 struct {
sewardjc8858442006-01-20 15:17:20 +0000464 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000465 }
466 OrigFn;
467
sewardj0ec07f32006-01-12 12:32:32 +0000468#define __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj4decb262014-02-10 12:26:12 +0000469 "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \
470 "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000471
bart575ce8e2011-05-15 07:04:03 +0000472#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
473 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000474 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000475 \
bart575ce8e2011-05-15 07:04:03 +0000476 __extension__ \
477 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000478 unsigned int _zzq_result; \
479 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000480 _zzq_args[0] = (unsigned int)(_zzq_request); \
481 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
482 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
483 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
484 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000485 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000486 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000487 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
488 "mr 4,%2\n\t" /*ptr*/ \
489 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000490 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000491 "or 1,1,1\n\t" \
492 "mr %0,3" /*result*/ \
493 : "=b" (_zzq_result) \
494 : "b" (_zzq_default), "b" (_zzq_ptr) \
495 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000496 _zzq_result; \
497 })
sewardj0ec07f32006-01-12 12:32:32 +0000498
sewardjd68ac3e2006-01-20 14:31:57 +0000499#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
500 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000501 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000502 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
503 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000504 "or 2,2,2\n\t" \
505 "mr %0,3" \
506 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000507 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000508 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000509 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000510 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000511 }
512
513#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
514 __SPECIAL_INSTRUCTION_PREAMBLE \
515 /* branch-and-link-to-noredir *%R11 */ \
516 "or 3,3,3\n\t"
florian4d261bb2012-08-29 14:59:13 +0000517
518#define VALGRIND_VEX_INJECT_IR() \
519 do { \
520 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
521 "or 5,5,5\n\t" \
522 ); \
523 } while (0)
524
sewardjf5c1a7f2006-10-17 01:32:48 +0000525#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000526
sewardjf5c1a7f2006-10-17 01:32:48 +0000527/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000528
carllcae0cc22014-08-07 23:17:29 +0000529#if defined(PLAT_ppc64be_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000530
531typedef
532 struct {
533 unsigned long long int nraddr; /* where's the code? */
534 unsigned long long int r2; /* what tocptr do we need? */
535 }
536 OrigFn;
537
sewardj1a85f4f2006-01-12 21:15:35 +0000538#define __SPECIAL_INSTRUCTION_PREAMBLE \
539 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
540 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
541
bart575ce8e2011-05-15 07:04:03 +0000542#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
543 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000544 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000545 \
bart575ce8e2011-05-15 07:04:03 +0000546 __extension__ \
547 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000548 unsigned long long int _zzq_result; \
549 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000550 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
551 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
552 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
553 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
554 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000555 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000556 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000557 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
558 "mr 4,%2\n\t" /*ptr*/ \
559 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000560 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000561 "or 1,1,1\n\t" \
562 "mr %0,3" /*result*/ \
563 : "=b" (_zzq_result) \
564 : "b" (_zzq_default), "b" (_zzq_ptr) \
565 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000566 _zzq_result; \
567 })
sewardj1a85f4f2006-01-12 21:15:35 +0000568
sewardjd68ac3e2006-01-20 14:31:57 +0000569#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
570 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000571 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000572 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
573 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000574 "or 2,2,2\n\t" \
575 "mr %0,3" \
576 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000577 : \
sewardj8258a3a2011-10-05 07:39:07 +0000578 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000579 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000580 _zzq_orig->nraddr = __addr; \
581 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
582 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000583 "or 4,4,4\n\t" \
584 "mr %0,3" \
585 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000586 : \
sewardj8258a3a2011-10-05 07:39:07 +0000587 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000588 ); \
589 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000590 }
591
592#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
593 __SPECIAL_INSTRUCTION_PREAMBLE \
594 /* branch-and-link-to-noredir *%R11 */ \
595 "or 3,3,3\n\t"
596
florianbb913cd2012-08-28 16:50:39 +0000597#define VALGRIND_VEX_INJECT_IR() \
598 do { \
599 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
600 "or 5,5,5\n\t" \
601 ); \
602 } while (0)
603
carllcae0cc22014-08-07 23:17:29 +0000604#endif /* PLAT_ppc64be_linux */
605
carll582d5822014-08-07 23:35:54 +0000606#if defined(PLAT_ppc64le_linux)
607
608typedef
609 struct {
610 unsigned long long int nraddr; /* where's the code? */
611 unsigned long long int r2; /* what tocptr do we need? */
612 }
613 OrigFn;
614
615#define __SPECIAL_INSTRUCTION_PREAMBLE \
616 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
617 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
618
619#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
620 _zzq_default, _zzq_request, \
621 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
622 \
623 __extension__ \
624 ({ unsigned long long int _zzq_args[6]; \
625 unsigned long long int _zzq_result; \
626 unsigned long long int* _zzq_ptr; \
627 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
628 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
629 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
630 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
631 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
632 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
633 _zzq_ptr = _zzq_args; \
634 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
635 "mr 4,%2\n\t" /*ptr*/ \
636 __SPECIAL_INSTRUCTION_PREAMBLE \
637 /* %R3 = client_request ( %R4 ) */ \
638 "or 1,1,1\n\t" \
639 "mr %0,3" /*result*/ \
640 : "=b" (_zzq_result) \
641 : "b" (_zzq_default), "b" (_zzq_ptr) \
642 : "cc", "memory", "r3", "r4"); \
643 _zzq_result; \
644 })
645
646#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
647 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
648 unsigned long long int __addr; \
649 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
650 /* %R3 = guest_NRADDR */ \
651 "or 2,2,2\n\t" \
652 "mr %0,3" \
653 : "=b" (__addr) \
654 : \
655 : "cc", "memory", "r3" \
656 ); \
657 _zzq_orig->nraddr = __addr; \
658 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
659 /* %R3 = guest_NRADDR_GPR2 */ \
660 "or 4,4,4\n\t" \
661 "mr %0,3" \
662 : "=b" (__addr) \
663 : \
664 : "cc", "memory", "r3" \
665 ); \
666 _zzq_orig->r2 = __addr; \
667 }
668
669#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
670 __SPECIAL_INSTRUCTION_PREAMBLE \
671 /* branch-and-link-to-noredir *%R12 */ \
672 "or 3,3,3\n\t"
673
674#define VALGRIND_VEX_INJECT_IR() \
675 do { \
676 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
677 "or 5,5,5\n\t" \
678 ); \
679 } while (0)
680
681#endif /* PLAT_ppc64le_linux */
cerion85665ca2005-06-20 15:51:07 +0000682
sewardj59570ff2010-01-01 11:59:33 +0000683/* ------------------------- arm-linux ------------------------- */
684
685#if defined(PLAT_arm_linux)
686
687typedef
688 struct {
689 unsigned int nraddr; /* where's the code? */
690 }
691 OrigFn;
692
693#define __SPECIAL_INSTRUCTION_PREAMBLE \
694 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
695 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
696
bart575ce8e2011-05-15 07:04:03 +0000697#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
698 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000699 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
700 \
bart575ce8e2011-05-15 07:04:03 +0000701 __extension__ \
702 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000703 volatile unsigned int _zzq_result; \
704 _zzq_args[0] = (unsigned int)(_zzq_request); \
705 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
706 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
707 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
708 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
709 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
710 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
711 "mov r4, %2\n\t" /*ptr*/ \
712 __SPECIAL_INSTRUCTION_PREAMBLE \
713 /* R3 = client_request ( R4 ) */ \
714 "orr r10, r10, r10\n\t" \
715 "mov %0, r3" /*result*/ \
716 : "=r" (_zzq_result) \
717 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
718 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000719 _zzq_result; \
720 })
sewardj59570ff2010-01-01 11:59:33 +0000721
722#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
723 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
724 unsigned int __addr; \
725 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
726 /* R3 = guest_NRADDR */ \
727 "orr r11, r11, r11\n\t" \
728 "mov %0, r3" \
729 : "=r" (__addr) \
730 : \
731 : "cc", "memory", "r3" \
732 ); \
733 _zzq_orig->nraddr = __addr; \
734 }
735
736#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
737 __SPECIAL_INSTRUCTION_PREAMBLE \
738 /* branch-and-link-to-noredir *%R4 */ \
739 "orr r12, r12, r12\n\t"
740
florianbb913cd2012-08-28 16:50:39 +0000741#define VALGRIND_VEX_INJECT_IR() \
742 do { \
743 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
sewardjc379fec2012-09-03 21:51:02 +0000744 "orr r9, r9, r9\n\t" \
florianbb913cd2012-08-28 16:50:39 +0000745 : : : "cc", "memory" \
746 ); \
747 } while (0)
748
sewardj59570ff2010-01-01 11:59:33 +0000749#endif /* PLAT_arm_linux */
750
sewardjf0c12502014-01-12 12:54:00 +0000751/* ------------------------ arm64-linux ------------------------- */
752
753#if defined(PLAT_arm64_linux)
754
755typedef
756 struct {
757 unsigned long long int nraddr; /* where's the code? */
758 }
759 OrigFn;
760
761#define __SPECIAL_INSTRUCTION_PREAMBLE \
762 "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
763 "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
764
765#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
766 _zzq_default, _zzq_request, \
767 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
768 \
769 __extension__ \
770 ({volatile unsigned long long int _zzq_args[6]; \
771 volatile unsigned long long int _zzq_result; \
772 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
773 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
774 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
775 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
776 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
777 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
778 __asm__ volatile("mov x3, %1\n\t" /*default*/ \
779 "mov x4, %2\n\t" /*ptr*/ \
780 __SPECIAL_INSTRUCTION_PREAMBLE \
781 /* X3 = client_request ( X4 ) */ \
782 "orr x10, x10, x10\n\t" \
783 "mov %0, x3" /*result*/ \
784 : "=r" (_zzq_result) \
785 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
786 : "cc","memory", "x3", "x4"); \
787 _zzq_result; \
788 })
789
790#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
791 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
792 unsigned long long int __addr; \
793 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
794 /* X3 = guest_NRADDR */ \
795 "orr x11, x11, x11\n\t" \
796 "mov %0, x3" \
797 : "=r" (__addr) \
798 : \
799 : "cc", "memory", "x3" \
800 ); \
801 _zzq_orig->nraddr = __addr; \
802 }
803
804#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
805 __SPECIAL_INSTRUCTION_PREAMBLE \
806 /* branch-and-link-to-noredir X8 */ \
807 "orr x12, x12, x12\n\t"
808
809#define VALGRIND_VEX_INJECT_IR() \
810 do { \
811 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
812 "orr x9, x9, x9\n\t" \
813 : : : "cc", "memory" \
814 ); \
815 } while (0)
816
817#endif /* PLAT_arm64_linux */
818
sewardjb5b87402011-03-07 16:05:35 +0000819/* ------------------------ s390x-linux ------------------------ */
820
821#if defined(PLAT_s390x_linux)
822
823typedef
824 struct {
825 unsigned long long int nraddr; /* where's the code? */
826 }
827 OrigFn;
828
829/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
830 * code. This detection is implemented in platform specific toIR.c
831 * (e.g. VEX/priv/guest_s390_decoder.c).
832 */
833#define __SPECIAL_INSTRUCTION_PREAMBLE \
834 "lr 15,15\n\t" \
835 "lr 1,1\n\t" \
836 "lr 2,2\n\t" \
837 "lr 3,3\n\t"
838
839#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
840#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
841#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
florianbb913cd2012-08-28 16:50:39 +0000842#define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
sewardjb5b87402011-03-07 16:05:35 +0000843
bart575ce8e2011-05-15 07:04:03 +0000844#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
845 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000846 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000847 __extension__ \
848 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000849 volatile unsigned long long int _zzq_result; \
850 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
851 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
852 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
853 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
854 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
855 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
856 __asm__ volatile(/* r2 = args */ \
857 "lgr 2,%1\n\t" \
858 /* r3 = default */ \
859 "lgr 3,%2\n\t" \
860 __SPECIAL_INSTRUCTION_PREAMBLE \
861 __CLIENT_REQUEST_CODE \
862 /* results = r3 */ \
863 "lgr %0, 3\n\t" \
864 : "=d" (_zzq_result) \
865 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
866 : "cc", "2", "3", "memory" \
867 ); \
bart575ce8e2011-05-15 07:04:03 +0000868 _zzq_result; \
869 })
sewardjb5b87402011-03-07 16:05:35 +0000870
871#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
872 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
873 volatile unsigned long long int __addr; \
874 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
875 __GET_NR_CONTEXT_CODE \
876 "lgr %0, 3\n\t" \
877 : "=a" (__addr) \
878 : \
879 : "cc", "3", "memory" \
880 ); \
881 _zzq_orig->nraddr = __addr; \
882 }
883
884#define VALGRIND_CALL_NOREDIR_R1 \
885 __SPECIAL_INSTRUCTION_PREAMBLE \
886 __CALL_NO_REDIR_CODE
887
florianbb913cd2012-08-28 16:50:39 +0000888#define VALGRIND_VEX_INJECT_IR() \
889 do { \
890 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
891 __VEX_INJECT_IR_CODE); \
892 } while (0)
893
sewardjb5b87402011-03-07 16:05:35 +0000894#endif /* PLAT_s390x_linux */
895
sewardj5db15402012-06-07 09:13:21 +0000896/* ------------------------- mips32-linux ---------------- */
897
898#if defined(PLAT_mips32_linux)
899
900typedef
901 struct {
902 unsigned int nraddr; /* where's the code? */
903 }
904 OrigFn;
905
906/* .word 0x342
907 * .word 0x742
908 * .word 0xC2
909 * .word 0x4C2*/
910#define __SPECIAL_INSTRUCTION_PREAMBLE \
911 "srl $0, $0, 13\n\t" \
912 "srl $0, $0, 29\n\t" \
913 "srl $0, $0, 3\n\t" \
914 "srl $0, $0, 19\n\t"
915
916#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
917 _zzq_default, _zzq_request, \
918 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
919 __extension__ \
920 ({ volatile unsigned int _zzq_args[6]; \
921 volatile unsigned int _zzq_result; \
922 _zzq_args[0] = (unsigned int)(_zzq_request); \
923 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
924 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
925 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
926 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
927 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
928 __asm__ volatile("move $11, %1\n\t" /*default*/ \
929 "move $12, %2\n\t" /*ptr*/ \
930 __SPECIAL_INSTRUCTION_PREAMBLE \
931 /* T3 = client_request ( T4 ) */ \
932 "or $13, $13, $13\n\t" \
933 "move %0, $11\n\t" /*result*/ \
934 : "=r" (_zzq_result) \
935 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
petarj4df0bfc2013-02-27 23:17:33 +0000936 : "$11", "$12"); \
sewardj5db15402012-06-07 09:13:21 +0000937 _zzq_result; \
938 })
939
940#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
941 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
942 volatile unsigned int __addr; \
943 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
944 /* %t9 = guest_NRADDR */ \
945 "or $14, $14, $14\n\t" \
946 "move %0, $11" /*result*/ \
947 : "=r" (__addr) \
948 : \
petarj4df0bfc2013-02-27 23:17:33 +0000949 : "$11" \
sewardj5db15402012-06-07 09:13:21 +0000950 ); \
951 _zzq_orig->nraddr = __addr; \
952 }
953
954#define VALGRIND_CALL_NOREDIR_T9 \
955 __SPECIAL_INSTRUCTION_PREAMBLE \
956 /* call-noredir *%t9 */ \
florianbb913cd2012-08-28 16:50:39 +0000957 "or $15, $15, $15\n\t"
958
959#define VALGRIND_VEX_INJECT_IR() \
960 do { \
961 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
962 "or $11, $11, $11\n\t" \
963 ); \
964 } while (0)
965
966
sewardj5db15402012-06-07 09:13:21 +0000967#endif /* PLAT_mips32_linux */
968
petarj4df0bfc2013-02-27 23:17:33 +0000969/* ------------------------- mips64-linux ---------------- */
970
971#if defined(PLAT_mips64_linux)
972
973typedef
974 struct {
975 unsigned long long nraddr; /* where's the code? */
976 }
977 OrigFn;
978
979/* dsll $0,$0, 3
980 * dsll $0,$0, 13
981 * dsll $0,$0, 29
982 * dsll $0,$0, 19*/
983#define __SPECIAL_INSTRUCTION_PREAMBLE \
984 "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \
985 "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
986
987#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
988 _zzq_default, _zzq_request, \
989 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
990 __extension__ \
991 ({ volatile unsigned long long int _zzq_args[6]; \
992 volatile unsigned long long int _zzq_result; \
993 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
994 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
995 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
996 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
997 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
998 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
999 __asm__ volatile("move $11, %1\n\t" /*default*/ \
1000 "move $12, %2\n\t" /*ptr*/ \
1001 __SPECIAL_INSTRUCTION_PREAMBLE \
1002 /* $11 = client_request ( $12 ) */ \
1003 "or $13, $13, $13\n\t" \
1004 "move %0, $11\n\t" /*result*/ \
1005 : "=r" (_zzq_result) \
1006 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
1007 : "$11", "$12"); \
1008 _zzq_result; \
1009 })
1010
1011#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1012 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1013 volatile unsigned long long int __addr; \
1014 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1015 /* $11 = guest_NRADDR */ \
1016 "or $14, $14, $14\n\t" \
1017 "move %0, $11" /*result*/ \
1018 : "=r" (__addr) \
1019 : \
1020 : "$11"); \
1021 _zzq_orig->nraddr = __addr; \
1022 }
1023
1024#define VALGRIND_CALL_NOREDIR_T9 \
1025 __SPECIAL_INSTRUCTION_PREAMBLE \
1026 /* call-noredir $25 */ \
1027 "or $15, $15, $15\n\t"
1028
1029#define VALGRIND_VEX_INJECT_IR() \
1030 do { \
1031 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1032 "or $11, $11, $11\n\t" \
1033 ); \
1034 } while (0)
1035
1036#endif /* PLAT_mips64_linux */
1037
sewardjf5c1a7f2006-10-17 01:32:48 +00001038/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +00001039
sewardj37091fb2002-11-16 11:06:50 +00001040#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +00001041
nethercote69d9c462004-10-26 13:00:12 +00001042
njn30d76c62005-06-18 15:07:39 +00001043/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +00001044/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +00001045/* ugly. It's the least-worst tradeoff I can think of. */
1046/* ------------------------------------------------------------------ */
1047
1048/* This section defines magic (a.k.a appalling-hack) macros for doing
1049 guaranteed-no-redirection macros, so as to get from function
1050 wrappers to the functions they are wrapping. The whole point is to
1051 construct standard call sequences, but to do the call itself with a
1052 special no-redirect call pseudo-instruction that the JIT
1053 understands and handles specially. This section is long and
1054 repetitious, and I can't see a way to make it shorter.
1055
1056 The naming scheme is as follows:
1057
1058 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
1059
1060 'W' stands for "word" and 'v' for "void". Hence there are
1061 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
1062 and for each, the possibility of returning a word-typed result, or
1063 no result.
1064*/
1065
1066/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +00001067 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
1068 the default behaviour equivalance class tag "0000" into the name.
1069 See pub_tool_redir.h for details -- normally you don't need to
1070 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +00001071
njn5f5ef2a2009-05-11 08:01:09 +00001072/* Use an extra level of macroisation so as to ensure the soname/fnname
1073 args are fully macro-expanded before pasting them together. */
1074#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
1075
sewardj0ec07f32006-01-12 12:32:32 +00001076#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001077 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +00001078
1079#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001080 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +00001081
sewardjd68ac3e2006-01-20 14:31:57 +00001082/* Use this macro from within a wrapper function to collect the
1083 context (address and possibly other info) of the original function.
1084 Once you have that you can then use it in one of the CALL_FN_
1085 macros. The type of the argument _lval is OrigFn. */
1086#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +00001087
sewardj573f8bc2012-06-05 07:12:15 +00001088/* Also provide end-user facilities for function replacement, rather
1089 than wrapping. A replacement function differs from a wrapper in
1090 that it has no way to get hold of the original function being
1091 called, and hence no way to call onwards to it. In a replacement
1092 function, VALGRIND_GET_ORIG_FN always returns zero. */
1093
1094#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
1095 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1096
1097#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
1098 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1099
sewardj0ec07f32006-01-12 12:32:32 +00001100/* Derivatives of the main macros below, for calling functions
1101 returning void. */
1102
1103#define CALL_FN_v_v(fnptr) \
1104 do { volatile unsigned long _junk; \
1105 CALL_FN_W_v(_junk,fnptr); } while (0)
1106
1107#define CALL_FN_v_W(fnptr, arg1) \
1108 do { volatile unsigned long _junk; \
1109 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1110
1111#define CALL_FN_v_WW(fnptr, arg1,arg2) \
1112 do { volatile unsigned long _junk; \
1113 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1114
sewardj5ce4b152006-03-11 12:57:41 +00001115#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
1116 do { volatile unsigned long _junk; \
1117 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1118
njn2b5f0a92009-05-19 01:24:50 +00001119#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
1120 do { volatile unsigned long _junk; \
1121 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1122
1123#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
1124 do { volatile unsigned long _junk; \
1125 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1126
1127#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
1128 do { volatile unsigned long _junk; \
1129 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1130
1131#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
1132 do { volatile unsigned long _junk; \
1133 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1134
njnf76d27a2009-05-28 01:53:07 +00001135/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001136
njnf76d27a2009-05-28 01:53:07 +00001137#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001138
1139/* These regs are trashed by the hidden call. No need to mention eax
1140 as gcc can already see that, plus causes gcc to bomb. */
1141#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1142
tom4118e0f2012-08-02 09:23:45 +00001143/* Macros to save and align the stack before making a function
1144 call and restore it afterwards as gcc may not keep the stack
1145 pointer aligned if it doesn't realise calls are being made
1146 to other functions. */
1147
1148#define VALGRIND_ALIGN_STACK \
1149 "movl %%esp,%%edi\n\t" \
1150 "andl $0xfffffff0,%%esp\n\t"
1151#define VALGRIND_RESTORE_STACK \
1152 "movl %%edi,%%esp\n\t"
1153
sewardj0ec07f32006-01-12 12:32:32 +00001154/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1155 long) == 4. */
1156
sewardj66226cc2006-01-20 15:46:46 +00001157#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001158 do { \
sewardj66226cc2006-01-20 15:46:46 +00001159 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001160 volatile unsigned long _argvec[1]; \
1161 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001162 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001163 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001164 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001165 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1166 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001167 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001168 : /*out*/ "=a" (_res) \
1169 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001170 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001171 ); \
1172 lval = (__typeof__(lval)) _res; \
1173 } while (0)
1174
sewardj66226cc2006-01-20 15:46:46 +00001175#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001176 do { \
sewardj66226cc2006-01-20 15:46:46 +00001177 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001178 volatile unsigned long _argvec[2]; \
1179 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001180 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001181 _argvec[1] = (unsigned long)(arg1); \
1182 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001183 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001184 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001185 "pushl 4(%%eax)\n\t" \
1186 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1187 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001188 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001189 : /*out*/ "=a" (_res) \
1190 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001191 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001192 ); \
1193 lval = (__typeof__(lval)) _res; \
1194 } while (0)
1195
sewardj66226cc2006-01-20 15:46:46 +00001196#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001197 do { \
sewardj66226cc2006-01-20 15:46:46 +00001198 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001199 volatile unsigned long _argvec[3]; \
1200 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001201 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001202 _argvec[1] = (unsigned long)(arg1); \
1203 _argvec[2] = (unsigned long)(arg2); \
1204 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001205 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001206 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001207 "pushl 8(%%eax)\n\t" \
1208 "pushl 4(%%eax)\n\t" \
1209 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1210 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001211 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001212 : /*out*/ "=a" (_res) \
1213 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001214 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001215 ); \
1216 lval = (__typeof__(lval)) _res; \
1217 } while (0)
1218
sewardj9e8b07a2006-02-18 21:13:29 +00001219#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1220 do { \
1221 volatile OrigFn _orig = (orig); \
1222 volatile unsigned long _argvec[4]; \
1223 volatile unsigned long _res; \
1224 _argvec[0] = (unsigned long)_orig.nraddr; \
1225 _argvec[1] = (unsigned long)(arg1); \
1226 _argvec[2] = (unsigned long)(arg2); \
1227 _argvec[3] = (unsigned long)(arg3); \
1228 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001229 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001230 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +00001231 "pushl 12(%%eax)\n\t" \
1232 "pushl 8(%%eax)\n\t" \
1233 "pushl 4(%%eax)\n\t" \
1234 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1235 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001236 VALGRIND_RESTORE_STACK \
sewardj9e8b07a2006-02-18 21:13:29 +00001237 : /*out*/ "=a" (_res) \
1238 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001239 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj9e8b07a2006-02-18 21:13:29 +00001240 ); \
1241 lval = (__typeof__(lval)) _res; \
1242 } while (0)
1243
sewardj66226cc2006-01-20 15:46:46 +00001244#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +00001245 do { \
sewardj66226cc2006-01-20 15:46:46 +00001246 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001247 volatile unsigned long _argvec[5]; \
1248 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001249 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001250 _argvec[1] = (unsigned long)(arg1); \
1251 _argvec[2] = (unsigned long)(arg2); \
1252 _argvec[3] = (unsigned long)(arg3); \
1253 _argvec[4] = (unsigned long)(arg4); \
1254 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001255 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001256 "pushl 16(%%eax)\n\t" \
1257 "pushl 12(%%eax)\n\t" \
1258 "pushl 8(%%eax)\n\t" \
1259 "pushl 4(%%eax)\n\t" \
1260 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1261 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001262 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001263 : /*out*/ "=a" (_res) \
1264 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001265 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001266 ); \
1267 lval = (__typeof__(lval)) _res; \
1268 } while (0)
1269
sewardj66226cc2006-01-20 15:46:46 +00001270#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +00001271 do { \
sewardj66226cc2006-01-20 15:46:46 +00001272 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001273 volatile unsigned long _argvec[6]; \
1274 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001275 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001276 _argvec[1] = (unsigned long)(arg1); \
1277 _argvec[2] = (unsigned long)(arg2); \
1278 _argvec[3] = (unsigned long)(arg3); \
1279 _argvec[4] = (unsigned long)(arg4); \
1280 _argvec[5] = (unsigned long)(arg5); \
1281 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001282 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001283 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001284 "pushl 20(%%eax)\n\t" \
1285 "pushl 16(%%eax)\n\t" \
1286 "pushl 12(%%eax)\n\t" \
1287 "pushl 8(%%eax)\n\t" \
1288 "pushl 4(%%eax)\n\t" \
1289 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1290 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001291 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001292 : /*out*/ "=a" (_res) \
1293 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001294 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001295 ); \
1296 lval = (__typeof__(lval)) _res; \
1297 } while (0)
1298
sewardj66226cc2006-01-20 15:46:46 +00001299#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +00001300 do { \
sewardj66226cc2006-01-20 15:46:46 +00001301 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001302 volatile unsigned long _argvec[7]; \
1303 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001304 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001305 _argvec[1] = (unsigned long)(arg1); \
1306 _argvec[2] = (unsigned long)(arg2); \
1307 _argvec[3] = (unsigned long)(arg3); \
1308 _argvec[4] = (unsigned long)(arg4); \
1309 _argvec[5] = (unsigned long)(arg5); \
1310 _argvec[6] = (unsigned long)(arg6); \
1311 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001312 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001313 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001314 "pushl 24(%%eax)\n\t" \
1315 "pushl 20(%%eax)\n\t" \
1316 "pushl 16(%%eax)\n\t" \
1317 "pushl 12(%%eax)\n\t" \
1318 "pushl 8(%%eax)\n\t" \
1319 "pushl 4(%%eax)\n\t" \
1320 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1321 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001322 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001323 : /*out*/ "=a" (_res) \
1324 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001325 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001326 ); \
1327 lval = (__typeof__(lval)) _res; \
1328 } while (0)
1329
sewardj66226cc2006-01-20 15:46:46 +00001330#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1331 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +00001332 do { \
sewardj66226cc2006-01-20 15:46:46 +00001333 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001334 volatile unsigned long _argvec[8]; \
1335 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001336 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001337 _argvec[1] = (unsigned long)(arg1); \
1338 _argvec[2] = (unsigned long)(arg2); \
1339 _argvec[3] = (unsigned long)(arg3); \
1340 _argvec[4] = (unsigned long)(arg4); \
1341 _argvec[5] = (unsigned long)(arg5); \
1342 _argvec[6] = (unsigned long)(arg6); \
1343 _argvec[7] = (unsigned long)(arg7); \
1344 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001345 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001346 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001347 "pushl 28(%%eax)\n\t" \
1348 "pushl 24(%%eax)\n\t" \
1349 "pushl 20(%%eax)\n\t" \
1350 "pushl 16(%%eax)\n\t" \
1351 "pushl 12(%%eax)\n\t" \
1352 "pushl 8(%%eax)\n\t" \
1353 "pushl 4(%%eax)\n\t" \
1354 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1355 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001356 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001357 : /*out*/ "=a" (_res) \
1358 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001359 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001360 ); \
1361 lval = (__typeof__(lval)) _res; \
1362 } while (0)
1363
sewardj66226cc2006-01-20 15:46:46 +00001364#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1365 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +00001366 do { \
sewardj66226cc2006-01-20 15:46:46 +00001367 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001368 volatile unsigned long _argvec[9]; \
1369 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001370 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001371 _argvec[1] = (unsigned long)(arg1); \
1372 _argvec[2] = (unsigned long)(arg2); \
1373 _argvec[3] = (unsigned long)(arg3); \
1374 _argvec[4] = (unsigned long)(arg4); \
1375 _argvec[5] = (unsigned long)(arg5); \
1376 _argvec[6] = (unsigned long)(arg6); \
1377 _argvec[7] = (unsigned long)(arg7); \
1378 _argvec[8] = (unsigned long)(arg8); \
1379 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001380 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001381 "pushl 32(%%eax)\n\t" \
1382 "pushl 28(%%eax)\n\t" \
1383 "pushl 24(%%eax)\n\t" \
1384 "pushl 20(%%eax)\n\t" \
1385 "pushl 16(%%eax)\n\t" \
1386 "pushl 12(%%eax)\n\t" \
1387 "pushl 8(%%eax)\n\t" \
1388 "pushl 4(%%eax)\n\t" \
1389 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1390 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001391 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001392 : /*out*/ "=a" (_res) \
1393 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001394 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001395 ); \
1396 lval = (__typeof__(lval)) _res; \
1397 } while (0)
1398
sewardj45fa5b02006-03-09 19:06:23 +00001399#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1400 arg7,arg8,arg9) \
1401 do { \
1402 volatile OrigFn _orig = (orig); \
1403 volatile unsigned long _argvec[10]; \
1404 volatile unsigned long _res; \
1405 _argvec[0] = (unsigned long)_orig.nraddr; \
1406 _argvec[1] = (unsigned long)(arg1); \
1407 _argvec[2] = (unsigned long)(arg2); \
1408 _argvec[3] = (unsigned long)(arg3); \
1409 _argvec[4] = (unsigned long)(arg4); \
1410 _argvec[5] = (unsigned long)(arg5); \
1411 _argvec[6] = (unsigned long)(arg6); \
1412 _argvec[7] = (unsigned long)(arg7); \
1413 _argvec[8] = (unsigned long)(arg8); \
1414 _argvec[9] = (unsigned long)(arg9); \
1415 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001416 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001417 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001418 "pushl 36(%%eax)\n\t" \
1419 "pushl 32(%%eax)\n\t" \
1420 "pushl 28(%%eax)\n\t" \
1421 "pushl 24(%%eax)\n\t" \
1422 "pushl 20(%%eax)\n\t" \
1423 "pushl 16(%%eax)\n\t" \
1424 "pushl 12(%%eax)\n\t" \
1425 "pushl 8(%%eax)\n\t" \
1426 "pushl 4(%%eax)\n\t" \
1427 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1428 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001429 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001430 : /*out*/ "=a" (_res) \
1431 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001432 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001433 ); \
1434 lval = (__typeof__(lval)) _res; \
1435 } while (0)
1436
1437#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1438 arg7,arg8,arg9,arg10) \
1439 do { \
1440 volatile OrigFn _orig = (orig); \
1441 volatile unsigned long _argvec[11]; \
1442 volatile unsigned long _res; \
1443 _argvec[0] = (unsigned long)_orig.nraddr; \
1444 _argvec[1] = (unsigned long)(arg1); \
1445 _argvec[2] = (unsigned long)(arg2); \
1446 _argvec[3] = (unsigned long)(arg3); \
1447 _argvec[4] = (unsigned long)(arg4); \
1448 _argvec[5] = (unsigned long)(arg5); \
1449 _argvec[6] = (unsigned long)(arg6); \
1450 _argvec[7] = (unsigned long)(arg7); \
1451 _argvec[8] = (unsigned long)(arg8); \
1452 _argvec[9] = (unsigned long)(arg9); \
1453 _argvec[10] = (unsigned long)(arg10); \
1454 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001455 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001456 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001457 "pushl 40(%%eax)\n\t" \
1458 "pushl 36(%%eax)\n\t" \
1459 "pushl 32(%%eax)\n\t" \
1460 "pushl 28(%%eax)\n\t" \
1461 "pushl 24(%%eax)\n\t" \
1462 "pushl 20(%%eax)\n\t" \
1463 "pushl 16(%%eax)\n\t" \
1464 "pushl 12(%%eax)\n\t" \
1465 "pushl 8(%%eax)\n\t" \
1466 "pushl 4(%%eax)\n\t" \
1467 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1468 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001469 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001470 : /*out*/ "=a" (_res) \
1471 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001472 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001473 ); \
1474 lval = (__typeof__(lval)) _res; \
1475 } while (0)
1476
sewardj5ce4b152006-03-11 12:57:41 +00001477#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1478 arg6,arg7,arg8,arg9,arg10, \
1479 arg11) \
1480 do { \
1481 volatile OrigFn _orig = (orig); \
1482 volatile unsigned long _argvec[12]; \
1483 volatile unsigned long _res; \
1484 _argvec[0] = (unsigned long)_orig.nraddr; \
1485 _argvec[1] = (unsigned long)(arg1); \
1486 _argvec[2] = (unsigned long)(arg2); \
1487 _argvec[3] = (unsigned long)(arg3); \
1488 _argvec[4] = (unsigned long)(arg4); \
1489 _argvec[5] = (unsigned long)(arg5); \
1490 _argvec[6] = (unsigned long)(arg6); \
1491 _argvec[7] = (unsigned long)(arg7); \
1492 _argvec[8] = (unsigned long)(arg8); \
1493 _argvec[9] = (unsigned long)(arg9); \
1494 _argvec[10] = (unsigned long)(arg10); \
1495 _argvec[11] = (unsigned long)(arg11); \
1496 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001497 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001498 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001499 "pushl 44(%%eax)\n\t" \
1500 "pushl 40(%%eax)\n\t" \
1501 "pushl 36(%%eax)\n\t" \
1502 "pushl 32(%%eax)\n\t" \
1503 "pushl 28(%%eax)\n\t" \
1504 "pushl 24(%%eax)\n\t" \
1505 "pushl 20(%%eax)\n\t" \
1506 "pushl 16(%%eax)\n\t" \
1507 "pushl 12(%%eax)\n\t" \
1508 "pushl 8(%%eax)\n\t" \
1509 "pushl 4(%%eax)\n\t" \
1510 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1511 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001512 VALGRIND_RESTORE_STACK \
sewardj5ce4b152006-03-11 12:57:41 +00001513 : /*out*/ "=a" (_res) \
1514 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001515 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj5ce4b152006-03-11 12:57:41 +00001516 ); \
1517 lval = (__typeof__(lval)) _res; \
1518 } while (0)
1519
sewardj66226cc2006-01-20 15:46:46 +00001520#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1521 arg6,arg7,arg8,arg9,arg10, \
1522 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001523 do { \
sewardj66226cc2006-01-20 15:46:46 +00001524 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001525 volatile unsigned long _argvec[13]; \
1526 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001527 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001528 _argvec[1] = (unsigned long)(arg1); \
1529 _argvec[2] = (unsigned long)(arg2); \
1530 _argvec[3] = (unsigned long)(arg3); \
1531 _argvec[4] = (unsigned long)(arg4); \
1532 _argvec[5] = (unsigned long)(arg5); \
1533 _argvec[6] = (unsigned long)(arg6); \
1534 _argvec[7] = (unsigned long)(arg7); \
1535 _argvec[8] = (unsigned long)(arg8); \
1536 _argvec[9] = (unsigned long)(arg9); \
1537 _argvec[10] = (unsigned long)(arg10); \
1538 _argvec[11] = (unsigned long)(arg11); \
1539 _argvec[12] = (unsigned long)(arg12); \
1540 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001541 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001542 "pushl 48(%%eax)\n\t" \
1543 "pushl 44(%%eax)\n\t" \
1544 "pushl 40(%%eax)\n\t" \
1545 "pushl 36(%%eax)\n\t" \
1546 "pushl 32(%%eax)\n\t" \
1547 "pushl 28(%%eax)\n\t" \
1548 "pushl 24(%%eax)\n\t" \
1549 "pushl 20(%%eax)\n\t" \
1550 "pushl 16(%%eax)\n\t" \
1551 "pushl 12(%%eax)\n\t" \
1552 "pushl 8(%%eax)\n\t" \
1553 "pushl 4(%%eax)\n\t" \
1554 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1555 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001556 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001557 : /*out*/ "=a" (_res) \
1558 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001559 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001560 ); \
1561 lval = (__typeof__(lval)) _res; \
1562 } while (0)
1563
njnf76d27a2009-05-28 01:53:07 +00001564#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001565
njnf76d27a2009-05-28 01:53:07 +00001566/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001567
njnf76d27a2009-05-28 01:53:07 +00001568#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001569
1570/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1571
1572/* These regs are trashed by the hidden call. */
1573#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1574 "rdi", "r8", "r9", "r10", "r11"
1575
sewardjdfa55cf2010-10-06 22:07:06 +00001576/* This is all pretty complex. It's so as to make stack unwinding
1577 work reliably. See bug 243270. The basic problem is the sub and
1578 add of 128 of %rsp in all of the following macros. If gcc believes
1579 the CFA is in %rsp, then unwinding may fail, because what's at the
1580 CFA is not what gcc "expected" when it constructs the CFIs for the
1581 places where the macros are instantiated.
1582
1583 But we can't just add a CFI annotation to increase the CFA offset
1584 by 128, to match the sub of 128 from %rsp, because we don't know
1585 whether gcc has chosen %rsp as the CFA at that point, or whether it
1586 has chosen some other register (eg, %rbp). In the latter case,
1587 adding a CFI annotation to change the CFA offset is simply wrong.
1588
1589 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001590 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001591 CFI annotation to say what the register is. We choose %rbp for
1592 this (perhaps perversely), because:
1593
1594 (1) %rbp is already subject to unwinding. If a new register was
1595 chosen then the unwinder would have to unwind it in all stack
1596 traces, which is expensive, and
1597
1598 (2) %rbp is already subject to precise exception updates in the
1599 JIT. If a new register was chosen, we'd have to have precise
1600 exceptions for it too, which reduces performance of the
1601 generated code.
1602
1603 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001604 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001605 list of trashed registers at the end of the inline assembly
1606 fragments; gcc won't allow %rbp to appear in that list. Hence
1607 instead we need to stash %rbp in %r15 for the duration of the asm,
1608 and say that %r15 is trashed instead. gcc seems happy to go with
1609 that.
1610
1611 Oh .. and this all needs to be conditionalised so that it is
1612 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001613 that don't support __builtin_dwarf_cfa. Furthermore, since
1614 this header file is freestanding, it has to be independent of
1615 config.h, and so the following conditionalisation cannot depend on
1616 configure time checks.
1617
1618 Although it's not clear from
1619 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1620 this expression excludes Darwin.
1621 .cfi directives in Darwin assembly appear to be completely
1622 different and I haven't investigated how they work.
1623
1624 For even more entertainment value, note we have to use the
1625 completely undocumented __builtin_dwarf_cfa(), which appears to
1626 really compute the CFA, whereas __builtin_frame_address(0) claims
1627 to but actually doesn't. See
1628 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001629*/
sewardj8d1dc152010-10-08 17:43:26 +00001630#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001631# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001632 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001633# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001634 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001635 "movq %2, %%rbp\n\t" \
1636 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001637 ".cfi_def_cfa rbp, 0\n\t"
1638# define VALGRIND_CFI_EPILOGUE \
1639 "movq %%r15, %%rbp\n\t" \
1640 ".cfi_restore_state\n\t"
1641#else
1642# define __FRAME_POINTER
1643# define VALGRIND_CFI_PROLOGUE
1644# define VALGRIND_CFI_EPILOGUE
1645#endif
1646
tom4118e0f2012-08-02 09:23:45 +00001647/* Macros to save and align the stack before making a function
1648 call and restore it afterwards as gcc may not keep the stack
1649 pointer aligned if it doesn't realise calls are being made
1650 to other functions. */
1651
1652#define VALGRIND_ALIGN_STACK \
1653 "movq %%rsp,%%r14\n\t" \
1654 "andq $0xfffffffffffffff0,%%rsp\n\t"
1655#define VALGRIND_RESTORE_STACK \
1656 "movq %%r14,%%rsp\n\t"
sewardjdfa55cf2010-10-06 22:07:06 +00001657
sewardj0ec07f32006-01-12 12:32:32 +00001658/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1659 long) == 8. */
1660
sewardja07c2e12007-11-09 23:09:50 +00001661/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1662 macros. In order not to trash the stack redzone, we need to drop
1663 %rsp by 128 before the hidden call, and restore afterwards. The
1664 nastyness is that it is only by luck that the stack still appears
1665 to be unwindable during the hidden call - since then the behaviour
1666 of any routine using this macro does not match what the CFI data
1667 says. Sigh.
1668
1669 Why is this important? Imagine that a wrapper has a stack
1670 allocated local, and passes to the hidden call, a pointer to it.
1671 Because gcc does not know about the hidden call, it may allocate
1672 that local in the redzone. Unfortunately the hidden call may then
1673 trash it before it comes to use it. So we must step clear of the
1674 redzone, for the duration of the hidden call, to make it safe.
1675
1676 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001677 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001678 self describing (none of this CFI nonsense) so at least messing
1679 with the stack pointer doesn't give a danger of non-unwindable
1680 stack. */
1681
tom4118e0f2012-08-02 09:23:45 +00001682#define CALL_FN_W_v(lval, orig) \
1683 do { \
1684 volatile OrigFn _orig = (orig); \
1685 volatile unsigned long _argvec[1]; \
1686 volatile unsigned long _res; \
1687 _argvec[0] = (unsigned long)_orig.nraddr; \
1688 __asm__ volatile( \
1689 VALGRIND_CFI_PROLOGUE \
1690 VALGRIND_ALIGN_STACK \
1691 "subq $128,%%rsp\n\t" \
1692 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1693 VALGRIND_CALL_NOREDIR_RAX \
1694 VALGRIND_RESTORE_STACK \
1695 VALGRIND_CFI_EPILOGUE \
1696 : /*out*/ "=a" (_res) \
1697 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1698 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1699 ); \
1700 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001701 } while (0)
1702
tom4118e0f2012-08-02 09:23:45 +00001703#define CALL_FN_W_W(lval, orig, arg1) \
1704 do { \
1705 volatile OrigFn _orig = (orig); \
1706 volatile unsigned long _argvec[2]; \
1707 volatile unsigned long _res; \
1708 _argvec[0] = (unsigned long)_orig.nraddr; \
1709 _argvec[1] = (unsigned long)(arg1); \
1710 __asm__ volatile( \
1711 VALGRIND_CFI_PROLOGUE \
1712 VALGRIND_ALIGN_STACK \
1713 "subq $128,%%rsp\n\t" \
1714 "movq 8(%%rax), %%rdi\n\t" \
1715 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1716 VALGRIND_CALL_NOREDIR_RAX \
1717 VALGRIND_RESTORE_STACK \
1718 VALGRIND_CFI_EPILOGUE \
1719 : /*out*/ "=a" (_res) \
1720 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1721 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1722 ); \
1723 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001724 } while (0)
1725
tom4118e0f2012-08-02 09:23:45 +00001726#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1727 do { \
1728 volatile OrigFn _orig = (orig); \
1729 volatile unsigned long _argvec[3]; \
1730 volatile unsigned long _res; \
1731 _argvec[0] = (unsigned long)_orig.nraddr; \
1732 _argvec[1] = (unsigned long)(arg1); \
1733 _argvec[2] = (unsigned long)(arg2); \
1734 __asm__ volatile( \
1735 VALGRIND_CFI_PROLOGUE \
1736 VALGRIND_ALIGN_STACK \
1737 "subq $128,%%rsp\n\t" \
1738 "movq 16(%%rax), %%rsi\n\t" \
1739 "movq 8(%%rax), %%rdi\n\t" \
1740 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1741 VALGRIND_CALL_NOREDIR_RAX \
1742 VALGRIND_RESTORE_STACK \
1743 VALGRIND_CFI_EPILOGUE \
1744 : /*out*/ "=a" (_res) \
1745 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1746 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1747 ); \
1748 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001749 } while (0)
1750
tom4118e0f2012-08-02 09:23:45 +00001751#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1752 do { \
1753 volatile OrigFn _orig = (orig); \
1754 volatile unsigned long _argvec[4]; \
1755 volatile unsigned long _res; \
1756 _argvec[0] = (unsigned long)_orig.nraddr; \
1757 _argvec[1] = (unsigned long)(arg1); \
1758 _argvec[2] = (unsigned long)(arg2); \
1759 _argvec[3] = (unsigned long)(arg3); \
1760 __asm__ volatile( \
1761 VALGRIND_CFI_PROLOGUE \
1762 VALGRIND_ALIGN_STACK \
1763 "subq $128,%%rsp\n\t" \
1764 "movq 24(%%rax), %%rdx\n\t" \
1765 "movq 16(%%rax), %%rsi\n\t" \
1766 "movq 8(%%rax), %%rdi\n\t" \
1767 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1768 VALGRIND_CALL_NOREDIR_RAX \
1769 VALGRIND_RESTORE_STACK \
1770 VALGRIND_CFI_EPILOGUE \
1771 : /*out*/ "=a" (_res) \
1772 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1773 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1774 ); \
1775 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001776 } while (0)
1777
tom4118e0f2012-08-02 09:23:45 +00001778#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1779 do { \
1780 volatile OrigFn _orig = (orig); \
1781 volatile unsigned long _argvec[5]; \
1782 volatile unsigned long _res; \
1783 _argvec[0] = (unsigned long)_orig.nraddr; \
1784 _argvec[1] = (unsigned long)(arg1); \
1785 _argvec[2] = (unsigned long)(arg2); \
1786 _argvec[3] = (unsigned long)(arg3); \
1787 _argvec[4] = (unsigned long)(arg4); \
1788 __asm__ volatile( \
1789 VALGRIND_CFI_PROLOGUE \
1790 VALGRIND_ALIGN_STACK \
1791 "subq $128,%%rsp\n\t" \
1792 "movq 32(%%rax), %%rcx\n\t" \
1793 "movq 24(%%rax), %%rdx\n\t" \
1794 "movq 16(%%rax), %%rsi\n\t" \
1795 "movq 8(%%rax), %%rdi\n\t" \
1796 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1797 VALGRIND_CALL_NOREDIR_RAX \
1798 VALGRIND_RESTORE_STACK \
1799 VALGRIND_CFI_EPILOGUE \
1800 : /*out*/ "=a" (_res) \
1801 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1802 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1803 ); \
1804 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001805 } while (0)
1806
tom4118e0f2012-08-02 09:23:45 +00001807#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1808 do { \
1809 volatile OrigFn _orig = (orig); \
1810 volatile unsigned long _argvec[6]; \
1811 volatile unsigned long _res; \
1812 _argvec[0] = (unsigned long)_orig.nraddr; \
1813 _argvec[1] = (unsigned long)(arg1); \
1814 _argvec[2] = (unsigned long)(arg2); \
1815 _argvec[3] = (unsigned long)(arg3); \
1816 _argvec[4] = (unsigned long)(arg4); \
1817 _argvec[5] = (unsigned long)(arg5); \
1818 __asm__ volatile( \
1819 VALGRIND_CFI_PROLOGUE \
1820 VALGRIND_ALIGN_STACK \
1821 "subq $128,%%rsp\n\t" \
1822 "movq 40(%%rax), %%r8\n\t" \
1823 "movq 32(%%rax), %%rcx\n\t" \
1824 "movq 24(%%rax), %%rdx\n\t" \
1825 "movq 16(%%rax), %%rsi\n\t" \
1826 "movq 8(%%rax), %%rdi\n\t" \
1827 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1828 VALGRIND_CALL_NOREDIR_RAX \
1829 VALGRIND_RESTORE_STACK \
1830 VALGRIND_CFI_EPILOGUE \
1831 : /*out*/ "=a" (_res) \
1832 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1833 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1834 ); \
1835 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001836 } while (0)
1837
tom4118e0f2012-08-02 09:23:45 +00001838#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1839 do { \
1840 volatile OrigFn _orig = (orig); \
1841 volatile unsigned long _argvec[7]; \
1842 volatile unsigned long _res; \
1843 _argvec[0] = (unsigned long)_orig.nraddr; \
1844 _argvec[1] = (unsigned long)(arg1); \
1845 _argvec[2] = (unsigned long)(arg2); \
1846 _argvec[3] = (unsigned long)(arg3); \
1847 _argvec[4] = (unsigned long)(arg4); \
1848 _argvec[5] = (unsigned long)(arg5); \
1849 _argvec[6] = (unsigned long)(arg6); \
1850 __asm__ volatile( \
1851 VALGRIND_CFI_PROLOGUE \
1852 VALGRIND_ALIGN_STACK \
1853 "subq $128,%%rsp\n\t" \
1854 "movq 48(%%rax), %%r9\n\t" \
1855 "movq 40(%%rax), %%r8\n\t" \
1856 "movq 32(%%rax), %%rcx\n\t" \
1857 "movq 24(%%rax), %%rdx\n\t" \
1858 "movq 16(%%rax), %%rsi\n\t" \
1859 "movq 8(%%rax), %%rdi\n\t" \
1860 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1861 VALGRIND_CALL_NOREDIR_RAX \
1862 VALGRIND_RESTORE_STACK \
1863 VALGRIND_CFI_EPILOGUE \
1864 : /*out*/ "=a" (_res) \
1865 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1866 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1867 ); \
1868 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001869 } while (0)
1870
tom4118e0f2012-08-02 09:23:45 +00001871#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1872 arg7) \
1873 do { \
1874 volatile OrigFn _orig = (orig); \
1875 volatile unsigned long _argvec[8]; \
1876 volatile unsigned long _res; \
1877 _argvec[0] = (unsigned long)_orig.nraddr; \
1878 _argvec[1] = (unsigned long)(arg1); \
1879 _argvec[2] = (unsigned long)(arg2); \
1880 _argvec[3] = (unsigned long)(arg3); \
1881 _argvec[4] = (unsigned long)(arg4); \
1882 _argvec[5] = (unsigned long)(arg5); \
1883 _argvec[6] = (unsigned long)(arg6); \
1884 _argvec[7] = (unsigned long)(arg7); \
1885 __asm__ volatile( \
1886 VALGRIND_CFI_PROLOGUE \
1887 VALGRIND_ALIGN_STACK \
1888 "subq $136,%%rsp\n\t" \
1889 "pushq 56(%%rax)\n\t" \
1890 "movq 48(%%rax), %%r9\n\t" \
1891 "movq 40(%%rax), %%r8\n\t" \
1892 "movq 32(%%rax), %%rcx\n\t" \
1893 "movq 24(%%rax), %%rdx\n\t" \
1894 "movq 16(%%rax), %%rsi\n\t" \
1895 "movq 8(%%rax), %%rdi\n\t" \
1896 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1897 VALGRIND_CALL_NOREDIR_RAX \
1898 VALGRIND_RESTORE_STACK \
1899 VALGRIND_CFI_EPILOGUE \
1900 : /*out*/ "=a" (_res) \
1901 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1902 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1903 ); \
1904 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001905 } while (0)
1906
tom4118e0f2012-08-02 09:23:45 +00001907#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1908 arg7,arg8) \
1909 do { \
1910 volatile OrigFn _orig = (orig); \
1911 volatile unsigned long _argvec[9]; \
1912 volatile unsigned long _res; \
1913 _argvec[0] = (unsigned long)_orig.nraddr; \
1914 _argvec[1] = (unsigned long)(arg1); \
1915 _argvec[2] = (unsigned long)(arg2); \
1916 _argvec[3] = (unsigned long)(arg3); \
1917 _argvec[4] = (unsigned long)(arg4); \
1918 _argvec[5] = (unsigned long)(arg5); \
1919 _argvec[6] = (unsigned long)(arg6); \
1920 _argvec[7] = (unsigned long)(arg7); \
1921 _argvec[8] = (unsigned long)(arg8); \
1922 __asm__ volatile( \
1923 VALGRIND_CFI_PROLOGUE \
1924 VALGRIND_ALIGN_STACK \
1925 "subq $128,%%rsp\n\t" \
1926 "pushq 64(%%rax)\n\t" \
1927 "pushq 56(%%rax)\n\t" \
1928 "movq 48(%%rax), %%r9\n\t" \
1929 "movq 40(%%rax), %%r8\n\t" \
1930 "movq 32(%%rax), %%rcx\n\t" \
1931 "movq 24(%%rax), %%rdx\n\t" \
1932 "movq 16(%%rax), %%rsi\n\t" \
1933 "movq 8(%%rax), %%rdi\n\t" \
1934 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1935 VALGRIND_CALL_NOREDIR_RAX \
1936 VALGRIND_RESTORE_STACK \
1937 VALGRIND_CFI_EPILOGUE \
1938 : /*out*/ "=a" (_res) \
1939 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1940 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1941 ); \
1942 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001943 } while (0)
1944
tom4118e0f2012-08-02 09:23:45 +00001945#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1946 arg7,arg8,arg9) \
1947 do { \
1948 volatile OrigFn _orig = (orig); \
1949 volatile unsigned long _argvec[10]; \
1950 volatile unsigned long _res; \
1951 _argvec[0] = (unsigned long)_orig.nraddr; \
1952 _argvec[1] = (unsigned long)(arg1); \
1953 _argvec[2] = (unsigned long)(arg2); \
1954 _argvec[3] = (unsigned long)(arg3); \
1955 _argvec[4] = (unsigned long)(arg4); \
1956 _argvec[5] = (unsigned long)(arg5); \
1957 _argvec[6] = (unsigned long)(arg6); \
1958 _argvec[7] = (unsigned long)(arg7); \
1959 _argvec[8] = (unsigned long)(arg8); \
1960 _argvec[9] = (unsigned long)(arg9); \
1961 __asm__ volatile( \
1962 VALGRIND_CFI_PROLOGUE \
1963 VALGRIND_ALIGN_STACK \
1964 "subq $136,%%rsp\n\t" \
1965 "pushq 72(%%rax)\n\t" \
1966 "pushq 64(%%rax)\n\t" \
1967 "pushq 56(%%rax)\n\t" \
1968 "movq 48(%%rax), %%r9\n\t" \
1969 "movq 40(%%rax), %%r8\n\t" \
1970 "movq 32(%%rax), %%rcx\n\t" \
1971 "movq 24(%%rax), %%rdx\n\t" \
1972 "movq 16(%%rax), %%rsi\n\t" \
1973 "movq 8(%%rax), %%rdi\n\t" \
1974 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1975 VALGRIND_CALL_NOREDIR_RAX \
1976 VALGRIND_RESTORE_STACK \
1977 VALGRIND_CFI_EPILOGUE \
1978 : /*out*/ "=a" (_res) \
1979 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1980 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1981 ); \
1982 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001983 } while (0)
1984
tom4118e0f2012-08-02 09:23:45 +00001985#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1986 arg7,arg8,arg9,arg10) \
1987 do { \
1988 volatile OrigFn _orig = (orig); \
1989 volatile unsigned long _argvec[11]; \
1990 volatile unsigned long _res; \
1991 _argvec[0] = (unsigned long)_orig.nraddr; \
1992 _argvec[1] = (unsigned long)(arg1); \
1993 _argvec[2] = (unsigned long)(arg2); \
1994 _argvec[3] = (unsigned long)(arg3); \
1995 _argvec[4] = (unsigned long)(arg4); \
1996 _argvec[5] = (unsigned long)(arg5); \
1997 _argvec[6] = (unsigned long)(arg6); \
1998 _argvec[7] = (unsigned long)(arg7); \
1999 _argvec[8] = (unsigned long)(arg8); \
2000 _argvec[9] = (unsigned long)(arg9); \
2001 _argvec[10] = (unsigned long)(arg10); \
2002 __asm__ volatile( \
2003 VALGRIND_CFI_PROLOGUE \
2004 VALGRIND_ALIGN_STACK \
2005 "subq $128,%%rsp\n\t" \
2006 "pushq 80(%%rax)\n\t" \
2007 "pushq 72(%%rax)\n\t" \
2008 "pushq 64(%%rax)\n\t" \
2009 "pushq 56(%%rax)\n\t" \
2010 "movq 48(%%rax), %%r9\n\t" \
2011 "movq 40(%%rax), %%r8\n\t" \
2012 "movq 32(%%rax), %%rcx\n\t" \
2013 "movq 24(%%rax), %%rdx\n\t" \
2014 "movq 16(%%rax), %%rsi\n\t" \
2015 "movq 8(%%rax), %%rdi\n\t" \
2016 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2017 VALGRIND_CALL_NOREDIR_RAX \
2018 VALGRIND_RESTORE_STACK \
2019 VALGRIND_CFI_EPILOGUE \
2020 : /*out*/ "=a" (_res) \
2021 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2022 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2023 ); \
2024 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002025 } while (0)
2026
tom4118e0f2012-08-02 09:23:45 +00002027#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2028 arg7,arg8,arg9,arg10,arg11) \
2029 do { \
2030 volatile OrigFn _orig = (orig); \
2031 volatile unsigned long _argvec[12]; \
2032 volatile unsigned long _res; \
2033 _argvec[0] = (unsigned long)_orig.nraddr; \
2034 _argvec[1] = (unsigned long)(arg1); \
2035 _argvec[2] = (unsigned long)(arg2); \
2036 _argvec[3] = (unsigned long)(arg3); \
2037 _argvec[4] = (unsigned long)(arg4); \
2038 _argvec[5] = (unsigned long)(arg5); \
2039 _argvec[6] = (unsigned long)(arg6); \
2040 _argvec[7] = (unsigned long)(arg7); \
2041 _argvec[8] = (unsigned long)(arg8); \
2042 _argvec[9] = (unsigned long)(arg9); \
2043 _argvec[10] = (unsigned long)(arg10); \
2044 _argvec[11] = (unsigned long)(arg11); \
2045 __asm__ volatile( \
2046 VALGRIND_CFI_PROLOGUE \
2047 VALGRIND_ALIGN_STACK \
2048 "subq $136,%%rsp\n\t" \
2049 "pushq 88(%%rax)\n\t" \
2050 "pushq 80(%%rax)\n\t" \
2051 "pushq 72(%%rax)\n\t" \
2052 "pushq 64(%%rax)\n\t" \
2053 "pushq 56(%%rax)\n\t" \
2054 "movq 48(%%rax), %%r9\n\t" \
2055 "movq 40(%%rax), %%r8\n\t" \
2056 "movq 32(%%rax), %%rcx\n\t" \
2057 "movq 24(%%rax), %%rdx\n\t" \
2058 "movq 16(%%rax), %%rsi\n\t" \
2059 "movq 8(%%rax), %%rdi\n\t" \
2060 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2061 VALGRIND_CALL_NOREDIR_RAX \
2062 VALGRIND_RESTORE_STACK \
2063 VALGRIND_CFI_EPILOGUE \
2064 : /*out*/ "=a" (_res) \
2065 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2066 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2067 ); \
2068 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002069 } while (0)
2070
tom4118e0f2012-08-02 09:23:45 +00002071#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2072 arg7,arg8,arg9,arg10,arg11,arg12) \
2073 do { \
2074 volatile OrigFn _orig = (orig); \
2075 volatile unsigned long _argvec[13]; \
2076 volatile unsigned long _res; \
2077 _argvec[0] = (unsigned long)_orig.nraddr; \
2078 _argvec[1] = (unsigned long)(arg1); \
2079 _argvec[2] = (unsigned long)(arg2); \
2080 _argvec[3] = (unsigned long)(arg3); \
2081 _argvec[4] = (unsigned long)(arg4); \
2082 _argvec[5] = (unsigned long)(arg5); \
2083 _argvec[6] = (unsigned long)(arg6); \
2084 _argvec[7] = (unsigned long)(arg7); \
2085 _argvec[8] = (unsigned long)(arg8); \
2086 _argvec[9] = (unsigned long)(arg9); \
2087 _argvec[10] = (unsigned long)(arg10); \
2088 _argvec[11] = (unsigned long)(arg11); \
2089 _argvec[12] = (unsigned long)(arg12); \
2090 __asm__ volatile( \
2091 VALGRIND_CFI_PROLOGUE \
2092 VALGRIND_ALIGN_STACK \
2093 "subq $128,%%rsp\n\t" \
2094 "pushq 96(%%rax)\n\t" \
2095 "pushq 88(%%rax)\n\t" \
2096 "pushq 80(%%rax)\n\t" \
2097 "pushq 72(%%rax)\n\t" \
2098 "pushq 64(%%rax)\n\t" \
2099 "pushq 56(%%rax)\n\t" \
2100 "movq 48(%%rax), %%r9\n\t" \
2101 "movq 40(%%rax), %%r8\n\t" \
2102 "movq 32(%%rax), %%rcx\n\t" \
2103 "movq 24(%%rax), %%rdx\n\t" \
2104 "movq 16(%%rax), %%rsi\n\t" \
2105 "movq 8(%%rax), %%rdi\n\t" \
2106 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2107 VALGRIND_CALL_NOREDIR_RAX \
2108 VALGRIND_RESTORE_STACK \
2109 VALGRIND_CFI_EPILOGUE \
2110 : /*out*/ "=a" (_res) \
2111 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2112 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2113 ); \
2114 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002115 } while (0)
2116
njnf76d27a2009-05-28 01:53:07 +00002117#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00002118
sewardjf5c1a7f2006-10-17 01:32:48 +00002119/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002120
sewardjf5c1a7f2006-10-17 01:32:48 +00002121#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00002122
sewardjead61df2006-03-12 13:39:15 +00002123/* This is useful for finding out about the on-stack stuff:
2124
2125 extern int f9 ( int,int,int,int,int,int,int,int,int );
2126 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2127 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2128 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2129
2130 int g9 ( void ) {
2131 return f9(11,22,33,44,55,66,77,88,99);
2132 }
2133 int g10 ( void ) {
2134 return f10(11,22,33,44,55,66,77,88,99,110);
2135 }
2136 int g11 ( void ) {
2137 return f11(11,22,33,44,55,66,77,88,99,110,121);
2138 }
2139 int g12 ( void ) {
2140 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2141 }
2142*/
2143
sewardj0ec07f32006-01-12 12:32:32 +00002144/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2145
2146/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00002147#define __CALLER_SAVED_REGS \
2148 "lr", "ctr", "xer", \
2149 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2150 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2151 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00002152
tom4118e0f2012-08-02 09:23:45 +00002153/* Macros to save and align the stack before making a function
2154 call and restore it afterwards as gcc may not keep the stack
2155 pointer aligned if it doesn't realise calls are being made
2156 to other functions. */
2157
2158#define VALGRIND_ALIGN_STACK \
2159 "mr 28,1\n\t" \
2160 "rlwinm 1,1,0,0,27\n\t"
2161#define VALGRIND_RESTORE_STACK \
2162 "mr 1,28\n\t"
2163
sewardjead61df2006-03-12 13:39:15 +00002164/* These CALL_FN_ macros assume that on ppc32-linux,
2165 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00002166
sewardj38de0992006-01-20 16:46:34 +00002167#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00002168 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002169 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002170 volatile unsigned long _argvec[1]; \
2171 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002172 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002173 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002174 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002175 "mr 11,%1\n\t" \
2176 "lwz 11,0(11)\n\t" /* target->r11 */ \
2177 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002178 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002179 "mr %0,3" \
2180 : /*out*/ "=r" (_res) \
2181 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002182 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002183 ); \
2184 lval = (__typeof__(lval)) _res; \
2185 } while (0)
2186
sewardj38de0992006-01-20 16:46:34 +00002187#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00002188 do { \
sewardj38de0992006-01-20 16:46:34 +00002189 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002190 volatile unsigned long _argvec[2]; \
2191 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002192 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002193 _argvec[1] = (unsigned long)arg1; \
2194 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002195 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002196 "mr 11,%1\n\t" \
2197 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2198 "lwz 11,0(11)\n\t" /* target->r11 */ \
2199 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002200 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002201 "mr %0,3" \
2202 : /*out*/ "=r" (_res) \
2203 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002204 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002205 ); \
2206 lval = (__typeof__(lval)) _res; \
2207 } while (0)
2208
sewardj38de0992006-01-20 16:46:34 +00002209#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00002210 do { \
sewardj38de0992006-01-20 16:46:34 +00002211 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002212 volatile unsigned long _argvec[3]; \
2213 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002214 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002215 _argvec[1] = (unsigned long)arg1; \
2216 _argvec[2] = (unsigned long)arg2; \
2217 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002218 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002219 "mr 11,%1\n\t" \
2220 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2221 "lwz 4,8(11)\n\t" \
2222 "lwz 11,0(11)\n\t" /* target->r11 */ \
2223 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002224 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002225 "mr %0,3" \
2226 : /*out*/ "=r" (_res) \
2227 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002228 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002229 ); \
2230 lval = (__typeof__(lval)) _res; \
2231 } while (0)
2232
sewardjead61df2006-03-12 13:39:15 +00002233#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2234 do { \
2235 volatile OrigFn _orig = (orig); \
2236 volatile unsigned long _argvec[4]; \
2237 volatile unsigned long _res; \
2238 _argvec[0] = (unsigned long)_orig.nraddr; \
2239 _argvec[1] = (unsigned long)arg1; \
2240 _argvec[2] = (unsigned long)arg2; \
2241 _argvec[3] = (unsigned long)arg3; \
2242 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002243 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002244 "mr 11,%1\n\t" \
2245 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2246 "lwz 4,8(11)\n\t" \
2247 "lwz 5,12(11)\n\t" \
2248 "lwz 11,0(11)\n\t" /* target->r11 */ \
2249 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002250 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002251 "mr %0,3" \
2252 : /*out*/ "=r" (_res) \
2253 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002254 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002255 ); \
2256 lval = (__typeof__(lval)) _res; \
2257 } while (0)
2258
2259#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2260 do { \
2261 volatile OrigFn _orig = (orig); \
2262 volatile unsigned long _argvec[5]; \
2263 volatile unsigned long _res; \
2264 _argvec[0] = (unsigned long)_orig.nraddr; \
2265 _argvec[1] = (unsigned long)arg1; \
2266 _argvec[2] = (unsigned long)arg2; \
2267 _argvec[3] = (unsigned long)arg3; \
2268 _argvec[4] = (unsigned long)arg4; \
2269 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002270 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002271 "mr 11,%1\n\t" \
2272 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2273 "lwz 4,8(11)\n\t" \
2274 "lwz 5,12(11)\n\t" \
2275 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2276 "lwz 11,0(11)\n\t" /* target->r11 */ \
2277 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002278 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002279 "mr %0,3" \
2280 : /*out*/ "=r" (_res) \
2281 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002282 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002283 ); \
2284 lval = (__typeof__(lval)) _res; \
2285 } while (0)
2286
2287#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2288 do { \
2289 volatile OrigFn _orig = (orig); \
2290 volatile unsigned long _argvec[6]; \
2291 volatile unsigned long _res; \
2292 _argvec[0] = (unsigned long)_orig.nraddr; \
2293 _argvec[1] = (unsigned long)arg1; \
2294 _argvec[2] = (unsigned long)arg2; \
2295 _argvec[3] = (unsigned long)arg3; \
2296 _argvec[4] = (unsigned long)arg4; \
2297 _argvec[5] = (unsigned long)arg5; \
2298 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002299 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002300 "mr 11,%1\n\t" \
2301 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2302 "lwz 4,8(11)\n\t" \
2303 "lwz 5,12(11)\n\t" \
2304 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2305 "lwz 7,20(11)\n\t" \
2306 "lwz 11,0(11)\n\t" /* target->r11 */ \
2307 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002308 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002309 "mr %0,3" \
2310 : /*out*/ "=r" (_res) \
2311 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002312 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002313 ); \
2314 lval = (__typeof__(lval)) _res; \
2315 } while (0)
2316
2317#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2318 do { \
2319 volatile OrigFn _orig = (orig); \
2320 volatile unsigned long _argvec[7]; \
2321 volatile unsigned long _res; \
2322 _argvec[0] = (unsigned long)_orig.nraddr; \
2323 _argvec[1] = (unsigned long)arg1; \
2324 _argvec[2] = (unsigned long)arg2; \
2325 _argvec[3] = (unsigned long)arg3; \
2326 _argvec[4] = (unsigned long)arg4; \
2327 _argvec[5] = (unsigned long)arg5; \
2328 _argvec[6] = (unsigned long)arg6; \
2329 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002330 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002331 "mr 11,%1\n\t" \
2332 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2333 "lwz 4,8(11)\n\t" \
2334 "lwz 5,12(11)\n\t" \
2335 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2336 "lwz 7,20(11)\n\t" \
2337 "lwz 8,24(11)\n\t" \
2338 "lwz 11,0(11)\n\t" /* target->r11 */ \
2339 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002340 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002341 "mr %0,3" \
2342 : /*out*/ "=r" (_res) \
2343 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002344 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002345 ); \
2346 lval = (__typeof__(lval)) _res; \
2347 } while (0)
2348
2349#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2350 arg7) \
2351 do { \
2352 volatile OrigFn _orig = (orig); \
2353 volatile unsigned long _argvec[8]; \
2354 volatile unsigned long _res; \
2355 _argvec[0] = (unsigned long)_orig.nraddr; \
2356 _argvec[1] = (unsigned long)arg1; \
2357 _argvec[2] = (unsigned long)arg2; \
2358 _argvec[3] = (unsigned long)arg3; \
2359 _argvec[4] = (unsigned long)arg4; \
2360 _argvec[5] = (unsigned long)arg5; \
2361 _argvec[6] = (unsigned long)arg6; \
2362 _argvec[7] = (unsigned long)arg7; \
2363 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002364 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002365 "mr 11,%1\n\t" \
2366 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2367 "lwz 4,8(11)\n\t" \
2368 "lwz 5,12(11)\n\t" \
2369 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2370 "lwz 7,20(11)\n\t" \
2371 "lwz 8,24(11)\n\t" \
2372 "lwz 9,28(11)\n\t" \
2373 "lwz 11,0(11)\n\t" /* target->r11 */ \
2374 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002375 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002376 "mr %0,3" \
2377 : /*out*/ "=r" (_res) \
2378 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002379 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002380 ); \
2381 lval = (__typeof__(lval)) _res; \
2382 } while (0)
2383
2384#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2385 arg7,arg8) \
2386 do { \
2387 volatile OrigFn _orig = (orig); \
2388 volatile unsigned long _argvec[9]; \
2389 volatile unsigned long _res; \
2390 _argvec[0] = (unsigned long)_orig.nraddr; \
2391 _argvec[1] = (unsigned long)arg1; \
2392 _argvec[2] = (unsigned long)arg2; \
2393 _argvec[3] = (unsigned long)arg3; \
2394 _argvec[4] = (unsigned long)arg4; \
2395 _argvec[5] = (unsigned long)arg5; \
2396 _argvec[6] = (unsigned long)arg6; \
2397 _argvec[7] = (unsigned long)arg7; \
2398 _argvec[8] = (unsigned long)arg8; \
2399 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002400 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002401 "mr 11,%1\n\t" \
2402 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2403 "lwz 4,8(11)\n\t" \
2404 "lwz 5,12(11)\n\t" \
2405 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2406 "lwz 7,20(11)\n\t" \
2407 "lwz 8,24(11)\n\t" \
2408 "lwz 9,28(11)\n\t" \
2409 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2410 "lwz 11,0(11)\n\t" /* target->r11 */ \
2411 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002412 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002413 "mr %0,3" \
2414 : /*out*/ "=r" (_res) \
2415 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002416 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002417 ); \
2418 lval = (__typeof__(lval)) _res; \
2419 } while (0)
2420
2421#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2422 arg7,arg8,arg9) \
2423 do { \
2424 volatile OrigFn _orig = (orig); \
2425 volatile unsigned long _argvec[10]; \
2426 volatile unsigned long _res; \
2427 _argvec[0] = (unsigned long)_orig.nraddr; \
2428 _argvec[1] = (unsigned long)arg1; \
2429 _argvec[2] = (unsigned long)arg2; \
2430 _argvec[3] = (unsigned long)arg3; \
2431 _argvec[4] = (unsigned long)arg4; \
2432 _argvec[5] = (unsigned long)arg5; \
2433 _argvec[6] = (unsigned long)arg6; \
2434 _argvec[7] = (unsigned long)arg7; \
2435 _argvec[8] = (unsigned long)arg8; \
2436 _argvec[9] = (unsigned long)arg9; \
2437 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002438 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002439 "mr 11,%1\n\t" \
2440 "addi 1,1,-16\n\t" \
2441 /* arg9 */ \
2442 "lwz 3,36(11)\n\t" \
2443 "stw 3,8(1)\n\t" \
2444 /* args1-8 */ \
2445 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2446 "lwz 4,8(11)\n\t" \
2447 "lwz 5,12(11)\n\t" \
2448 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2449 "lwz 7,20(11)\n\t" \
2450 "lwz 8,24(11)\n\t" \
2451 "lwz 9,28(11)\n\t" \
2452 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2453 "lwz 11,0(11)\n\t" /* target->r11 */ \
2454 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002455 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002456 "mr %0,3" \
2457 : /*out*/ "=r" (_res) \
2458 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002459 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002460 ); \
2461 lval = (__typeof__(lval)) _res; \
2462 } while (0)
2463
2464#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2465 arg7,arg8,arg9,arg10) \
2466 do { \
2467 volatile OrigFn _orig = (orig); \
2468 volatile unsigned long _argvec[11]; \
2469 volatile unsigned long _res; \
2470 _argvec[0] = (unsigned long)_orig.nraddr; \
2471 _argvec[1] = (unsigned long)arg1; \
2472 _argvec[2] = (unsigned long)arg2; \
2473 _argvec[3] = (unsigned long)arg3; \
2474 _argvec[4] = (unsigned long)arg4; \
2475 _argvec[5] = (unsigned long)arg5; \
2476 _argvec[6] = (unsigned long)arg6; \
2477 _argvec[7] = (unsigned long)arg7; \
2478 _argvec[8] = (unsigned long)arg8; \
2479 _argvec[9] = (unsigned long)arg9; \
2480 _argvec[10] = (unsigned long)arg10; \
2481 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002482 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002483 "mr 11,%1\n\t" \
2484 "addi 1,1,-16\n\t" \
2485 /* arg10 */ \
2486 "lwz 3,40(11)\n\t" \
2487 "stw 3,12(1)\n\t" \
2488 /* arg9 */ \
2489 "lwz 3,36(11)\n\t" \
2490 "stw 3,8(1)\n\t" \
2491 /* args1-8 */ \
2492 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2493 "lwz 4,8(11)\n\t" \
2494 "lwz 5,12(11)\n\t" \
2495 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2496 "lwz 7,20(11)\n\t" \
2497 "lwz 8,24(11)\n\t" \
2498 "lwz 9,28(11)\n\t" \
2499 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2500 "lwz 11,0(11)\n\t" /* target->r11 */ \
2501 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002502 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002503 "mr %0,3" \
2504 : /*out*/ "=r" (_res) \
2505 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002506 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002507 ); \
2508 lval = (__typeof__(lval)) _res; \
2509 } while (0)
2510
2511#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2512 arg7,arg8,arg9,arg10,arg11) \
2513 do { \
2514 volatile OrigFn _orig = (orig); \
2515 volatile unsigned long _argvec[12]; \
2516 volatile unsigned long _res; \
2517 _argvec[0] = (unsigned long)_orig.nraddr; \
2518 _argvec[1] = (unsigned long)arg1; \
2519 _argvec[2] = (unsigned long)arg2; \
2520 _argvec[3] = (unsigned long)arg3; \
2521 _argvec[4] = (unsigned long)arg4; \
2522 _argvec[5] = (unsigned long)arg5; \
2523 _argvec[6] = (unsigned long)arg6; \
2524 _argvec[7] = (unsigned long)arg7; \
2525 _argvec[8] = (unsigned long)arg8; \
2526 _argvec[9] = (unsigned long)arg9; \
2527 _argvec[10] = (unsigned long)arg10; \
2528 _argvec[11] = (unsigned long)arg11; \
2529 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002530 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002531 "mr 11,%1\n\t" \
2532 "addi 1,1,-32\n\t" \
2533 /* arg11 */ \
2534 "lwz 3,44(11)\n\t" \
2535 "stw 3,16(1)\n\t" \
2536 /* arg10 */ \
2537 "lwz 3,40(11)\n\t" \
2538 "stw 3,12(1)\n\t" \
2539 /* arg9 */ \
2540 "lwz 3,36(11)\n\t" \
2541 "stw 3,8(1)\n\t" \
2542 /* args1-8 */ \
2543 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2544 "lwz 4,8(11)\n\t" \
2545 "lwz 5,12(11)\n\t" \
2546 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2547 "lwz 7,20(11)\n\t" \
2548 "lwz 8,24(11)\n\t" \
2549 "lwz 9,28(11)\n\t" \
2550 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2551 "lwz 11,0(11)\n\t" /* target->r11 */ \
2552 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002553 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002554 "mr %0,3" \
2555 : /*out*/ "=r" (_res) \
2556 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002557 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002558 ); \
2559 lval = (__typeof__(lval)) _res; \
2560 } while (0)
2561
2562#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2563 arg7,arg8,arg9,arg10,arg11,arg12) \
2564 do { \
2565 volatile OrigFn _orig = (orig); \
2566 volatile unsigned long _argvec[13]; \
2567 volatile unsigned long _res; \
2568 _argvec[0] = (unsigned long)_orig.nraddr; \
2569 _argvec[1] = (unsigned long)arg1; \
2570 _argvec[2] = (unsigned long)arg2; \
2571 _argvec[3] = (unsigned long)arg3; \
2572 _argvec[4] = (unsigned long)arg4; \
2573 _argvec[5] = (unsigned long)arg5; \
2574 _argvec[6] = (unsigned long)arg6; \
2575 _argvec[7] = (unsigned long)arg7; \
2576 _argvec[8] = (unsigned long)arg8; \
2577 _argvec[9] = (unsigned long)arg9; \
2578 _argvec[10] = (unsigned long)arg10; \
2579 _argvec[11] = (unsigned long)arg11; \
2580 _argvec[12] = (unsigned long)arg12; \
2581 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002582 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002583 "mr 11,%1\n\t" \
2584 "addi 1,1,-32\n\t" \
2585 /* arg12 */ \
2586 "lwz 3,48(11)\n\t" \
2587 "stw 3,20(1)\n\t" \
2588 /* arg11 */ \
2589 "lwz 3,44(11)\n\t" \
2590 "stw 3,16(1)\n\t" \
2591 /* arg10 */ \
2592 "lwz 3,40(11)\n\t" \
2593 "stw 3,12(1)\n\t" \
2594 /* arg9 */ \
2595 "lwz 3,36(11)\n\t" \
2596 "stw 3,8(1)\n\t" \
2597 /* args1-8 */ \
2598 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2599 "lwz 4,8(11)\n\t" \
2600 "lwz 5,12(11)\n\t" \
2601 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2602 "lwz 7,20(11)\n\t" \
2603 "lwz 8,24(11)\n\t" \
2604 "lwz 9,28(11)\n\t" \
2605 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2606 "lwz 11,0(11)\n\t" /* target->r11 */ \
2607 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002608 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002609 "mr %0,3" \
2610 : /*out*/ "=r" (_res) \
2611 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002612 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002613 ); \
2614 lval = (__typeof__(lval)) _res; \
2615 } while (0)
2616
sewardjf5c1a7f2006-10-17 01:32:48 +00002617#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002618
sewardjf5c1a7f2006-10-17 01:32:48 +00002619/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002620
carllcae0cc22014-08-07 23:17:29 +00002621#if defined(PLAT_ppc64be_linux)
sewardj9734b202006-01-17 01:49:37 +00002622
2623/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2624
2625/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002626#define __CALLER_SAVED_REGS \
2627 "lr", "ctr", "xer", \
2628 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2629 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2630 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002631
tom4118e0f2012-08-02 09:23:45 +00002632/* Macros to save and align the stack before making a function
2633 call and restore it afterwards as gcc may not keep the stack
2634 pointer aligned if it doesn't realise calls are being made
2635 to other functions. */
2636
2637#define VALGRIND_ALIGN_STACK \
2638 "mr 28,1\n\t" \
2639 "rldicr 1,1,0,59\n\t"
2640#define VALGRIND_RESTORE_STACK \
2641 "mr 1,28\n\t"
2642
sewardj9734b202006-01-17 01:49:37 +00002643/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2644 long) == 8. */
2645
sewardjd68ac3e2006-01-20 14:31:57 +00002646#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002647 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002648 volatile OrigFn _orig = (orig); \
2649 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002650 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002651 /* _argvec[0] holds current r2 across the call */ \
2652 _argvec[1] = (unsigned long)_orig.r2; \
2653 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002654 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002655 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002656 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002657 "std 2,-16(11)\n\t" /* save tocptr */ \
2658 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2659 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002660 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2661 "mr 11,%1\n\t" \
2662 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002663 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2664 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002665 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002666 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002667 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002668 ); \
2669 lval = (__typeof__(lval)) _res; \
2670 } while (0)
2671
sewardjd68ac3e2006-01-20 14:31:57 +00002672#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002673 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002674 volatile OrigFn _orig = (orig); \
2675 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002676 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002677 /* _argvec[0] holds current r2 across the call */ \
2678 _argvec[1] = (unsigned long)_orig.r2; \
2679 _argvec[2] = (unsigned long)_orig.nraddr; \
2680 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002681 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002682 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002683 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002684 "std 2,-16(11)\n\t" /* save tocptr */ \
2685 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2686 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2687 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002688 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2689 "mr 11,%1\n\t" \
2690 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002691 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2692 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002693 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002694 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002695 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002696 ); \
2697 lval = (__typeof__(lval)) _res; \
2698 } while (0)
2699
sewardjd68ac3e2006-01-20 14:31:57 +00002700#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002701 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002702 volatile OrigFn _orig = (orig); \
2703 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002704 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002705 /* _argvec[0] holds current r2 across the call */ \
2706 _argvec[1] = (unsigned long)_orig.r2; \
2707 _argvec[2] = (unsigned long)_orig.nraddr; \
2708 _argvec[2+1] = (unsigned long)arg1; \
2709 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002710 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002711 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002712 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002713 "std 2,-16(11)\n\t" /* save tocptr */ \
2714 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2715 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002716 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002717 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002718 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2719 "mr 11,%1\n\t" \
2720 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002721 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2722 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002723 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002724 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002725 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002726 ); \
2727 lval = (__typeof__(lval)) _res; \
2728 } while (0)
2729
sewardjcd636392006-03-12 16:48:14 +00002730#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2731 do { \
2732 volatile OrigFn _orig = (orig); \
2733 volatile unsigned long _argvec[3+3]; \
2734 volatile unsigned long _res; \
2735 /* _argvec[0] holds current r2 across the call */ \
2736 _argvec[1] = (unsigned long)_orig.r2; \
2737 _argvec[2] = (unsigned long)_orig.nraddr; \
2738 _argvec[2+1] = (unsigned long)arg1; \
2739 _argvec[2+2] = (unsigned long)arg2; \
2740 _argvec[2+3] = (unsigned long)arg3; \
2741 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002742 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002743 "mr 11,%1\n\t" \
2744 "std 2,-16(11)\n\t" /* save tocptr */ \
2745 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2746 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2747 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2748 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2749 "ld 11, 0(11)\n\t" /* target->r11 */ \
2750 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2751 "mr 11,%1\n\t" \
2752 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002753 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2754 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002755 : /*out*/ "=r" (_res) \
2756 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002757 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002758 ); \
2759 lval = (__typeof__(lval)) _res; \
2760 } while (0)
2761
2762#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2763 do { \
2764 volatile OrigFn _orig = (orig); \
2765 volatile unsigned long _argvec[3+4]; \
2766 volatile unsigned long _res; \
2767 /* _argvec[0] holds current r2 across the call */ \
2768 _argvec[1] = (unsigned long)_orig.r2; \
2769 _argvec[2] = (unsigned long)_orig.nraddr; \
2770 _argvec[2+1] = (unsigned long)arg1; \
2771 _argvec[2+2] = (unsigned long)arg2; \
2772 _argvec[2+3] = (unsigned long)arg3; \
2773 _argvec[2+4] = (unsigned long)arg4; \
2774 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002775 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002776 "mr 11,%1\n\t" \
2777 "std 2,-16(11)\n\t" /* save tocptr */ \
2778 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2779 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2780 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2781 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2782 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2783 "ld 11, 0(11)\n\t" /* target->r11 */ \
2784 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2785 "mr 11,%1\n\t" \
2786 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002787 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2788 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002789 : /*out*/ "=r" (_res) \
2790 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002791 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002792 ); \
2793 lval = (__typeof__(lval)) _res; \
2794 } while (0)
2795
2796#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2797 do { \
2798 volatile OrigFn _orig = (orig); \
2799 volatile unsigned long _argvec[3+5]; \
2800 volatile unsigned long _res; \
2801 /* _argvec[0] holds current r2 across the call */ \
2802 _argvec[1] = (unsigned long)_orig.r2; \
2803 _argvec[2] = (unsigned long)_orig.nraddr; \
2804 _argvec[2+1] = (unsigned long)arg1; \
2805 _argvec[2+2] = (unsigned long)arg2; \
2806 _argvec[2+3] = (unsigned long)arg3; \
2807 _argvec[2+4] = (unsigned long)arg4; \
2808 _argvec[2+5] = (unsigned long)arg5; \
2809 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002810 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002811 "mr 11,%1\n\t" \
2812 "std 2,-16(11)\n\t" /* save tocptr */ \
2813 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2814 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2815 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2816 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2817 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2818 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2819 "ld 11, 0(11)\n\t" /* target->r11 */ \
2820 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2821 "mr 11,%1\n\t" \
2822 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002823 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2824 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002825 : /*out*/ "=r" (_res) \
2826 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002827 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002828 ); \
2829 lval = (__typeof__(lval)) _res; \
2830 } while (0)
2831
2832#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2833 do { \
2834 volatile OrigFn _orig = (orig); \
2835 volatile unsigned long _argvec[3+6]; \
2836 volatile unsigned long _res; \
2837 /* _argvec[0] holds current r2 across the call */ \
2838 _argvec[1] = (unsigned long)_orig.r2; \
2839 _argvec[2] = (unsigned long)_orig.nraddr; \
2840 _argvec[2+1] = (unsigned long)arg1; \
2841 _argvec[2+2] = (unsigned long)arg2; \
2842 _argvec[2+3] = (unsigned long)arg3; \
2843 _argvec[2+4] = (unsigned long)arg4; \
2844 _argvec[2+5] = (unsigned long)arg5; \
2845 _argvec[2+6] = (unsigned long)arg6; \
2846 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002847 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002848 "mr 11,%1\n\t" \
2849 "std 2,-16(11)\n\t" /* save tocptr */ \
2850 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2851 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2852 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2853 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2854 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2855 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2856 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2857 "ld 11, 0(11)\n\t" /* target->r11 */ \
2858 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2859 "mr 11,%1\n\t" \
2860 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002861 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2862 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002863 : /*out*/ "=r" (_res) \
2864 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002865 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002866 ); \
2867 lval = (__typeof__(lval)) _res; \
2868 } while (0)
2869
2870#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2871 arg7) \
2872 do { \
2873 volatile OrigFn _orig = (orig); \
2874 volatile unsigned long _argvec[3+7]; \
2875 volatile unsigned long _res; \
2876 /* _argvec[0] holds current r2 across the call */ \
2877 _argvec[1] = (unsigned long)_orig.r2; \
2878 _argvec[2] = (unsigned long)_orig.nraddr; \
2879 _argvec[2+1] = (unsigned long)arg1; \
2880 _argvec[2+2] = (unsigned long)arg2; \
2881 _argvec[2+3] = (unsigned long)arg3; \
2882 _argvec[2+4] = (unsigned long)arg4; \
2883 _argvec[2+5] = (unsigned long)arg5; \
2884 _argvec[2+6] = (unsigned long)arg6; \
2885 _argvec[2+7] = (unsigned long)arg7; \
2886 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002887 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002888 "mr 11,%1\n\t" \
2889 "std 2,-16(11)\n\t" /* save tocptr */ \
2890 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2891 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2892 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2893 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2894 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2895 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2896 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2897 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2898 "ld 11, 0(11)\n\t" /* target->r11 */ \
2899 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2900 "mr 11,%1\n\t" \
2901 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002902 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2903 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002904 : /*out*/ "=r" (_res) \
2905 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002906 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002907 ); \
2908 lval = (__typeof__(lval)) _res; \
2909 } while (0)
2910
2911#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2912 arg7,arg8) \
2913 do { \
2914 volatile OrigFn _orig = (orig); \
2915 volatile unsigned long _argvec[3+8]; \
2916 volatile unsigned long _res; \
2917 /* _argvec[0] holds current r2 across the call */ \
2918 _argvec[1] = (unsigned long)_orig.r2; \
2919 _argvec[2] = (unsigned long)_orig.nraddr; \
2920 _argvec[2+1] = (unsigned long)arg1; \
2921 _argvec[2+2] = (unsigned long)arg2; \
2922 _argvec[2+3] = (unsigned long)arg3; \
2923 _argvec[2+4] = (unsigned long)arg4; \
2924 _argvec[2+5] = (unsigned long)arg5; \
2925 _argvec[2+6] = (unsigned long)arg6; \
2926 _argvec[2+7] = (unsigned long)arg7; \
2927 _argvec[2+8] = (unsigned long)arg8; \
2928 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002929 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002930 "mr 11,%1\n\t" \
2931 "std 2,-16(11)\n\t" /* save tocptr */ \
2932 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2933 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2934 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2935 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2936 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2937 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2938 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2939 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2940 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2941 "ld 11, 0(11)\n\t" /* target->r11 */ \
2942 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2943 "mr 11,%1\n\t" \
2944 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002945 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2946 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002947 : /*out*/ "=r" (_res) \
2948 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002949 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002950 ); \
2951 lval = (__typeof__(lval)) _res; \
2952 } while (0)
2953
2954#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2955 arg7,arg8,arg9) \
2956 do { \
2957 volatile OrigFn _orig = (orig); \
2958 volatile unsigned long _argvec[3+9]; \
2959 volatile unsigned long _res; \
2960 /* _argvec[0] holds current r2 across the call */ \
2961 _argvec[1] = (unsigned long)_orig.r2; \
2962 _argvec[2] = (unsigned long)_orig.nraddr; \
2963 _argvec[2+1] = (unsigned long)arg1; \
2964 _argvec[2+2] = (unsigned long)arg2; \
2965 _argvec[2+3] = (unsigned long)arg3; \
2966 _argvec[2+4] = (unsigned long)arg4; \
2967 _argvec[2+5] = (unsigned long)arg5; \
2968 _argvec[2+6] = (unsigned long)arg6; \
2969 _argvec[2+7] = (unsigned long)arg7; \
2970 _argvec[2+8] = (unsigned long)arg8; \
2971 _argvec[2+9] = (unsigned long)arg9; \
2972 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002973 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002974 "mr 11,%1\n\t" \
2975 "std 2,-16(11)\n\t" /* save tocptr */ \
2976 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2977 "addi 1,1,-128\n\t" /* expand stack frame */ \
2978 /* arg9 */ \
2979 "ld 3,72(11)\n\t" \
2980 "std 3,112(1)\n\t" \
2981 /* args1-8 */ \
2982 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2983 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2984 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2985 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2986 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2987 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2988 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2989 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2990 "ld 11, 0(11)\n\t" /* target->r11 */ \
2991 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2992 "mr 11,%1\n\t" \
2993 "mr %0,3\n\t" \
2994 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002995 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002996 : /*out*/ "=r" (_res) \
2997 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002998 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002999 ); \
3000 lval = (__typeof__(lval)) _res; \
3001 } while (0)
3002
3003#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3004 arg7,arg8,arg9,arg10) \
3005 do { \
3006 volatile OrigFn _orig = (orig); \
3007 volatile unsigned long _argvec[3+10]; \
3008 volatile unsigned long _res; \
3009 /* _argvec[0] holds current r2 across the call */ \
3010 _argvec[1] = (unsigned long)_orig.r2; \
3011 _argvec[2] = (unsigned long)_orig.nraddr; \
3012 _argvec[2+1] = (unsigned long)arg1; \
3013 _argvec[2+2] = (unsigned long)arg2; \
3014 _argvec[2+3] = (unsigned long)arg3; \
3015 _argvec[2+4] = (unsigned long)arg4; \
3016 _argvec[2+5] = (unsigned long)arg5; \
3017 _argvec[2+6] = (unsigned long)arg6; \
3018 _argvec[2+7] = (unsigned long)arg7; \
3019 _argvec[2+8] = (unsigned long)arg8; \
3020 _argvec[2+9] = (unsigned long)arg9; \
3021 _argvec[2+10] = (unsigned long)arg10; \
3022 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003023 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003024 "mr 11,%1\n\t" \
3025 "std 2,-16(11)\n\t" /* save tocptr */ \
3026 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3027 "addi 1,1,-128\n\t" /* expand stack frame */ \
3028 /* arg10 */ \
3029 "ld 3,80(11)\n\t" \
3030 "std 3,120(1)\n\t" \
3031 /* arg9 */ \
3032 "ld 3,72(11)\n\t" \
3033 "std 3,112(1)\n\t" \
3034 /* args1-8 */ \
3035 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3036 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3037 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3038 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3039 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3040 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3041 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3042 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3043 "ld 11, 0(11)\n\t" /* target->r11 */ \
3044 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3045 "mr 11,%1\n\t" \
3046 "mr %0,3\n\t" \
3047 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003048 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003049 : /*out*/ "=r" (_res) \
3050 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003051 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003052 ); \
3053 lval = (__typeof__(lval)) _res; \
3054 } while (0)
3055
3056#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3057 arg7,arg8,arg9,arg10,arg11) \
3058 do { \
3059 volatile OrigFn _orig = (orig); \
3060 volatile unsigned long _argvec[3+11]; \
3061 volatile unsigned long _res; \
3062 /* _argvec[0] holds current r2 across the call */ \
3063 _argvec[1] = (unsigned long)_orig.r2; \
3064 _argvec[2] = (unsigned long)_orig.nraddr; \
3065 _argvec[2+1] = (unsigned long)arg1; \
3066 _argvec[2+2] = (unsigned long)arg2; \
3067 _argvec[2+3] = (unsigned long)arg3; \
3068 _argvec[2+4] = (unsigned long)arg4; \
3069 _argvec[2+5] = (unsigned long)arg5; \
3070 _argvec[2+6] = (unsigned long)arg6; \
3071 _argvec[2+7] = (unsigned long)arg7; \
3072 _argvec[2+8] = (unsigned long)arg8; \
3073 _argvec[2+9] = (unsigned long)arg9; \
3074 _argvec[2+10] = (unsigned long)arg10; \
3075 _argvec[2+11] = (unsigned long)arg11; \
3076 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003077 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003078 "mr 11,%1\n\t" \
3079 "std 2,-16(11)\n\t" /* save tocptr */ \
3080 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3081 "addi 1,1,-144\n\t" /* expand stack frame */ \
3082 /* arg11 */ \
3083 "ld 3,88(11)\n\t" \
3084 "std 3,128(1)\n\t" \
3085 /* arg10 */ \
3086 "ld 3,80(11)\n\t" \
3087 "std 3,120(1)\n\t" \
3088 /* arg9 */ \
3089 "ld 3,72(11)\n\t" \
3090 "std 3,112(1)\n\t" \
3091 /* args1-8 */ \
3092 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3093 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3094 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3095 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3096 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3097 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3098 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3099 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3100 "ld 11, 0(11)\n\t" /* target->r11 */ \
3101 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3102 "mr 11,%1\n\t" \
3103 "mr %0,3\n\t" \
3104 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003105 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003106 : /*out*/ "=r" (_res) \
3107 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003108 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003109 ); \
3110 lval = (__typeof__(lval)) _res; \
3111 } while (0)
3112
3113#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3114 arg7,arg8,arg9,arg10,arg11,arg12) \
3115 do { \
3116 volatile OrigFn _orig = (orig); \
3117 volatile unsigned long _argvec[3+12]; \
3118 volatile unsigned long _res; \
3119 /* _argvec[0] holds current r2 across the call */ \
3120 _argvec[1] = (unsigned long)_orig.r2; \
3121 _argvec[2] = (unsigned long)_orig.nraddr; \
3122 _argvec[2+1] = (unsigned long)arg1; \
3123 _argvec[2+2] = (unsigned long)arg2; \
3124 _argvec[2+3] = (unsigned long)arg3; \
3125 _argvec[2+4] = (unsigned long)arg4; \
3126 _argvec[2+5] = (unsigned long)arg5; \
3127 _argvec[2+6] = (unsigned long)arg6; \
3128 _argvec[2+7] = (unsigned long)arg7; \
3129 _argvec[2+8] = (unsigned long)arg8; \
3130 _argvec[2+9] = (unsigned long)arg9; \
3131 _argvec[2+10] = (unsigned long)arg10; \
3132 _argvec[2+11] = (unsigned long)arg11; \
3133 _argvec[2+12] = (unsigned long)arg12; \
3134 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003135 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003136 "mr 11,%1\n\t" \
3137 "std 2,-16(11)\n\t" /* save tocptr */ \
3138 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3139 "addi 1,1,-144\n\t" /* expand stack frame */ \
3140 /* arg12 */ \
3141 "ld 3,96(11)\n\t" \
3142 "std 3,136(1)\n\t" \
3143 /* arg11 */ \
3144 "ld 3,88(11)\n\t" \
3145 "std 3,128(1)\n\t" \
3146 /* arg10 */ \
3147 "ld 3,80(11)\n\t" \
3148 "std 3,120(1)\n\t" \
3149 /* arg9 */ \
3150 "ld 3,72(11)\n\t" \
3151 "std 3,112(1)\n\t" \
3152 /* args1-8 */ \
3153 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3154 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3155 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3156 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3157 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3158 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3159 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3160 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3161 "ld 11, 0(11)\n\t" /* target->r11 */ \
3162 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3163 "mr 11,%1\n\t" \
3164 "mr %0,3\n\t" \
3165 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003166 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003167 : /*out*/ "=r" (_res) \
3168 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003169 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003170 ); \
3171 lval = (__typeof__(lval)) _res; \
3172 } while (0)
3173
carllcae0cc22014-08-07 23:17:29 +00003174#endif /* PLAT_ppc64be_linux */
sewardjf5c1a7f2006-10-17 01:32:48 +00003175
carll582d5822014-08-07 23:35:54 +00003176/* ------------------------- ppc64le-linux ----------------------- */
3177#if defined(PLAT_ppc64le_linux)
3178
3179/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3180
3181/* These regs are trashed by the hidden call. */
3182#define __CALLER_SAVED_REGS \
3183 "lr", "ctr", "xer", \
3184 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3185 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3186 "r11", "r12", "r13"
3187
3188/* Macros to save and align the stack before making a function
3189 call and restore it afterwards as gcc may not keep the stack
3190 pointer aligned if it doesn't realise calls are being made
3191 to other functions. */
3192
3193#define VALGRIND_ALIGN_STACK \
3194 "mr 28,1\n\t" \
3195 "rldicr 1,1,0,59\n\t"
3196#define VALGRIND_RESTORE_STACK \
3197 "mr 1,28\n\t"
3198
3199/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
3200 long) == 8. */
3201
3202#define CALL_FN_W_v(lval, orig) \
3203 do { \
3204 volatile OrigFn _orig = (orig); \
3205 volatile unsigned long _argvec[3+0]; \
3206 volatile unsigned long _res; \
3207 /* _argvec[0] holds current r2 across the call */ \
3208 _argvec[1] = (unsigned long)_orig.r2; \
3209 _argvec[2] = (unsigned long)_orig.nraddr; \
3210 __asm__ volatile( \
3211 VALGRIND_ALIGN_STACK \
3212 "mr 12,%1\n\t" \
3213 "std 2,-16(12)\n\t" /* save tocptr */ \
3214 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3215 "ld 12, 0(12)\n\t" /* target->r12 */ \
3216 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3217 "mr 12,%1\n\t" \
3218 "mr %0,3\n\t" \
3219 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3220 VALGRIND_RESTORE_STACK \
3221 : /*out*/ "=r" (_res) \
3222 : /*in*/ "r" (&_argvec[2]) \
3223 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3224 ); \
3225 lval = (__typeof__(lval)) _res; \
3226 } while (0)
3227
3228#define CALL_FN_W_W(lval, orig, arg1) \
3229 do { \
3230 volatile OrigFn _orig = (orig); \
3231 volatile unsigned long _argvec[3+1]; \
3232 volatile unsigned long _res; \
3233 /* _argvec[0] holds current r2 across the call */ \
3234 _argvec[1] = (unsigned long)_orig.r2; \
3235 _argvec[2] = (unsigned long)_orig.nraddr; \
3236 _argvec[2+1] = (unsigned long)arg1; \
3237 __asm__ volatile( \
3238 VALGRIND_ALIGN_STACK \
3239 "mr 12,%1\n\t" \
3240 "std 2,-16(12)\n\t" /* save tocptr */ \
3241 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3242 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3243 "ld 12, 0(12)\n\t" /* target->r12 */ \
3244 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3245 "mr 12,%1\n\t" \
3246 "mr %0,3\n\t" \
3247 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3248 VALGRIND_RESTORE_STACK \
3249 : /*out*/ "=r" (_res) \
3250 : /*in*/ "r" (&_argvec[2]) \
3251 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3252 ); \
3253 lval = (__typeof__(lval)) _res; \
3254 } while (0)
3255
3256#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3257 do { \
3258 volatile OrigFn _orig = (orig); \
3259 volatile unsigned long _argvec[3+2]; \
3260 volatile unsigned long _res; \
3261 /* _argvec[0] holds current r2 across the call */ \
3262 _argvec[1] = (unsigned long)_orig.r2; \
3263 _argvec[2] = (unsigned long)_orig.nraddr; \
3264 _argvec[2+1] = (unsigned long)arg1; \
3265 _argvec[2+2] = (unsigned long)arg2; \
3266 __asm__ volatile( \
3267 VALGRIND_ALIGN_STACK \
3268 "mr 12,%1\n\t" \
3269 "std 2,-16(12)\n\t" /* save tocptr */ \
3270 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3271 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3272 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3273 "ld 12, 0(12)\n\t" /* target->r12 */ \
3274 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3275 "mr 12,%1\n\t" \
3276 "mr %0,3\n\t" \
3277 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3278 VALGRIND_RESTORE_STACK \
3279 : /*out*/ "=r" (_res) \
3280 : /*in*/ "r" (&_argvec[2]) \
3281 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3282 ); \
3283 lval = (__typeof__(lval)) _res; \
3284 } while (0)
3285
3286#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3287 do { \
3288 volatile OrigFn _orig = (orig); \
3289 volatile unsigned long _argvec[3+3]; \
3290 volatile unsigned long _res; \
3291 /* _argvec[0] holds current r2 across the call */ \
3292 _argvec[1] = (unsigned long)_orig.r2; \
3293 _argvec[2] = (unsigned long)_orig.nraddr; \
3294 _argvec[2+1] = (unsigned long)arg1; \
3295 _argvec[2+2] = (unsigned long)arg2; \
3296 _argvec[2+3] = (unsigned long)arg3; \
3297 __asm__ volatile( \
3298 VALGRIND_ALIGN_STACK \
3299 "mr 12,%1\n\t" \
3300 "std 2,-16(12)\n\t" /* save tocptr */ \
3301 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3302 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3303 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3304 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3305 "ld 12, 0(12)\n\t" /* target->r12 */ \
3306 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3307 "mr 12,%1\n\t" \
3308 "mr %0,3\n\t" \
3309 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3310 VALGRIND_RESTORE_STACK \
3311 : /*out*/ "=r" (_res) \
3312 : /*in*/ "r" (&_argvec[2]) \
3313 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3314 ); \
3315 lval = (__typeof__(lval)) _res; \
3316 } while (0)
3317
3318#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3319 do { \
3320 volatile OrigFn _orig = (orig); \
3321 volatile unsigned long _argvec[3+4]; \
3322 volatile unsigned long _res; \
3323 /* _argvec[0] holds current r2 across the call */ \
3324 _argvec[1] = (unsigned long)_orig.r2; \
3325 _argvec[2] = (unsigned long)_orig.nraddr; \
3326 _argvec[2+1] = (unsigned long)arg1; \
3327 _argvec[2+2] = (unsigned long)arg2; \
3328 _argvec[2+3] = (unsigned long)arg3; \
3329 _argvec[2+4] = (unsigned long)arg4; \
3330 __asm__ volatile( \
3331 VALGRIND_ALIGN_STACK \
3332 "mr 12,%1\n\t" \
3333 "std 2,-16(12)\n\t" /* save tocptr */ \
3334 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3335 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3336 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3337 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3338 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3339 "ld 12, 0(12)\n\t" /* target->r12 */ \
3340 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3341 "mr 12,%1\n\t" \
3342 "mr %0,3\n\t" \
3343 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3344 VALGRIND_RESTORE_STACK \
3345 : /*out*/ "=r" (_res) \
3346 : /*in*/ "r" (&_argvec[2]) \
3347 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3348 ); \
3349 lval = (__typeof__(lval)) _res; \
3350 } while (0)
3351
3352#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3353 do { \
3354 volatile OrigFn _orig = (orig); \
3355 volatile unsigned long _argvec[3+5]; \
3356 volatile unsigned long _res; \
3357 /* _argvec[0] holds current r2 across the call */ \
3358 _argvec[1] = (unsigned long)_orig.r2; \
3359 _argvec[2] = (unsigned long)_orig.nraddr; \
3360 _argvec[2+1] = (unsigned long)arg1; \
3361 _argvec[2+2] = (unsigned long)arg2; \
3362 _argvec[2+3] = (unsigned long)arg3; \
3363 _argvec[2+4] = (unsigned long)arg4; \
3364 _argvec[2+5] = (unsigned long)arg5; \
3365 __asm__ volatile( \
3366 VALGRIND_ALIGN_STACK \
3367 "mr 12,%1\n\t" \
3368 "std 2,-16(12)\n\t" /* save tocptr */ \
3369 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3370 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3371 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3372 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3373 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3374 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3375 "ld 12, 0(12)\n\t" /* target->r12 */ \
3376 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3377 "mr 12,%1\n\t" \
3378 "mr %0,3\n\t" \
3379 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3380 VALGRIND_RESTORE_STACK \
3381 : /*out*/ "=r" (_res) \
3382 : /*in*/ "r" (&_argvec[2]) \
3383 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3384 ); \
3385 lval = (__typeof__(lval)) _res; \
3386 } while (0)
3387
3388#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3389 do { \
3390 volatile OrigFn _orig = (orig); \
3391 volatile unsigned long _argvec[3+6]; \
3392 volatile unsigned long _res; \
3393 /* _argvec[0] holds current r2 across the call */ \
3394 _argvec[1] = (unsigned long)_orig.r2; \
3395 _argvec[2] = (unsigned long)_orig.nraddr; \
3396 _argvec[2+1] = (unsigned long)arg1; \
3397 _argvec[2+2] = (unsigned long)arg2; \
3398 _argvec[2+3] = (unsigned long)arg3; \
3399 _argvec[2+4] = (unsigned long)arg4; \
3400 _argvec[2+5] = (unsigned long)arg5; \
3401 _argvec[2+6] = (unsigned long)arg6; \
3402 __asm__ volatile( \
3403 VALGRIND_ALIGN_STACK \
3404 "mr 12,%1\n\t" \
3405 "std 2,-16(12)\n\t" /* save tocptr */ \
3406 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3407 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3408 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3409 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3410 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3411 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3412 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3413 "ld 12, 0(12)\n\t" /* target->r12 */ \
3414 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3415 "mr 12,%1\n\t" \
3416 "mr %0,3\n\t" \
3417 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3418 VALGRIND_RESTORE_STACK \
3419 : /*out*/ "=r" (_res) \
3420 : /*in*/ "r" (&_argvec[2]) \
3421 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3422 ); \
3423 lval = (__typeof__(lval)) _res; \
3424 } while (0)
3425
3426#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3427 arg7) \
3428 do { \
3429 volatile OrigFn _orig = (orig); \
3430 volatile unsigned long _argvec[3+7]; \
3431 volatile unsigned long _res; \
3432 /* _argvec[0] holds current r2 across the call */ \
3433 _argvec[1] = (unsigned long)_orig.r2; \
3434 _argvec[2] = (unsigned long)_orig.nraddr; \
3435 _argvec[2+1] = (unsigned long)arg1; \
3436 _argvec[2+2] = (unsigned long)arg2; \
3437 _argvec[2+3] = (unsigned long)arg3; \
3438 _argvec[2+4] = (unsigned long)arg4; \
3439 _argvec[2+5] = (unsigned long)arg5; \
3440 _argvec[2+6] = (unsigned long)arg6; \
3441 _argvec[2+7] = (unsigned long)arg7; \
3442 __asm__ volatile( \
3443 VALGRIND_ALIGN_STACK \
3444 "mr 12,%1\n\t" \
3445 "std 2,-16(12)\n\t" /* save tocptr */ \
3446 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3447 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3448 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3449 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3450 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3451 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3452 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3453 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3454 "ld 12, 0(12)\n\t" /* target->r12 */ \
3455 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3456 "mr 12,%1\n\t" \
3457 "mr %0,3\n\t" \
3458 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3459 VALGRIND_RESTORE_STACK \
3460 : /*out*/ "=r" (_res) \
3461 : /*in*/ "r" (&_argvec[2]) \
3462 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3463 ); \
3464 lval = (__typeof__(lval)) _res; \
3465 } while (0)
3466
3467#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3468 arg7,arg8) \
3469 do { \
3470 volatile OrigFn _orig = (orig); \
3471 volatile unsigned long _argvec[3+8]; \
3472 volatile unsigned long _res; \
3473 /* _argvec[0] holds current r2 across the call */ \
3474 _argvec[1] = (unsigned long)_orig.r2; \
3475 _argvec[2] = (unsigned long)_orig.nraddr; \
3476 _argvec[2+1] = (unsigned long)arg1; \
3477 _argvec[2+2] = (unsigned long)arg2; \
3478 _argvec[2+3] = (unsigned long)arg3; \
3479 _argvec[2+4] = (unsigned long)arg4; \
3480 _argvec[2+5] = (unsigned long)arg5; \
3481 _argvec[2+6] = (unsigned long)arg6; \
3482 _argvec[2+7] = (unsigned long)arg7; \
3483 _argvec[2+8] = (unsigned long)arg8; \
3484 __asm__ volatile( \
3485 VALGRIND_ALIGN_STACK \
3486 "mr 12,%1\n\t" \
3487 "std 2,-16(12)\n\t" /* save tocptr */ \
3488 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3489 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3490 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3491 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3492 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3493 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3494 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3495 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3496 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3497 "ld 12, 0(12)\n\t" /* target->r12 */ \
3498 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3499 "mr 12,%1\n\t" \
3500 "mr %0,3\n\t" \
3501 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3502 VALGRIND_RESTORE_STACK \
3503 : /*out*/ "=r" (_res) \
3504 : /*in*/ "r" (&_argvec[2]) \
3505 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3506 ); \
3507 lval = (__typeof__(lval)) _res; \
3508 } while (0)
3509
3510#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3511 arg7,arg8,arg9) \
3512 do { \
3513 volatile OrigFn _orig = (orig); \
3514 volatile unsigned long _argvec[3+9]; \
3515 volatile unsigned long _res; \
3516 /* _argvec[0] holds current r2 across the call */ \
3517 _argvec[1] = (unsigned long)_orig.r2; \
3518 _argvec[2] = (unsigned long)_orig.nraddr; \
3519 _argvec[2+1] = (unsigned long)arg1; \
3520 _argvec[2+2] = (unsigned long)arg2; \
3521 _argvec[2+3] = (unsigned long)arg3; \
3522 _argvec[2+4] = (unsigned long)arg4; \
3523 _argvec[2+5] = (unsigned long)arg5; \
3524 _argvec[2+6] = (unsigned long)arg6; \
3525 _argvec[2+7] = (unsigned long)arg7; \
3526 _argvec[2+8] = (unsigned long)arg8; \
3527 _argvec[2+9] = (unsigned long)arg9; \
3528 __asm__ volatile( \
3529 VALGRIND_ALIGN_STACK \
3530 "mr 12,%1\n\t" \
3531 "std 2,-16(12)\n\t" /* save tocptr */ \
3532 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3533 "addi 1,1,-128\n\t" /* expand stack frame */ \
3534 /* arg9 */ \
3535 "ld 3,72(12)\n\t" \
3536 "std 3,96(1)\n\t" \
3537 /* args1-8 */ \
3538 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3539 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3540 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3541 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3542 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3543 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3544 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3545 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3546 "ld 12, 0(12)\n\t" /* target->r12 */ \
3547 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3548 "mr 12,%1\n\t" \
3549 "mr %0,3\n\t" \
3550 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3551 VALGRIND_RESTORE_STACK \
3552 : /*out*/ "=r" (_res) \
3553 : /*in*/ "r" (&_argvec[2]) \
3554 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3555 ); \
3556 lval = (__typeof__(lval)) _res; \
3557 } while (0)
3558
3559#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3560 arg7,arg8,arg9,arg10) \
3561 do { \
3562 volatile OrigFn _orig = (orig); \
3563 volatile unsigned long _argvec[3+10]; \
3564 volatile unsigned long _res; \
3565 /* _argvec[0] holds current r2 across the call */ \
3566 _argvec[1] = (unsigned long)_orig.r2; \
3567 _argvec[2] = (unsigned long)_orig.nraddr; \
3568 _argvec[2+1] = (unsigned long)arg1; \
3569 _argvec[2+2] = (unsigned long)arg2; \
3570 _argvec[2+3] = (unsigned long)arg3; \
3571 _argvec[2+4] = (unsigned long)arg4; \
3572 _argvec[2+5] = (unsigned long)arg5; \
3573 _argvec[2+6] = (unsigned long)arg6; \
3574 _argvec[2+7] = (unsigned long)arg7; \
3575 _argvec[2+8] = (unsigned long)arg8; \
3576 _argvec[2+9] = (unsigned long)arg9; \
3577 _argvec[2+10] = (unsigned long)arg10; \
3578 __asm__ volatile( \
3579 VALGRIND_ALIGN_STACK \
3580 "mr 12,%1\n\t" \
3581 "std 2,-16(12)\n\t" /* save tocptr */ \
3582 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3583 "addi 1,1,-128\n\t" /* expand stack frame */ \
3584 /* arg10 */ \
3585 "ld 3,80(12)\n\t" \
3586 "std 3,104(1)\n\t" \
3587 /* arg9 */ \
3588 "ld 3,72(12)\n\t" \
3589 "std 3,96(1)\n\t" \
3590 /* args1-8 */ \
3591 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3592 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3593 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3594 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3595 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3596 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3597 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3598 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3599 "ld 12, 0(12)\n\t" /* target->r12 */ \
3600 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3601 "mr 12,%1\n\t" \
3602 "mr %0,3\n\t" \
3603 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3604 VALGRIND_RESTORE_STACK \
3605 : /*out*/ "=r" (_res) \
3606 : /*in*/ "r" (&_argvec[2]) \
3607 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3608 ); \
3609 lval = (__typeof__(lval)) _res; \
3610 } while (0)
3611
3612#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3613 arg7,arg8,arg9,arg10,arg11) \
3614 do { \
3615 volatile OrigFn _orig = (orig); \
3616 volatile unsigned long _argvec[3+11]; \
3617 volatile unsigned long _res; \
3618 /* _argvec[0] holds current r2 across the call */ \
3619 _argvec[1] = (unsigned long)_orig.r2; \
3620 _argvec[2] = (unsigned long)_orig.nraddr; \
3621 _argvec[2+1] = (unsigned long)arg1; \
3622 _argvec[2+2] = (unsigned long)arg2; \
3623 _argvec[2+3] = (unsigned long)arg3; \
3624 _argvec[2+4] = (unsigned long)arg4; \
3625 _argvec[2+5] = (unsigned long)arg5; \
3626 _argvec[2+6] = (unsigned long)arg6; \
3627 _argvec[2+7] = (unsigned long)arg7; \
3628 _argvec[2+8] = (unsigned long)arg8; \
3629 _argvec[2+9] = (unsigned long)arg9; \
3630 _argvec[2+10] = (unsigned long)arg10; \
3631 _argvec[2+11] = (unsigned long)arg11; \
3632 __asm__ volatile( \
3633 VALGRIND_ALIGN_STACK \
3634 "mr 12,%1\n\t" \
3635 "std 2,-16(12)\n\t" /* save tocptr */ \
3636 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3637 "addi 1,1,-144\n\t" /* expand stack frame */ \
3638 /* arg11 */ \
3639 "ld 3,88(12)\n\t" \
3640 "std 3,112(1)\n\t" \
3641 /* arg10 */ \
3642 "ld 3,80(12)\n\t" \
3643 "std 3,104(1)\n\t" \
3644 /* arg9 */ \
3645 "ld 3,72(12)\n\t" \
3646 "std 3,96(1)\n\t" \
3647 /* args1-8 */ \
3648 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3649 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3650 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3651 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3652 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3653 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3654 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3655 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3656 "ld 12, 0(12)\n\t" /* target->r12 */ \
3657 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3658 "mr 12,%1\n\t" \
3659 "mr %0,3\n\t" \
3660 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3661 VALGRIND_RESTORE_STACK \
3662 : /*out*/ "=r" (_res) \
3663 : /*in*/ "r" (&_argvec[2]) \
3664 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3665 ); \
3666 lval = (__typeof__(lval)) _res; \
3667 } while (0)
3668
3669#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3670 arg7,arg8,arg9,arg10,arg11,arg12) \
3671 do { \
3672 volatile OrigFn _orig = (orig); \
3673 volatile unsigned long _argvec[3+12]; \
3674 volatile unsigned long _res; \
3675 /* _argvec[0] holds current r2 across the call */ \
3676 _argvec[1] = (unsigned long)_orig.r2; \
3677 _argvec[2] = (unsigned long)_orig.nraddr; \
3678 _argvec[2+1] = (unsigned long)arg1; \
3679 _argvec[2+2] = (unsigned long)arg2; \
3680 _argvec[2+3] = (unsigned long)arg3; \
3681 _argvec[2+4] = (unsigned long)arg4; \
3682 _argvec[2+5] = (unsigned long)arg5; \
3683 _argvec[2+6] = (unsigned long)arg6; \
3684 _argvec[2+7] = (unsigned long)arg7; \
3685 _argvec[2+8] = (unsigned long)arg8; \
3686 _argvec[2+9] = (unsigned long)arg9; \
3687 _argvec[2+10] = (unsigned long)arg10; \
3688 _argvec[2+11] = (unsigned long)arg11; \
3689 _argvec[2+12] = (unsigned long)arg12; \
3690 __asm__ volatile( \
3691 VALGRIND_ALIGN_STACK \
3692 "mr 12,%1\n\t" \
3693 "std 2,-16(12)\n\t" /* save tocptr */ \
3694 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3695 "addi 1,1,-144\n\t" /* expand stack frame */ \
3696 /* arg12 */ \
3697 "ld 3,96(12)\n\t" \
3698 "std 3,120(1)\n\t" \
3699 /* arg11 */ \
3700 "ld 3,88(12)\n\t" \
3701 "std 3,112(1)\n\t" \
3702 /* arg10 */ \
3703 "ld 3,80(12)\n\t" \
3704 "std 3,104(1)\n\t" \
3705 /* arg9 */ \
3706 "ld 3,72(12)\n\t" \
3707 "std 3,96(1)\n\t" \
3708 /* args1-8 */ \
3709 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3710 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3711 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3712 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3713 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3714 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3715 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3716 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3717 "ld 12, 0(12)\n\t" /* target->r12 */ \
3718 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3719 "mr 12,%1\n\t" \
3720 "mr %0,3\n\t" \
3721 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3722 VALGRIND_RESTORE_STACK \
3723 : /*out*/ "=r" (_res) \
3724 : /*in*/ "r" (&_argvec[2]) \
3725 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3726 ); \
3727 lval = (__typeof__(lval)) _res; \
3728 } while (0)
3729
3730#endif /* PLAT_ppc64le_linux */
3731
sewardj59570ff2010-01-01 11:59:33 +00003732/* ------------------------- arm-linux ------------------------- */
3733
3734#if defined(PLAT_arm_linux)
3735
3736/* These regs are trashed by the hidden call. */
3737#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
3738
tom4118e0f2012-08-02 09:23:45 +00003739/* Macros to save and align the stack before making a function
3740 call and restore it afterwards as gcc may not keep the stack
3741 pointer aligned if it doesn't realise calls are being made
3742 to other functions. */
3743
sewardj567e5bb2012-08-04 19:23:54 +00003744/* This is a bit tricky. We store the original stack pointer in r10
3745 as it is callee-saves. gcc doesn't allow the use of r11 for some
3746 reason. Also, we can't directly "bic" the stack pointer in thumb
3747 mode since r13 isn't an allowed register number in that context.
3748 So use r4 as a temporary, since that is about to get trashed
3749 anyway, just after each use of this macro. Side effect is we need
3750 to be very careful about any future changes, since
3751 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
tom4118e0f2012-08-02 09:23:45 +00003752#define VALGRIND_ALIGN_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003753 "mov r10, sp\n\t" \
3754 "mov r4, sp\n\t" \
3755 "bic r4, r4, #7\n\t" \
3756 "mov sp, r4\n\t"
tom4118e0f2012-08-02 09:23:45 +00003757#define VALGRIND_RESTORE_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003758 "mov sp, r10\n\t"
tom4118e0f2012-08-02 09:23:45 +00003759
sewardj59570ff2010-01-01 11:59:33 +00003760/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3761 long) == 4. */
3762
3763#define CALL_FN_W_v(lval, orig) \
3764 do { \
3765 volatile OrigFn _orig = (orig); \
3766 volatile unsigned long _argvec[1]; \
3767 volatile unsigned long _res; \
3768 _argvec[0] = (unsigned long)_orig.nraddr; \
3769 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003770 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003771 "ldr r4, [%1] \n\t" /* target->r4 */ \
3772 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003773 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003774 "mov %0, r0\n" \
3775 : /*out*/ "=r" (_res) \
3776 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003777 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003778 ); \
3779 lval = (__typeof__(lval)) _res; \
3780 } while (0)
3781
3782#define CALL_FN_W_W(lval, orig, arg1) \
3783 do { \
3784 volatile OrigFn _orig = (orig); \
3785 volatile unsigned long _argvec[2]; \
3786 volatile unsigned long _res; \
3787 _argvec[0] = (unsigned long)_orig.nraddr; \
3788 _argvec[1] = (unsigned long)(arg1); \
3789 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003790 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003791 "ldr r0, [%1, #4] \n\t" \
3792 "ldr r4, [%1] \n\t" /* target->r4 */ \
3793 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003794 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003795 "mov %0, r0\n" \
3796 : /*out*/ "=r" (_res) \
3797 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003798 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003799 ); \
3800 lval = (__typeof__(lval)) _res; \
3801 } while (0)
3802
3803#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3804 do { \
3805 volatile OrigFn _orig = (orig); \
3806 volatile unsigned long _argvec[3]; \
3807 volatile unsigned long _res; \
3808 _argvec[0] = (unsigned long)_orig.nraddr; \
3809 _argvec[1] = (unsigned long)(arg1); \
3810 _argvec[2] = (unsigned long)(arg2); \
3811 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003812 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003813 "ldr r0, [%1, #4] \n\t" \
3814 "ldr r1, [%1, #8] \n\t" \
3815 "ldr r4, [%1] \n\t" /* target->r4 */ \
3816 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003817 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003818 "mov %0, r0\n" \
3819 : /*out*/ "=r" (_res) \
3820 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003821 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003822 ); \
3823 lval = (__typeof__(lval)) _res; \
3824 } while (0)
3825
3826#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3827 do { \
3828 volatile OrigFn _orig = (orig); \
3829 volatile unsigned long _argvec[4]; \
3830 volatile unsigned long _res; \
3831 _argvec[0] = (unsigned long)_orig.nraddr; \
3832 _argvec[1] = (unsigned long)(arg1); \
3833 _argvec[2] = (unsigned long)(arg2); \
3834 _argvec[3] = (unsigned long)(arg3); \
3835 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003836 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003837 "ldr r0, [%1, #4] \n\t" \
3838 "ldr r1, [%1, #8] \n\t" \
3839 "ldr r2, [%1, #12] \n\t" \
3840 "ldr r4, [%1] \n\t" /* target->r4 */ \
3841 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003842 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003843 "mov %0, r0\n" \
3844 : /*out*/ "=r" (_res) \
3845 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003846 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003847 ); \
3848 lval = (__typeof__(lval)) _res; \
3849 } while (0)
3850
3851#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3852 do { \
3853 volatile OrigFn _orig = (orig); \
3854 volatile unsigned long _argvec[5]; \
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 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003862 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003863 "ldr r0, [%1, #4] \n\t" \
3864 "ldr r1, [%1, #8] \n\t" \
3865 "ldr r2, [%1, #12] \n\t" \
3866 "ldr r3, [%1, #16] \n\t" \
3867 "ldr r4, [%1] \n\t" /* target->r4 */ \
3868 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003869 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003870 "mov %0, r0" \
3871 : /*out*/ "=r" (_res) \
3872 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003873 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003874 ); \
3875 lval = (__typeof__(lval)) _res; \
3876 } while (0)
3877
3878#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3879 do { \
3880 volatile OrigFn _orig = (orig); \
3881 volatile unsigned long _argvec[6]; \
3882 volatile unsigned long _res; \
3883 _argvec[0] = (unsigned long)_orig.nraddr; \
3884 _argvec[1] = (unsigned long)(arg1); \
3885 _argvec[2] = (unsigned long)(arg2); \
3886 _argvec[3] = (unsigned long)(arg3); \
3887 _argvec[4] = (unsigned long)(arg4); \
3888 _argvec[5] = (unsigned long)(arg5); \
3889 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003890 VALGRIND_ALIGN_STACK \
3891 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003892 "ldr r0, [%1, #20] \n\t" \
3893 "push {r0} \n\t" \
3894 "ldr r0, [%1, #4] \n\t" \
3895 "ldr r1, [%1, #8] \n\t" \
3896 "ldr r2, [%1, #12] \n\t" \
3897 "ldr r3, [%1, #16] \n\t" \
3898 "ldr r4, [%1] \n\t" /* target->r4 */ \
3899 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003900 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003901 "mov %0, r0" \
3902 : /*out*/ "=r" (_res) \
3903 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003904 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003905 ); \
3906 lval = (__typeof__(lval)) _res; \
3907 } while (0)
3908
3909#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3910 do { \
3911 volatile OrigFn _orig = (orig); \
3912 volatile unsigned long _argvec[7]; \
3913 volatile unsigned long _res; \
3914 _argvec[0] = (unsigned long)_orig.nraddr; \
3915 _argvec[1] = (unsigned long)(arg1); \
3916 _argvec[2] = (unsigned long)(arg2); \
3917 _argvec[3] = (unsigned long)(arg3); \
3918 _argvec[4] = (unsigned long)(arg4); \
3919 _argvec[5] = (unsigned long)(arg5); \
3920 _argvec[6] = (unsigned long)(arg6); \
3921 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003922 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003923 "ldr r0, [%1, #20] \n\t" \
3924 "ldr r1, [%1, #24] \n\t" \
3925 "push {r0, r1} \n\t" \
3926 "ldr r0, [%1, #4] \n\t" \
3927 "ldr r1, [%1, #8] \n\t" \
3928 "ldr r2, [%1, #12] \n\t" \
3929 "ldr r3, [%1, #16] \n\t" \
3930 "ldr r4, [%1] \n\t" /* target->r4 */ \
3931 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003932 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003933 "mov %0, r0" \
3934 : /*out*/ "=r" (_res) \
3935 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003936 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003937 ); \
3938 lval = (__typeof__(lval)) _res; \
3939 } while (0)
3940
3941#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3942 arg7) \
3943 do { \
3944 volatile OrigFn _orig = (orig); \
3945 volatile unsigned long _argvec[8]; \
3946 volatile unsigned long _res; \
3947 _argvec[0] = (unsigned long)_orig.nraddr; \
3948 _argvec[1] = (unsigned long)(arg1); \
3949 _argvec[2] = (unsigned long)(arg2); \
3950 _argvec[3] = (unsigned long)(arg3); \
3951 _argvec[4] = (unsigned long)(arg4); \
3952 _argvec[5] = (unsigned long)(arg5); \
3953 _argvec[6] = (unsigned long)(arg6); \
3954 _argvec[7] = (unsigned long)(arg7); \
3955 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003956 VALGRIND_ALIGN_STACK \
3957 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003958 "ldr r0, [%1, #20] \n\t" \
3959 "ldr r1, [%1, #24] \n\t" \
3960 "ldr r2, [%1, #28] \n\t" \
3961 "push {r0, r1, r2} \n\t" \
3962 "ldr r0, [%1, #4] \n\t" \
3963 "ldr r1, [%1, #8] \n\t" \
3964 "ldr r2, [%1, #12] \n\t" \
3965 "ldr r3, [%1, #16] \n\t" \
3966 "ldr r4, [%1] \n\t" /* target->r4 */ \
3967 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003968 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003969 "mov %0, r0" \
3970 : /*out*/ "=r" (_res) \
3971 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003972 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003973 ); \
3974 lval = (__typeof__(lval)) _res; \
3975 } while (0)
3976
3977#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3978 arg7,arg8) \
3979 do { \
3980 volatile OrigFn _orig = (orig); \
3981 volatile unsigned long _argvec[9]; \
3982 volatile unsigned long _res; \
3983 _argvec[0] = (unsigned long)_orig.nraddr; \
3984 _argvec[1] = (unsigned long)(arg1); \
3985 _argvec[2] = (unsigned long)(arg2); \
3986 _argvec[3] = (unsigned long)(arg3); \
3987 _argvec[4] = (unsigned long)(arg4); \
3988 _argvec[5] = (unsigned long)(arg5); \
3989 _argvec[6] = (unsigned long)(arg6); \
3990 _argvec[7] = (unsigned long)(arg7); \
3991 _argvec[8] = (unsigned long)(arg8); \
3992 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003993 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003994 "ldr r0, [%1, #20] \n\t" \
3995 "ldr r1, [%1, #24] \n\t" \
3996 "ldr r2, [%1, #28] \n\t" \
3997 "ldr r3, [%1, #32] \n\t" \
3998 "push {r0, r1, r2, r3} \n\t" \
3999 "ldr r0, [%1, #4] \n\t" \
4000 "ldr r1, [%1, #8] \n\t" \
4001 "ldr r2, [%1, #12] \n\t" \
4002 "ldr r3, [%1, #16] \n\t" \
4003 "ldr r4, [%1] \n\t" /* target->r4 */ \
4004 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004005 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004006 "mov %0, r0" \
4007 : /*out*/ "=r" (_res) \
4008 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004009 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004010 ); \
4011 lval = (__typeof__(lval)) _res; \
4012 } while (0)
4013
4014#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4015 arg7,arg8,arg9) \
4016 do { \
4017 volatile OrigFn _orig = (orig); \
4018 volatile unsigned long _argvec[10]; \
4019 volatile unsigned long _res; \
4020 _argvec[0] = (unsigned long)_orig.nraddr; \
4021 _argvec[1] = (unsigned long)(arg1); \
4022 _argvec[2] = (unsigned long)(arg2); \
4023 _argvec[3] = (unsigned long)(arg3); \
4024 _argvec[4] = (unsigned long)(arg4); \
4025 _argvec[5] = (unsigned long)(arg5); \
4026 _argvec[6] = (unsigned long)(arg6); \
4027 _argvec[7] = (unsigned long)(arg7); \
4028 _argvec[8] = (unsigned long)(arg8); \
4029 _argvec[9] = (unsigned long)(arg9); \
4030 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004031 VALGRIND_ALIGN_STACK \
4032 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00004033 "ldr r0, [%1, #20] \n\t" \
4034 "ldr r1, [%1, #24] \n\t" \
4035 "ldr r2, [%1, #28] \n\t" \
4036 "ldr r3, [%1, #32] \n\t" \
4037 "ldr r4, [%1, #36] \n\t" \
4038 "push {r0, r1, r2, r3, r4} \n\t" \
4039 "ldr r0, [%1, #4] \n\t" \
4040 "ldr r1, [%1, #8] \n\t" \
4041 "ldr r2, [%1, #12] \n\t" \
4042 "ldr r3, [%1, #16] \n\t" \
4043 "ldr r4, [%1] \n\t" /* target->r4 */ \
4044 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004045 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004046 "mov %0, r0" \
4047 : /*out*/ "=r" (_res) \
4048 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004049 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004050 ); \
4051 lval = (__typeof__(lval)) _res; \
4052 } while (0)
4053
4054#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4055 arg7,arg8,arg9,arg10) \
4056 do { \
4057 volatile OrigFn _orig = (orig); \
4058 volatile unsigned long _argvec[11]; \
4059 volatile unsigned long _res; \
4060 _argvec[0] = (unsigned long)_orig.nraddr; \
4061 _argvec[1] = (unsigned long)(arg1); \
4062 _argvec[2] = (unsigned long)(arg2); \
4063 _argvec[3] = (unsigned long)(arg3); \
4064 _argvec[4] = (unsigned long)(arg4); \
4065 _argvec[5] = (unsigned long)(arg5); \
4066 _argvec[6] = (unsigned long)(arg6); \
4067 _argvec[7] = (unsigned long)(arg7); \
4068 _argvec[8] = (unsigned long)(arg8); \
4069 _argvec[9] = (unsigned long)(arg9); \
4070 _argvec[10] = (unsigned long)(arg10); \
4071 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004072 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004073 "ldr r0, [%1, #40] \n\t" \
4074 "push {r0} \n\t" \
4075 "ldr r0, [%1, #20] \n\t" \
4076 "ldr r1, [%1, #24] \n\t" \
4077 "ldr r2, [%1, #28] \n\t" \
4078 "ldr r3, [%1, #32] \n\t" \
4079 "ldr r4, [%1, #36] \n\t" \
4080 "push {r0, r1, r2, r3, r4} \n\t" \
4081 "ldr r0, [%1, #4] \n\t" \
4082 "ldr r1, [%1, #8] \n\t" \
4083 "ldr r2, [%1, #12] \n\t" \
4084 "ldr r3, [%1, #16] \n\t" \
4085 "ldr r4, [%1] \n\t" /* target->r4 */ \
4086 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004087 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004088 "mov %0, r0" \
4089 : /*out*/ "=r" (_res) \
4090 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004091 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004092 ); \
4093 lval = (__typeof__(lval)) _res; \
4094 } while (0)
4095
4096#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4097 arg6,arg7,arg8,arg9,arg10, \
4098 arg11) \
4099 do { \
4100 volatile OrigFn _orig = (orig); \
4101 volatile unsigned long _argvec[12]; \
4102 volatile unsigned long _res; \
4103 _argvec[0] = (unsigned long)_orig.nraddr; \
4104 _argvec[1] = (unsigned long)(arg1); \
4105 _argvec[2] = (unsigned long)(arg2); \
4106 _argvec[3] = (unsigned long)(arg3); \
4107 _argvec[4] = (unsigned long)(arg4); \
4108 _argvec[5] = (unsigned long)(arg5); \
4109 _argvec[6] = (unsigned long)(arg6); \
4110 _argvec[7] = (unsigned long)(arg7); \
4111 _argvec[8] = (unsigned long)(arg8); \
4112 _argvec[9] = (unsigned long)(arg9); \
4113 _argvec[10] = (unsigned long)(arg10); \
4114 _argvec[11] = (unsigned long)(arg11); \
4115 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004116 VALGRIND_ALIGN_STACK \
4117 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00004118 "ldr r0, [%1, #40] \n\t" \
4119 "ldr r1, [%1, #44] \n\t" \
4120 "push {r0, r1} \n\t" \
4121 "ldr r0, [%1, #20] \n\t" \
4122 "ldr r1, [%1, #24] \n\t" \
4123 "ldr r2, [%1, #28] \n\t" \
4124 "ldr r3, [%1, #32] \n\t" \
4125 "ldr r4, [%1, #36] \n\t" \
4126 "push {r0, r1, r2, r3, r4} \n\t" \
4127 "ldr r0, [%1, #4] \n\t" \
4128 "ldr r1, [%1, #8] \n\t" \
4129 "ldr r2, [%1, #12] \n\t" \
4130 "ldr r3, [%1, #16] \n\t" \
4131 "ldr r4, [%1] \n\t" /* target->r4 */ \
4132 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004133 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004134 "mov %0, r0" \
4135 : /*out*/ "=r" (_res) \
4136 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004137 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004138 ); \
4139 lval = (__typeof__(lval)) _res; \
4140 } while (0)
4141
4142#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4143 arg6,arg7,arg8,arg9,arg10, \
4144 arg11,arg12) \
4145 do { \
4146 volatile OrigFn _orig = (orig); \
4147 volatile unsigned long _argvec[13]; \
4148 volatile unsigned long _res; \
4149 _argvec[0] = (unsigned long)_orig.nraddr; \
4150 _argvec[1] = (unsigned long)(arg1); \
4151 _argvec[2] = (unsigned long)(arg2); \
4152 _argvec[3] = (unsigned long)(arg3); \
4153 _argvec[4] = (unsigned long)(arg4); \
4154 _argvec[5] = (unsigned long)(arg5); \
4155 _argvec[6] = (unsigned long)(arg6); \
4156 _argvec[7] = (unsigned long)(arg7); \
4157 _argvec[8] = (unsigned long)(arg8); \
4158 _argvec[9] = (unsigned long)(arg9); \
4159 _argvec[10] = (unsigned long)(arg10); \
4160 _argvec[11] = (unsigned long)(arg11); \
4161 _argvec[12] = (unsigned long)(arg12); \
4162 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004163 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004164 "ldr r0, [%1, #40] \n\t" \
4165 "ldr r1, [%1, #44] \n\t" \
4166 "ldr r2, [%1, #48] \n\t" \
4167 "push {r0, r1, r2} \n\t" \
4168 "ldr r0, [%1, #20] \n\t" \
4169 "ldr r1, [%1, #24] \n\t" \
4170 "ldr r2, [%1, #28] \n\t" \
4171 "ldr r3, [%1, #32] \n\t" \
4172 "ldr r4, [%1, #36] \n\t" \
4173 "push {r0, r1, r2, r3, r4} \n\t" \
4174 "ldr r0, [%1, #4] \n\t" \
4175 "ldr r1, [%1, #8] \n\t" \
4176 "ldr r2, [%1, #12] \n\t" \
4177 "ldr r3, [%1, #16] \n\t" \
4178 "ldr r4, [%1] \n\t" /* target->r4 */ \
4179 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004180 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004181 "mov %0, r0" \
4182 : /*out*/ "=r" (_res) \
4183 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004184 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004185 ); \
4186 lval = (__typeof__(lval)) _res; \
4187 } while (0)
4188
4189#endif /* PLAT_arm_linux */
4190
sewardjf0c12502014-01-12 12:54:00 +00004191/* ------------------------ arm64-linux ------------------------ */
4192
4193#if defined(PLAT_arm64_linux)
4194
4195/* These regs are trashed by the hidden call. */
4196#define __CALLER_SAVED_REGS \
4197 "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
4198 "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
sewardjbb9b1b92014-03-09 09:46:04 +00004199 "x18", "x19", "x20", "x30", \
sewardjf0c12502014-01-12 12:54:00 +00004200 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
4201 "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
4202 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
4203 "v26", "v27", "v28", "v29", "v30", "v31"
4204
sewardjbb9b1b92014-03-09 09:46:04 +00004205/* x21 is callee-saved, so we can use it to save and restore SP around
4206 the hidden call. */
4207#define VALGRIND_ALIGN_STACK \
4208 "mov x21, sp\n\t" \
4209 "bic sp, x21, #15\n\t"
4210#define VALGRIND_RESTORE_STACK \
4211 "mov sp, x21\n\t"
sewardjf0c12502014-01-12 12:54:00 +00004212
4213/* These CALL_FN_ macros assume that on arm64-linux,
4214 sizeof(unsigned long) == 8. */
4215
4216#define CALL_FN_W_v(lval, orig) \
4217 do { \
4218 volatile OrigFn _orig = (orig); \
4219 volatile unsigned long _argvec[1]; \
4220 volatile unsigned long _res; \
4221 _argvec[0] = (unsigned long)_orig.nraddr; \
4222 __asm__ volatile( \
4223 VALGRIND_ALIGN_STACK \
4224 "ldr x8, [%1] \n\t" /* target->x8 */ \
4225 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4226 VALGRIND_RESTORE_STACK \
4227 "mov %0, x0\n" \
4228 : /*out*/ "=r" (_res) \
4229 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00004230 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004231 ); \
4232 lval = (__typeof__(lval)) _res; \
4233 } while (0)
4234
4235#define CALL_FN_W_W(lval, orig, arg1) \
4236 do { \
4237 volatile OrigFn _orig = (orig); \
4238 volatile unsigned long _argvec[2]; \
4239 volatile unsigned long _res; \
4240 _argvec[0] = (unsigned long)_orig.nraddr; \
4241 _argvec[1] = (unsigned long)(arg1); \
4242 __asm__ volatile( \
4243 VALGRIND_ALIGN_STACK \
4244 "ldr x0, [%1, #8] \n\t" \
4245 "ldr x8, [%1] \n\t" /* target->x8 */ \
4246 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4247 VALGRIND_RESTORE_STACK \
4248 "mov %0, x0\n" \
4249 : /*out*/ "=r" (_res) \
4250 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00004251 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004252 ); \
4253 lval = (__typeof__(lval)) _res; \
4254 } while (0)
4255
4256#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
4257 do { \
4258 volatile OrigFn _orig = (orig); \
4259 volatile unsigned long _argvec[3]; \
4260 volatile unsigned long _res; \
4261 _argvec[0] = (unsigned long)_orig.nraddr; \
4262 _argvec[1] = (unsigned long)(arg1); \
4263 _argvec[2] = (unsigned long)(arg2); \
4264 __asm__ volatile( \
4265 VALGRIND_ALIGN_STACK \
4266 "ldr x0, [%1, #8] \n\t" \
4267 "ldr x1, [%1, #16] \n\t" \
4268 "ldr x8, [%1] \n\t" /* target->x8 */ \
4269 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4270 VALGRIND_RESTORE_STACK \
4271 "mov %0, x0\n" \
4272 : /*out*/ "=r" (_res) \
4273 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00004274 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004275 ); \
4276 lval = (__typeof__(lval)) _res; \
4277 } while (0)
4278
4279#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
4280 do { \
4281 volatile OrigFn _orig = (orig); \
4282 volatile unsigned long _argvec[4]; \
4283 volatile unsigned long _res; \
4284 _argvec[0] = (unsigned long)_orig.nraddr; \
4285 _argvec[1] = (unsigned long)(arg1); \
4286 _argvec[2] = (unsigned long)(arg2); \
4287 _argvec[3] = (unsigned long)(arg3); \
4288 __asm__ volatile( \
4289 VALGRIND_ALIGN_STACK \
4290 "ldr x0, [%1, #8] \n\t" \
4291 "ldr x1, [%1, #16] \n\t" \
4292 "ldr x2, [%1, #24] \n\t" \
4293 "ldr x8, [%1] \n\t" /* target->x8 */ \
4294 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4295 VALGRIND_RESTORE_STACK \
4296 "mov %0, x0\n" \
4297 : /*out*/ "=r" (_res) \
4298 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00004299 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004300 ); \
4301 lval = (__typeof__(lval)) _res; \
4302 } while (0)
4303
4304#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
4305 do { \
4306 volatile OrigFn _orig = (orig); \
4307 volatile unsigned long _argvec[5]; \
4308 volatile unsigned long _res; \
4309 _argvec[0] = (unsigned long)_orig.nraddr; \
4310 _argvec[1] = (unsigned long)(arg1); \
4311 _argvec[2] = (unsigned long)(arg2); \
4312 _argvec[3] = (unsigned long)(arg3); \
4313 _argvec[4] = (unsigned long)(arg4); \
4314 __asm__ volatile( \
4315 VALGRIND_ALIGN_STACK \
4316 "ldr x0, [%1, #8] \n\t" \
4317 "ldr x1, [%1, #16] \n\t" \
4318 "ldr x2, [%1, #24] \n\t" \
4319 "ldr x3, [%1, #32] \n\t" \
4320 "ldr x8, [%1] \n\t" /* target->x8 */ \
4321 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4322 VALGRIND_RESTORE_STACK \
4323 "mov %0, x0" \
4324 : /*out*/ "=r" (_res) \
4325 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00004326 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4327 ); \
4328 lval = (__typeof__(lval)) _res; \
4329 } while (0)
4330
4331#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
4332 do { \
4333 volatile OrigFn _orig = (orig); \
4334 volatile unsigned long _argvec[6]; \
4335 volatile unsigned long _res; \
4336 _argvec[0] = (unsigned long)_orig.nraddr; \
4337 _argvec[1] = (unsigned long)(arg1); \
4338 _argvec[2] = (unsigned long)(arg2); \
4339 _argvec[3] = (unsigned long)(arg3); \
4340 _argvec[4] = (unsigned long)(arg4); \
4341 _argvec[5] = (unsigned long)(arg5); \
4342 __asm__ volatile( \
4343 VALGRIND_ALIGN_STACK \
4344 "ldr x0, [%1, #8] \n\t" \
4345 "ldr x1, [%1, #16] \n\t" \
4346 "ldr x2, [%1, #24] \n\t" \
4347 "ldr x3, [%1, #32] \n\t" \
4348 "ldr x4, [%1, #40] \n\t" \
4349 "ldr x8, [%1] \n\t" /* target->x8 */ \
4350 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4351 VALGRIND_RESTORE_STACK \
4352 "mov %0, x0" \
4353 : /*out*/ "=r" (_res) \
4354 : /*in*/ "0" (&_argvec[0]) \
4355 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4356 ); \
4357 lval = (__typeof__(lval)) _res; \
4358 } while (0)
4359
4360#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
4361 do { \
4362 volatile OrigFn _orig = (orig); \
4363 volatile unsigned long _argvec[7]; \
4364 volatile unsigned long _res; \
4365 _argvec[0] = (unsigned long)_orig.nraddr; \
4366 _argvec[1] = (unsigned long)(arg1); \
4367 _argvec[2] = (unsigned long)(arg2); \
4368 _argvec[3] = (unsigned long)(arg3); \
4369 _argvec[4] = (unsigned long)(arg4); \
4370 _argvec[5] = (unsigned long)(arg5); \
4371 _argvec[6] = (unsigned long)(arg6); \
4372 __asm__ volatile( \
4373 VALGRIND_ALIGN_STACK \
4374 "ldr x0, [%1, #8] \n\t" \
4375 "ldr x1, [%1, #16] \n\t" \
4376 "ldr x2, [%1, #24] \n\t" \
4377 "ldr x3, [%1, #32] \n\t" \
4378 "ldr x4, [%1, #40] \n\t" \
4379 "ldr x5, [%1, #48] \n\t" \
4380 "ldr x8, [%1] \n\t" /* target->x8 */ \
4381 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4382 VALGRIND_RESTORE_STACK \
4383 "mov %0, x0" \
4384 : /*out*/ "=r" (_res) \
4385 : /*in*/ "0" (&_argvec[0]) \
4386 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4387 ); \
4388 lval = (__typeof__(lval)) _res; \
4389 } while (0)
4390
4391#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4392 arg7) \
4393 do { \
4394 volatile OrigFn _orig = (orig); \
4395 volatile unsigned long _argvec[8]; \
4396 volatile unsigned long _res; \
4397 _argvec[0] = (unsigned long)_orig.nraddr; \
4398 _argvec[1] = (unsigned long)(arg1); \
4399 _argvec[2] = (unsigned long)(arg2); \
4400 _argvec[3] = (unsigned long)(arg3); \
4401 _argvec[4] = (unsigned long)(arg4); \
4402 _argvec[5] = (unsigned long)(arg5); \
4403 _argvec[6] = (unsigned long)(arg6); \
4404 _argvec[7] = (unsigned long)(arg7); \
4405 __asm__ volatile( \
4406 VALGRIND_ALIGN_STACK \
4407 "ldr x0, [%1, #8] \n\t" \
4408 "ldr x1, [%1, #16] \n\t" \
4409 "ldr x2, [%1, #24] \n\t" \
4410 "ldr x3, [%1, #32] \n\t" \
4411 "ldr x4, [%1, #40] \n\t" \
4412 "ldr x5, [%1, #48] \n\t" \
4413 "ldr x6, [%1, #56] \n\t" \
4414 "ldr x8, [%1] \n\t" /* target->x8 */ \
4415 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4416 VALGRIND_RESTORE_STACK \
4417 "mov %0, x0" \
4418 : /*out*/ "=r" (_res) \
4419 : /*in*/ "0" (&_argvec[0]) \
4420 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4421 ); \
4422 lval = (__typeof__(lval)) _res; \
4423 } while (0)
4424
4425#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4426 arg7,arg8) \
4427 do { \
4428 volatile OrigFn _orig = (orig); \
4429 volatile unsigned long _argvec[9]; \
4430 volatile unsigned long _res; \
4431 _argvec[0] = (unsigned long)_orig.nraddr; \
4432 _argvec[1] = (unsigned long)(arg1); \
4433 _argvec[2] = (unsigned long)(arg2); \
4434 _argvec[3] = (unsigned long)(arg3); \
4435 _argvec[4] = (unsigned long)(arg4); \
4436 _argvec[5] = (unsigned long)(arg5); \
4437 _argvec[6] = (unsigned long)(arg6); \
4438 _argvec[7] = (unsigned long)(arg7); \
4439 _argvec[8] = (unsigned long)(arg8); \
4440 __asm__ volatile( \
4441 VALGRIND_ALIGN_STACK \
4442 "ldr x0, [%1, #8] \n\t" \
4443 "ldr x1, [%1, #16] \n\t" \
4444 "ldr x2, [%1, #24] \n\t" \
4445 "ldr x3, [%1, #32] \n\t" \
4446 "ldr x4, [%1, #40] \n\t" \
4447 "ldr x5, [%1, #48] \n\t" \
4448 "ldr x6, [%1, #56] \n\t" \
4449 "ldr x7, [%1, #64] \n\t" \
4450 "ldr x8, [%1] \n\t" /* target->x8 */ \
4451 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4452 VALGRIND_RESTORE_STACK \
4453 "mov %0, x0" \
4454 : /*out*/ "=r" (_res) \
4455 : /*in*/ "0" (&_argvec[0]) \
4456 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4457 ); \
4458 lval = (__typeof__(lval)) _res; \
4459 } while (0)
4460
4461#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4462 arg7,arg8,arg9) \
4463 do { \
4464 volatile OrigFn _orig = (orig); \
4465 volatile unsigned long _argvec[10]; \
4466 volatile unsigned long _res; \
4467 _argvec[0] = (unsigned long)_orig.nraddr; \
4468 _argvec[1] = (unsigned long)(arg1); \
4469 _argvec[2] = (unsigned long)(arg2); \
4470 _argvec[3] = (unsigned long)(arg3); \
4471 _argvec[4] = (unsigned long)(arg4); \
4472 _argvec[5] = (unsigned long)(arg5); \
4473 _argvec[6] = (unsigned long)(arg6); \
4474 _argvec[7] = (unsigned long)(arg7); \
4475 _argvec[8] = (unsigned long)(arg8); \
4476 _argvec[9] = (unsigned long)(arg9); \
4477 __asm__ volatile( \
4478 VALGRIND_ALIGN_STACK \
4479 "sub sp, sp, #0x20 \n\t" \
4480 "ldr x0, [%1, #8] \n\t" \
4481 "ldr x1, [%1, #16] \n\t" \
4482 "ldr x2, [%1, #24] \n\t" \
4483 "ldr x3, [%1, #32] \n\t" \
4484 "ldr x4, [%1, #40] \n\t" \
4485 "ldr x5, [%1, #48] \n\t" \
4486 "ldr x6, [%1, #56] \n\t" \
4487 "ldr x7, [%1, #64] \n\t" \
4488 "ldr x8, [%1, #72] \n\t" \
4489 "str x8, [sp, #0] \n\t" \
4490 "ldr x8, [%1] \n\t" /* target->x8 */ \
4491 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4492 VALGRIND_RESTORE_STACK \
4493 "mov %0, x0" \
4494 : /*out*/ "=r" (_res) \
4495 : /*in*/ "0" (&_argvec[0]) \
4496 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4497 ); \
4498 lval = (__typeof__(lval)) _res; \
4499 } while (0)
4500
4501#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4502 arg7,arg8,arg9,arg10) \
4503 do { \
4504 volatile OrigFn _orig = (orig); \
4505 volatile unsigned long _argvec[11]; \
4506 volatile unsigned long _res; \
4507 _argvec[0] = (unsigned long)_orig.nraddr; \
4508 _argvec[1] = (unsigned long)(arg1); \
4509 _argvec[2] = (unsigned long)(arg2); \
4510 _argvec[3] = (unsigned long)(arg3); \
4511 _argvec[4] = (unsigned long)(arg4); \
4512 _argvec[5] = (unsigned long)(arg5); \
4513 _argvec[6] = (unsigned long)(arg6); \
4514 _argvec[7] = (unsigned long)(arg7); \
4515 _argvec[8] = (unsigned long)(arg8); \
4516 _argvec[9] = (unsigned long)(arg9); \
4517 _argvec[10] = (unsigned long)(arg10); \
4518 __asm__ volatile( \
4519 VALGRIND_ALIGN_STACK \
4520 "sub sp, sp, #0x20 \n\t" \
4521 "ldr x0, [%1, #8] \n\t" \
4522 "ldr x1, [%1, #16] \n\t" \
4523 "ldr x2, [%1, #24] \n\t" \
4524 "ldr x3, [%1, #32] \n\t" \
4525 "ldr x4, [%1, #40] \n\t" \
4526 "ldr x5, [%1, #48] \n\t" \
4527 "ldr x6, [%1, #56] \n\t" \
4528 "ldr x7, [%1, #64] \n\t" \
4529 "ldr x8, [%1, #72] \n\t" \
4530 "str x8, [sp, #0] \n\t" \
4531 "ldr x8, [%1, #80] \n\t" \
4532 "str x8, [sp, #8] \n\t" \
4533 "ldr x8, [%1] \n\t" /* target->x8 */ \
4534 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4535 VALGRIND_RESTORE_STACK \
4536 "mov %0, x0" \
4537 : /*out*/ "=r" (_res) \
4538 : /*in*/ "0" (&_argvec[0]) \
4539 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4540 ); \
4541 lval = (__typeof__(lval)) _res; \
4542 } while (0)
4543
4544#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4545 arg7,arg8,arg9,arg10,arg11) \
4546 do { \
4547 volatile OrigFn _orig = (orig); \
4548 volatile unsigned long _argvec[12]; \
4549 volatile unsigned long _res; \
4550 _argvec[0] = (unsigned long)_orig.nraddr; \
4551 _argvec[1] = (unsigned long)(arg1); \
4552 _argvec[2] = (unsigned long)(arg2); \
4553 _argvec[3] = (unsigned long)(arg3); \
4554 _argvec[4] = (unsigned long)(arg4); \
4555 _argvec[5] = (unsigned long)(arg5); \
4556 _argvec[6] = (unsigned long)(arg6); \
4557 _argvec[7] = (unsigned long)(arg7); \
4558 _argvec[8] = (unsigned long)(arg8); \
4559 _argvec[9] = (unsigned long)(arg9); \
4560 _argvec[10] = (unsigned long)(arg10); \
4561 _argvec[11] = (unsigned long)(arg11); \
4562 __asm__ volatile( \
4563 VALGRIND_ALIGN_STACK \
4564 "sub sp, sp, #0x30 \n\t" \
4565 "ldr x0, [%1, #8] \n\t" \
4566 "ldr x1, [%1, #16] \n\t" \
4567 "ldr x2, [%1, #24] \n\t" \
4568 "ldr x3, [%1, #32] \n\t" \
4569 "ldr x4, [%1, #40] \n\t" \
4570 "ldr x5, [%1, #48] \n\t" \
4571 "ldr x6, [%1, #56] \n\t" \
4572 "ldr x7, [%1, #64] \n\t" \
4573 "ldr x8, [%1, #72] \n\t" \
4574 "str x8, [sp, #0] \n\t" \
4575 "ldr x8, [%1, #80] \n\t" \
4576 "str x8, [sp, #8] \n\t" \
4577 "ldr x8, [%1, #88] \n\t" \
4578 "str x8, [sp, #16] \n\t" \
4579 "ldr x8, [%1] \n\t" /* target->x8 */ \
4580 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4581 VALGRIND_RESTORE_STACK \
4582 "mov %0, x0" \
4583 : /*out*/ "=r" (_res) \
4584 : /*in*/ "0" (&_argvec[0]) \
4585 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4586 ); \
4587 lval = (__typeof__(lval)) _res; \
4588 } while (0)
4589
4590#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4591 arg7,arg8,arg9,arg10,arg11, \
4592 arg12) \
4593 do { \
4594 volatile OrigFn _orig = (orig); \
4595 volatile unsigned long _argvec[13]; \
4596 volatile unsigned long _res; \
4597 _argvec[0] = (unsigned long)_orig.nraddr; \
4598 _argvec[1] = (unsigned long)(arg1); \
4599 _argvec[2] = (unsigned long)(arg2); \
4600 _argvec[3] = (unsigned long)(arg3); \
4601 _argvec[4] = (unsigned long)(arg4); \
4602 _argvec[5] = (unsigned long)(arg5); \
4603 _argvec[6] = (unsigned long)(arg6); \
4604 _argvec[7] = (unsigned long)(arg7); \
4605 _argvec[8] = (unsigned long)(arg8); \
4606 _argvec[9] = (unsigned long)(arg9); \
4607 _argvec[10] = (unsigned long)(arg10); \
4608 _argvec[11] = (unsigned long)(arg11); \
4609 _argvec[12] = (unsigned long)(arg12); \
4610 __asm__ volatile( \
4611 VALGRIND_ALIGN_STACK \
4612 "sub sp, sp, #0x30 \n\t" \
4613 "ldr x0, [%1, #8] \n\t" \
4614 "ldr x1, [%1, #16] \n\t" \
4615 "ldr x2, [%1, #24] \n\t" \
4616 "ldr x3, [%1, #32] \n\t" \
4617 "ldr x4, [%1, #40] \n\t" \
4618 "ldr x5, [%1, #48] \n\t" \
4619 "ldr x6, [%1, #56] \n\t" \
4620 "ldr x7, [%1, #64] \n\t" \
4621 "ldr x8, [%1, #72] \n\t" \
4622 "str x8, [sp, #0] \n\t" \
4623 "ldr x8, [%1, #80] \n\t" \
4624 "str x8, [sp, #8] \n\t" \
4625 "ldr x8, [%1, #88] \n\t" \
4626 "str x8, [sp, #16] \n\t" \
4627 "ldr x8, [%1, #96] \n\t" \
4628 "str x8, [sp, #24] \n\t" \
4629 "ldr x8, [%1] \n\t" /* target->x8 */ \
4630 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4631 VALGRIND_RESTORE_STACK \
4632 "mov %0, x0" \
4633 : /*out*/ "=r" (_res) \
4634 : /*in*/ "0" (&_argvec[0]) \
4635 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004636 ); \
4637 lval = (__typeof__(lval)) _res; \
4638 } while (0)
4639
4640#endif /* PLAT_arm64_linux */
4641
sewardjb5b87402011-03-07 16:05:35 +00004642/* ------------------------- s390x-linux ------------------------- */
4643
4644#if defined(PLAT_s390x_linux)
4645
4646/* Similar workaround as amd64 (see above), but we use r11 as frame
4647 pointer and save the old r11 in r7. r11 might be used for
4648 argvec, therefore we copy argvec in r1 since r1 is clobbered
4649 after the call anyway. */
4650#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4651# define __FRAME_POINTER \
4652 ,"d"(__builtin_dwarf_cfa())
4653# define VALGRIND_CFI_PROLOGUE \
4654 ".cfi_remember_state\n\t" \
4655 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
4656 "lgr 7,11\n\t" \
4657 "lgr 11,%2\n\t" \
4658 ".cfi_def_cfa r11, 0\n\t"
4659# define VALGRIND_CFI_EPILOGUE \
4660 "lgr 11, 7\n\t" \
4661 ".cfi_restore_state\n\t"
4662#else
4663# define __FRAME_POINTER
4664# define VALGRIND_CFI_PROLOGUE \
4665 "lgr 1,%1\n\t"
4666# define VALGRIND_CFI_EPILOGUE
4667#endif
4668
florian9af940f2012-08-03 03:21:42 +00004669/* Nb: On s390 the stack pointer is properly aligned *at all times*
4670 according to the s390 GCC maintainer. (The ABI specification is not
4671 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4672 VALGRIND_RESTORE_STACK are not defined here. */
sewardjb5b87402011-03-07 16:05:35 +00004673
4674/* These regs are trashed by the hidden call. Note that we overwrite
4675 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4676 function a proper return address. All others are ABI defined call
4677 clobbers. */
4678#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4679 "f0","f1","f2","f3","f4","f5","f6","f7"
4680
florian9af940f2012-08-03 03:21:42 +00004681/* Nb: Although r11 is modified in the asm snippets below (inside
4682 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4683 two reasons:
4684 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4685 modified
4686 (2) GCC will complain that r11 cannot appear inside a clobber section,
4687 when compiled with -O -fno-omit-frame-pointer
4688 */
sewardjb5b87402011-03-07 16:05:35 +00004689
4690#define CALL_FN_W_v(lval, orig) \
4691 do { \
4692 volatile OrigFn _orig = (orig); \
4693 volatile unsigned long _argvec[1]; \
4694 volatile unsigned long _res; \
4695 _argvec[0] = (unsigned long)_orig.nraddr; \
4696 __asm__ volatile( \
4697 VALGRIND_CFI_PROLOGUE \
4698 "aghi 15,-160\n\t" \
4699 "lg 1, 0(1)\n\t" /* target->r1 */ \
4700 VALGRIND_CALL_NOREDIR_R1 \
4701 "lgr %0, 2\n\t" \
4702 "aghi 15,160\n\t" \
4703 VALGRIND_CFI_EPILOGUE \
4704 : /*out*/ "=d" (_res) \
4705 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
4706 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4707 ); \
4708 lval = (__typeof__(lval)) _res; \
4709 } while (0)
4710
4711/* The call abi has the arguments in r2-r6 and stack */
4712#define CALL_FN_W_W(lval, orig, arg1) \
4713 do { \
4714 volatile OrigFn _orig = (orig); \
4715 volatile unsigned long _argvec[2]; \
4716 volatile unsigned long _res; \
4717 _argvec[0] = (unsigned long)_orig.nraddr; \
4718 _argvec[1] = (unsigned long)arg1; \
4719 __asm__ volatile( \
4720 VALGRIND_CFI_PROLOGUE \
4721 "aghi 15,-160\n\t" \
4722 "lg 2, 8(1)\n\t" \
4723 "lg 1, 0(1)\n\t" \
4724 VALGRIND_CALL_NOREDIR_R1 \
4725 "lgr %0, 2\n\t" \
4726 "aghi 15,160\n\t" \
4727 VALGRIND_CFI_EPILOGUE \
4728 : /*out*/ "=d" (_res) \
4729 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4730 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4731 ); \
4732 lval = (__typeof__(lval)) _res; \
4733 } while (0)
4734
4735#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
4736 do { \
4737 volatile OrigFn _orig = (orig); \
4738 volatile unsigned long _argvec[3]; \
4739 volatile unsigned long _res; \
4740 _argvec[0] = (unsigned long)_orig.nraddr; \
4741 _argvec[1] = (unsigned long)arg1; \
4742 _argvec[2] = (unsigned long)arg2; \
4743 __asm__ volatile( \
4744 VALGRIND_CFI_PROLOGUE \
4745 "aghi 15,-160\n\t" \
4746 "lg 2, 8(1)\n\t" \
4747 "lg 3,16(1)\n\t" \
4748 "lg 1, 0(1)\n\t" \
4749 VALGRIND_CALL_NOREDIR_R1 \
4750 "lgr %0, 2\n\t" \
4751 "aghi 15,160\n\t" \
4752 VALGRIND_CFI_EPILOGUE \
4753 : /*out*/ "=d" (_res) \
4754 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4755 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4756 ); \
4757 lval = (__typeof__(lval)) _res; \
4758 } while (0)
4759
4760#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
4761 do { \
4762 volatile OrigFn _orig = (orig); \
4763 volatile unsigned long _argvec[4]; \
4764 volatile unsigned long _res; \
4765 _argvec[0] = (unsigned long)_orig.nraddr; \
4766 _argvec[1] = (unsigned long)arg1; \
4767 _argvec[2] = (unsigned long)arg2; \
4768 _argvec[3] = (unsigned long)arg3; \
4769 __asm__ volatile( \
4770 VALGRIND_CFI_PROLOGUE \
4771 "aghi 15,-160\n\t" \
4772 "lg 2, 8(1)\n\t" \
4773 "lg 3,16(1)\n\t" \
4774 "lg 4,24(1)\n\t" \
4775 "lg 1, 0(1)\n\t" \
4776 VALGRIND_CALL_NOREDIR_R1 \
4777 "lgr %0, 2\n\t" \
4778 "aghi 15,160\n\t" \
4779 VALGRIND_CFI_EPILOGUE \
4780 : /*out*/ "=d" (_res) \
4781 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4782 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4783 ); \
4784 lval = (__typeof__(lval)) _res; \
4785 } while (0)
4786
4787#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
4788 do { \
4789 volatile OrigFn _orig = (orig); \
4790 volatile unsigned long _argvec[5]; \
4791 volatile unsigned long _res; \
4792 _argvec[0] = (unsigned long)_orig.nraddr; \
4793 _argvec[1] = (unsigned long)arg1; \
4794 _argvec[2] = (unsigned long)arg2; \
4795 _argvec[3] = (unsigned long)arg3; \
4796 _argvec[4] = (unsigned long)arg4; \
4797 __asm__ volatile( \
4798 VALGRIND_CFI_PROLOGUE \
4799 "aghi 15,-160\n\t" \
4800 "lg 2, 8(1)\n\t" \
4801 "lg 3,16(1)\n\t" \
4802 "lg 4,24(1)\n\t" \
4803 "lg 5,32(1)\n\t" \
4804 "lg 1, 0(1)\n\t" \
4805 VALGRIND_CALL_NOREDIR_R1 \
4806 "lgr %0, 2\n\t" \
4807 "aghi 15,160\n\t" \
4808 VALGRIND_CFI_EPILOGUE \
4809 : /*out*/ "=d" (_res) \
4810 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4811 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4812 ); \
4813 lval = (__typeof__(lval)) _res; \
4814 } while (0)
4815
4816#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
4817 do { \
4818 volatile OrigFn _orig = (orig); \
4819 volatile unsigned long _argvec[6]; \
4820 volatile unsigned long _res; \
4821 _argvec[0] = (unsigned long)_orig.nraddr; \
4822 _argvec[1] = (unsigned long)arg1; \
4823 _argvec[2] = (unsigned long)arg2; \
4824 _argvec[3] = (unsigned long)arg3; \
4825 _argvec[4] = (unsigned long)arg4; \
4826 _argvec[5] = (unsigned long)arg5; \
4827 __asm__ volatile( \
4828 VALGRIND_CFI_PROLOGUE \
4829 "aghi 15,-160\n\t" \
4830 "lg 2, 8(1)\n\t" \
4831 "lg 3,16(1)\n\t" \
4832 "lg 4,24(1)\n\t" \
4833 "lg 5,32(1)\n\t" \
4834 "lg 6,40(1)\n\t" \
4835 "lg 1, 0(1)\n\t" \
4836 VALGRIND_CALL_NOREDIR_R1 \
4837 "lgr %0, 2\n\t" \
4838 "aghi 15,160\n\t" \
4839 VALGRIND_CFI_EPILOGUE \
4840 : /*out*/ "=d" (_res) \
4841 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4842 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4843 ); \
4844 lval = (__typeof__(lval)) _res; \
4845 } while (0)
4846
4847#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4848 arg6) \
4849 do { \
4850 volatile OrigFn _orig = (orig); \
4851 volatile unsigned long _argvec[7]; \
4852 volatile unsigned long _res; \
4853 _argvec[0] = (unsigned long)_orig.nraddr; \
4854 _argvec[1] = (unsigned long)arg1; \
4855 _argvec[2] = (unsigned long)arg2; \
4856 _argvec[3] = (unsigned long)arg3; \
4857 _argvec[4] = (unsigned long)arg4; \
4858 _argvec[5] = (unsigned long)arg5; \
4859 _argvec[6] = (unsigned long)arg6; \
4860 __asm__ volatile( \
4861 VALGRIND_CFI_PROLOGUE \
4862 "aghi 15,-168\n\t" \
4863 "lg 2, 8(1)\n\t" \
4864 "lg 3,16(1)\n\t" \
4865 "lg 4,24(1)\n\t" \
4866 "lg 5,32(1)\n\t" \
4867 "lg 6,40(1)\n\t" \
4868 "mvc 160(8,15), 48(1)\n\t" \
4869 "lg 1, 0(1)\n\t" \
4870 VALGRIND_CALL_NOREDIR_R1 \
4871 "lgr %0, 2\n\t" \
4872 "aghi 15,168\n\t" \
4873 VALGRIND_CFI_EPILOGUE \
4874 : /*out*/ "=d" (_res) \
4875 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4876 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4877 ); \
4878 lval = (__typeof__(lval)) _res; \
4879 } while (0)
4880
4881#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4882 arg6, arg7) \
4883 do { \
4884 volatile OrigFn _orig = (orig); \
4885 volatile unsigned long _argvec[8]; \
4886 volatile unsigned long _res; \
4887 _argvec[0] = (unsigned long)_orig.nraddr; \
4888 _argvec[1] = (unsigned long)arg1; \
4889 _argvec[2] = (unsigned long)arg2; \
4890 _argvec[3] = (unsigned long)arg3; \
4891 _argvec[4] = (unsigned long)arg4; \
4892 _argvec[5] = (unsigned long)arg5; \
4893 _argvec[6] = (unsigned long)arg6; \
4894 _argvec[7] = (unsigned long)arg7; \
4895 __asm__ volatile( \
4896 VALGRIND_CFI_PROLOGUE \
4897 "aghi 15,-176\n\t" \
4898 "lg 2, 8(1)\n\t" \
4899 "lg 3,16(1)\n\t" \
4900 "lg 4,24(1)\n\t" \
4901 "lg 5,32(1)\n\t" \
4902 "lg 6,40(1)\n\t" \
4903 "mvc 160(8,15), 48(1)\n\t" \
4904 "mvc 168(8,15), 56(1)\n\t" \
4905 "lg 1, 0(1)\n\t" \
4906 VALGRIND_CALL_NOREDIR_R1 \
4907 "lgr %0, 2\n\t" \
4908 "aghi 15,176\n\t" \
4909 VALGRIND_CFI_EPILOGUE \
4910 : /*out*/ "=d" (_res) \
4911 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4912 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4913 ); \
4914 lval = (__typeof__(lval)) _res; \
4915 } while (0)
4916
4917#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4918 arg6, arg7 ,arg8) \
4919 do { \
4920 volatile OrigFn _orig = (orig); \
4921 volatile unsigned long _argvec[9]; \
4922 volatile unsigned long _res; \
4923 _argvec[0] = (unsigned long)_orig.nraddr; \
4924 _argvec[1] = (unsigned long)arg1; \
4925 _argvec[2] = (unsigned long)arg2; \
4926 _argvec[3] = (unsigned long)arg3; \
4927 _argvec[4] = (unsigned long)arg4; \
4928 _argvec[5] = (unsigned long)arg5; \
4929 _argvec[6] = (unsigned long)arg6; \
4930 _argvec[7] = (unsigned long)arg7; \
4931 _argvec[8] = (unsigned long)arg8; \
4932 __asm__ volatile( \
4933 VALGRIND_CFI_PROLOGUE \
4934 "aghi 15,-184\n\t" \
4935 "lg 2, 8(1)\n\t" \
4936 "lg 3,16(1)\n\t" \
4937 "lg 4,24(1)\n\t" \
4938 "lg 5,32(1)\n\t" \
4939 "lg 6,40(1)\n\t" \
4940 "mvc 160(8,15), 48(1)\n\t" \
4941 "mvc 168(8,15), 56(1)\n\t" \
4942 "mvc 176(8,15), 64(1)\n\t" \
4943 "lg 1, 0(1)\n\t" \
4944 VALGRIND_CALL_NOREDIR_R1 \
4945 "lgr %0, 2\n\t" \
4946 "aghi 15,184\n\t" \
4947 VALGRIND_CFI_EPILOGUE \
4948 : /*out*/ "=d" (_res) \
4949 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4950 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4951 ); \
4952 lval = (__typeof__(lval)) _res; \
4953 } while (0)
4954
4955#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4956 arg6, arg7 ,arg8, arg9) \
4957 do { \
4958 volatile OrigFn _orig = (orig); \
4959 volatile unsigned long _argvec[10]; \
4960 volatile unsigned long _res; \
4961 _argvec[0] = (unsigned long)_orig.nraddr; \
4962 _argvec[1] = (unsigned long)arg1; \
4963 _argvec[2] = (unsigned long)arg2; \
4964 _argvec[3] = (unsigned long)arg3; \
4965 _argvec[4] = (unsigned long)arg4; \
4966 _argvec[5] = (unsigned long)arg5; \
4967 _argvec[6] = (unsigned long)arg6; \
4968 _argvec[7] = (unsigned long)arg7; \
4969 _argvec[8] = (unsigned long)arg8; \
4970 _argvec[9] = (unsigned long)arg9; \
4971 __asm__ volatile( \
4972 VALGRIND_CFI_PROLOGUE \
4973 "aghi 15,-192\n\t" \
4974 "lg 2, 8(1)\n\t" \
4975 "lg 3,16(1)\n\t" \
4976 "lg 4,24(1)\n\t" \
4977 "lg 5,32(1)\n\t" \
4978 "lg 6,40(1)\n\t" \
4979 "mvc 160(8,15), 48(1)\n\t" \
4980 "mvc 168(8,15), 56(1)\n\t" \
4981 "mvc 176(8,15), 64(1)\n\t" \
4982 "mvc 184(8,15), 72(1)\n\t" \
4983 "lg 1, 0(1)\n\t" \
4984 VALGRIND_CALL_NOREDIR_R1 \
4985 "lgr %0, 2\n\t" \
4986 "aghi 15,192\n\t" \
4987 VALGRIND_CFI_EPILOGUE \
4988 : /*out*/ "=d" (_res) \
4989 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4990 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4991 ); \
4992 lval = (__typeof__(lval)) _res; \
4993 } while (0)
4994
4995#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4996 arg6, arg7 ,arg8, arg9, arg10) \
4997 do { \
4998 volatile OrigFn _orig = (orig); \
4999 volatile unsigned long _argvec[11]; \
5000 volatile unsigned long _res; \
5001 _argvec[0] = (unsigned long)_orig.nraddr; \
5002 _argvec[1] = (unsigned long)arg1; \
5003 _argvec[2] = (unsigned long)arg2; \
5004 _argvec[3] = (unsigned long)arg3; \
5005 _argvec[4] = (unsigned long)arg4; \
5006 _argvec[5] = (unsigned long)arg5; \
5007 _argvec[6] = (unsigned long)arg6; \
5008 _argvec[7] = (unsigned long)arg7; \
5009 _argvec[8] = (unsigned long)arg8; \
5010 _argvec[9] = (unsigned long)arg9; \
5011 _argvec[10] = (unsigned long)arg10; \
5012 __asm__ volatile( \
5013 VALGRIND_CFI_PROLOGUE \
5014 "aghi 15,-200\n\t" \
5015 "lg 2, 8(1)\n\t" \
5016 "lg 3,16(1)\n\t" \
5017 "lg 4,24(1)\n\t" \
5018 "lg 5,32(1)\n\t" \
5019 "lg 6,40(1)\n\t" \
5020 "mvc 160(8,15), 48(1)\n\t" \
5021 "mvc 168(8,15), 56(1)\n\t" \
5022 "mvc 176(8,15), 64(1)\n\t" \
5023 "mvc 184(8,15), 72(1)\n\t" \
5024 "mvc 192(8,15), 80(1)\n\t" \
5025 "lg 1, 0(1)\n\t" \
5026 VALGRIND_CALL_NOREDIR_R1 \
5027 "lgr %0, 2\n\t" \
5028 "aghi 15,200\n\t" \
5029 VALGRIND_CFI_EPILOGUE \
5030 : /*out*/ "=d" (_res) \
5031 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5032 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5033 ); \
5034 lval = (__typeof__(lval)) _res; \
5035 } while (0)
5036
5037#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5038 arg6, arg7 ,arg8, arg9, arg10, arg11) \
5039 do { \
5040 volatile OrigFn _orig = (orig); \
5041 volatile unsigned long _argvec[12]; \
5042 volatile unsigned long _res; \
5043 _argvec[0] = (unsigned long)_orig.nraddr; \
5044 _argvec[1] = (unsigned long)arg1; \
5045 _argvec[2] = (unsigned long)arg2; \
5046 _argvec[3] = (unsigned long)arg3; \
5047 _argvec[4] = (unsigned long)arg4; \
5048 _argvec[5] = (unsigned long)arg5; \
5049 _argvec[6] = (unsigned long)arg6; \
5050 _argvec[7] = (unsigned long)arg7; \
5051 _argvec[8] = (unsigned long)arg8; \
5052 _argvec[9] = (unsigned long)arg9; \
5053 _argvec[10] = (unsigned long)arg10; \
5054 _argvec[11] = (unsigned long)arg11; \
5055 __asm__ volatile( \
5056 VALGRIND_CFI_PROLOGUE \
5057 "aghi 15,-208\n\t" \
5058 "lg 2, 8(1)\n\t" \
5059 "lg 3,16(1)\n\t" \
5060 "lg 4,24(1)\n\t" \
5061 "lg 5,32(1)\n\t" \
5062 "lg 6,40(1)\n\t" \
5063 "mvc 160(8,15), 48(1)\n\t" \
5064 "mvc 168(8,15), 56(1)\n\t" \
5065 "mvc 176(8,15), 64(1)\n\t" \
5066 "mvc 184(8,15), 72(1)\n\t" \
5067 "mvc 192(8,15), 80(1)\n\t" \
5068 "mvc 200(8,15), 88(1)\n\t" \
5069 "lg 1, 0(1)\n\t" \
5070 VALGRIND_CALL_NOREDIR_R1 \
5071 "lgr %0, 2\n\t" \
5072 "aghi 15,208\n\t" \
5073 VALGRIND_CFI_EPILOGUE \
5074 : /*out*/ "=d" (_res) \
5075 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5076 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5077 ); \
5078 lval = (__typeof__(lval)) _res; \
5079 } while (0)
5080
5081#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5082 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
5083 do { \
5084 volatile OrigFn _orig = (orig); \
5085 volatile unsigned long _argvec[13]; \
5086 volatile unsigned long _res; \
5087 _argvec[0] = (unsigned long)_orig.nraddr; \
5088 _argvec[1] = (unsigned long)arg1; \
5089 _argvec[2] = (unsigned long)arg2; \
5090 _argvec[3] = (unsigned long)arg3; \
5091 _argvec[4] = (unsigned long)arg4; \
5092 _argvec[5] = (unsigned long)arg5; \
5093 _argvec[6] = (unsigned long)arg6; \
5094 _argvec[7] = (unsigned long)arg7; \
5095 _argvec[8] = (unsigned long)arg8; \
5096 _argvec[9] = (unsigned long)arg9; \
5097 _argvec[10] = (unsigned long)arg10; \
5098 _argvec[11] = (unsigned long)arg11; \
5099 _argvec[12] = (unsigned long)arg12; \
5100 __asm__ volatile( \
5101 VALGRIND_CFI_PROLOGUE \
5102 "aghi 15,-216\n\t" \
5103 "lg 2, 8(1)\n\t" \
5104 "lg 3,16(1)\n\t" \
5105 "lg 4,24(1)\n\t" \
5106 "lg 5,32(1)\n\t" \
5107 "lg 6,40(1)\n\t" \
5108 "mvc 160(8,15), 48(1)\n\t" \
5109 "mvc 168(8,15), 56(1)\n\t" \
5110 "mvc 176(8,15), 64(1)\n\t" \
5111 "mvc 184(8,15), 72(1)\n\t" \
5112 "mvc 192(8,15), 80(1)\n\t" \
5113 "mvc 200(8,15), 88(1)\n\t" \
5114 "mvc 208(8,15), 96(1)\n\t" \
5115 "lg 1, 0(1)\n\t" \
5116 VALGRIND_CALL_NOREDIR_R1 \
5117 "lgr %0, 2\n\t" \
5118 "aghi 15,216\n\t" \
5119 VALGRIND_CFI_EPILOGUE \
5120 : /*out*/ "=d" (_res) \
5121 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5122 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5123 ); \
5124 lval = (__typeof__(lval)) _res; \
5125 } while (0)
5126
5127
5128#endif /* PLAT_s390x_linux */
5129
petarj4df0bfc2013-02-27 23:17:33 +00005130/* ------------------------- mips32-linux ----------------------- */
sewardj5db15402012-06-07 09:13:21 +00005131
5132#if defined(PLAT_mips32_linux)
5133
5134/* These regs are trashed by the hidden call. */
5135#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5136"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5137"$25", "$31"
5138
5139/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5140 long) == 4. */
5141
5142#define CALL_FN_W_v(lval, orig) \
5143 do { \
5144 volatile OrigFn _orig = (orig); \
5145 volatile unsigned long _argvec[1]; \
5146 volatile unsigned long _res; \
5147 _argvec[0] = (unsigned long)_orig.nraddr; \
5148 __asm__ volatile( \
5149 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005150 "sw $28, 0($29) \n\t" \
5151 "sw $31, 4($29) \n\t" \
5152 "subu $29, $29, 16 \n\t" \
5153 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005154 VALGRIND_CALL_NOREDIR_T9 \
5155 "addu $29, $29, 16\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005156 "lw $28, 0($29) \n\t" \
5157 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005158 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005159 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005160 : /*out*/ "=r" (_res) \
5161 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005162 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005163 ); \
5164 lval = (__typeof__(lval)) _res; \
5165 } while (0)
5166
5167#define CALL_FN_W_W(lval, orig, arg1) \
5168 do { \
5169 volatile OrigFn _orig = (orig); \
5170 volatile unsigned long _argvec[2]; \
5171 volatile unsigned long _res; \
5172 _argvec[0] = (unsigned long)_orig.nraddr; \
5173 _argvec[1] = (unsigned long)(arg1); \
5174 __asm__ volatile( \
5175 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005176 "sw $28, 0($29) \n\t" \
5177 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005178 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005179 "lw $4, 4(%1) \n\t" /* arg1*/ \
5180 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005181 VALGRIND_CALL_NOREDIR_T9 \
5182 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005183 "lw $28, 0($29) \n\t" \
5184 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005185 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005186 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005187 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00005188 : /*in*/ "0" (&_argvec[0]) \
5189 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005190 ); \
5191 lval = (__typeof__(lval)) _res; \
5192 } while (0)
5193
5194#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5195 do { \
5196 volatile OrigFn _orig = (orig); \
5197 volatile unsigned long _argvec[3]; \
5198 volatile unsigned long _res; \
5199 _argvec[0] = (unsigned long)_orig.nraddr; \
5200 _argvec[1] = (unsigned long)(arg1); \
5201 _argvec[2] = (unsigned long)(arg2); \
5202 __asm__ volatile( \
5203 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005204 "sw $28, 0($29) \n\t" \
5205 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005206 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005207 "lw $4, 4(%1) \n\t" \
5208 "lw $5, 8(%1) \n\t" \
5209 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005210 VALGRIND_CALL_NOREDIR_T9 \
5211 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005212 "lw $28, 0($29) \n\t" \
5213 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005214 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005215 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005216 : /*out*/ "=r" (_res) \
5217 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005218 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005219 ); \
5220 lval = (__typeof__(lval)) _res; \
5221 } while (0)
5222
5223#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5224 do { \
5225 volatile OrigFn _orig = (orig); \
5226 volatile unsigned long _argvec[4]; \
5227 volatile unsigned long _res; \
5228 _argvec[0] = (unsigned long)_orig.nraddr; \
5229 _argvec[1] = (unsigned long)(arg1); \
5230 _argvec[2] = (unsigned long)(arg2); \
5231 _argvec[3] = (unsigned long)(arg3); \
5232 __asm__ volatile( \
5233 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005234 "sw $28, 0($29) \n\t" \
5235 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005236 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005237 "lw $4, 4(%1) \n\t" \
5238 "lw $5, 8(%1) \n\t" \
5239 "lw $6, 12(%1) \n\t" \
5240 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005241 VALGRIND_CALL_NOREDIR_T9 \
5242 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005243 "lw $28, 0($29) \n\t" \
5244 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005245 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005246 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005247 : /*out*/ "=r" (_res) \
5248 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005249 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005250 ); \
5251 lval = (__typeof__(lval)) _res; \
5252 } while (0)
5253
5254#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5255 do { \
5256 volatile OrigFn _orig = (orig); \
5257 volatile unsigned long _argvec[5]; \
5258 volatile unsigned long _res; \
5259 _argvec[0] = (unsigned long)_orig.nraddr; \
5260 _argvec[1] = (unsigned long)(arg1); \
5261 _argvec[2] = (unsigned long)(arg2); \
5262 _argvec[3] = (unsigned long)(arg3); \
5263 _argvec[4] = (unsigned long)(arg4); \
5264 __asm__ volatile( \
5265 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005266 "sw $28, 0($29) \n\t" \
5267 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005268 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005269 "lw $4, 4(%1) \n\t" \
5270 "lw $5, 8(%1) \n\t" \
5271 "lw $6, 12(%1) \n\t" \
5272 "lw $7, 16(%1) \n\t" \
5273 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005274 VALGRIND_CALL_NOREDIR_T9 \
5275 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005276 "lw $28, 0($29) \n\t" \
5277 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005278 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005279 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005280 : /*out*/ "=r" (_res) \
5281 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005282 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005283 ); \
5284 lval = (__typeof__(lval)) _res; \
5285 } while (0)
5286
5287#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5288 do { \
5289 volatile OrigFn _orig = (orig); \
5290 volatile unsigned long _argvec[6]; \
5291 volatile unsigned long _res; \
5292 _argvec[0] = (unsigned long)_orig.nraddr; \
5293 _argvec[1] = (unsigned long)(arg1); \
5294 _argvec[2] = (unsigned long)(arg2); \
5295 _argvec[3] = (unsigned long)(arg3); \
5296 _argvec[4] = (unsigned long)(arg4); \
5297 _argvec[5] = (unsigned long)(arg5); \
5298 __asm__ volatile( \
5299 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005300 "sw $28, 0($29) \n\t" \
5301 "sw $31, 4($29) \n\t" \
5302 "lw $4, 20(%1) \n\t" \
5303 "subu $29, $29, 24\n\t" \
5304 "sw $4, 16($29) \n\t" \
5305 "lw $4, 4(%1) \n\t" \
5306 "lw $5, 8(%1) \n\t" \
5307 "lw $6, 12(%1) \n\t" \
5308 "lw $7, 16(%1) \n\t" \
5309 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005310 VALGRIND_CALL_NOREDIR_T9 \
5311 "addu $29, $29, 24 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005312 "lw $28, 0($29) \n\t" \
5313 "lw $31, 4($29) \n\t" \
5314 "addu $29, $29, 8 \n\t" \
5315 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005316 : /*out*/ "=r" (_res) \
5317 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005318 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005319 ); \
5320 lval = (__typeof__(lval)) _res; \
5321 } while (0)
5322#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5323 do { \
5324 volatile OrigFn _orig = (orig); \
5325 volatile unsigned long _argvec[7]; \
5326 volatile unsigned long _res; \
5327 _argvec[0] = (unsigned long)_orig.nraddr; \
5328 _argvec[1] = (unsigned long)(arg1); \
5329 _argvec[2] = (unsigned long)(arg2); \
5330 _argvec[3] = (unsigned long)(arg3); \
5331 _argvec[4] = (unsigned long)(arg4); \
5332 _argvec[5] = (unsigned long)(arg5); \
5333 _argvec[6] = (unsigned long)(arg6); \
5334 __asm__ volatile( \
5335 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005336 "sw $28, 0($29) \n\t" \
5337 "sw $31, 4($29) \n\t" \
5338 "lw $4, 20(%1) \n\t" \
5339 "subu $29, $29, 32\n\t" \
5340 "sw $4, 16($29) \n\t" \
5341 "lw $4, 24(%1) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005342 "nop\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005343 "sw $4, 20($29) \n\t" \
5344 "lw $4, 4(%1) \n\t" \
5345 "lw $5, 8(%1) \n\t" \
5346 "lw $6, 12(%1) \n\t" \
5347 "lw $7, 16(%1) \n\t" \
5348 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005349 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005350 "addu $29, $29, 32 \n\t" \
5351 "lw $28, 0($29) \n\t" \
5352 "lw $31, 4($29) \n\t" \
5353 "addu $29, $29, 8 \n\t" \
5354 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005355 : /*out*/ "=r" (_res) \
5356 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005357 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005358 ); \
5359 lval = (__typeof__(lval)) _res; \
5360 } while (0)
5361
5362#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5363 arg7) \
5364 do { \
5365 volatile OrigFn _orig = (orig); \
5366 volatile unsigned long _argvec[8]; \
5367 volatile unsigned long _res; \
5368 _argvec[0] = (unsigned long)_orig.nraddr; \
5369 _argvec[1] = (unsigned long)(arg1); \
5370 _argvec[2] = (unsigned long)(arg2); \
5371 _argvec[3] = (unsigned long)(arg3); \
5372 _argvec[4] = (unsigned long)(arg4); \
5373 _argvec[5] = (unsigned long)(arg5); \
5374 _argvec[6] = (unsigned long)(arg6); \
5375 _argvec[7] = (unsigned long)(arg7); \
5376 __asm__ volatile( \
5377 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005378 "sw $28, 0($29) \n\t" \
5379 "sw $31, 4($29) \n\t" \
5380 "lw $4, 20(%1) \n\t" \
5381 "subu $29, $29, 32\n\t" \
5382 "sw $4, 16($29) \n\t" \
5383 "lw $4, 24(%1) \n\t" \
5384 "sw $4, 20($29) \n\t" \
5385 "lw $4, 28(%1) \n\t" \
5386 "sw $4, 24($29) \n\t" \
5387 "lw $4, 4(%1) \n\t" \
5388 "lw $5, 8(%1) \n\t" \
5389 "lw $6, 12(%1) \n\t" \
5390 "lw $7, 16(%1) \n\t" \
5391 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005392 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005393 "addu $29, $29, 32 \n\t" \
5394 "lw $28, 0($29) \n\t" \
5395 "lw $31, 4($29) \n\t" \
5396 "addu $29, $29, 8 \n\t" \
5397 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005398 : /*out*/ "=r" (_res) \
5399 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005400 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005401 ); \
5402 lval = (__typeof__(lval)) _res; \
5403 } while (0)
5404
5405#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5406 arg7,arg8) \
5407 do { \
5408 volatile OrigFn _orig = (orig); \
5409 volatile unsigned long _argvec[9]; \
5410 volatile unsigned long _res; \
5411 _argvec[0] = (unsigned long)_orig.nraddr; \
5412 _argvec[1] = (unsigned long)(arg1); \
5413 _argvec[2] = (unsigned long)(arg2); \
5414 _argvec[3] = (unsigned long)(arg3); \
5415 _argvec[4] = (unsigned long)(arg4); \
5416 _argvec[5] = (unsigned long)(arg5); \
5417 _argvec[6] = (unsigned long)(arg6); \
5418 _argvec[7] = (unsigned long)(arg7); \
5419 _argvec[8] = (unsigned long)(arg8); \
5420 __asm__ volatile( \
5421 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005422 "sw $28, 0($29) \n\t" \
5423 "sw $31, 4($29) \n\t" \
5424 "lw $4, 20(%1) \n\t" \
5425 "subu $29, $29, 40\n\t" \
5426 "sw $4, 16($29) \n\t" \
5427 "lw $4, 24(%1) \n\t" \
5428 "sw $4, 20($29) \n\t" \
5429 "lw $4, 28(%1) \n\t" \
5430 "sw $4, 24($29) \n\t" \
5431 "lw $4, 32(%1) \n\t" \
5432 "sw $4, 28($29) \n\t" \
5433 "lw $4, 4(%1) \n\t" \
5434 "lw $5, 8(%1) \n\t" \
5435 "lw $6, 12(%1) \n\t" \
5436 "lw $7, 16(%1) \n\t" \
5437 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005438 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005439 "addu $29, $29, 40 \n\t" \
5440 "lw $28, 0($29) \n\t" \
5441 "lw $31, 4($29) \n\t" \
5442 "addu $29, $29, 8 \n\t" \
5443 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005444 : /*out*/ "=r" (_res) \
5445 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005446 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005447 ); \
5448 lval = (__typeof__(lval)) _res; \
5449 } while (0)
5450
5451#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5452 arg7,arg8,arg9) \
5453 do { \
5454 volatile OrigFn _orig = (orig); \
5455 volatile unsigned long _argvec[10]; \
5456 volatile unsigned long _res; \
5457 _argvec[0] = (unsigned long)_orig.nraddr; \
5458 _argvec[1] = (unsigned long)(arg1); \
5459 _argvec[2] = (unsigned long)(arg2); \
5460 _argvec[3] = (unsigned long)(arg3); \
5461 _argvec[4] = (unsigned long)(arg4); \
5462 _argvec[5] = (unsigned long)(arg5); \
5463 _argvec[6] = (unsigned long)(arg6); \
5464 _argvec[7] = (unsigned long)(arg7); \
5465 _argvec[8] = (unsigned long)(arg8); \
5466 _argvec[9] = (unsigned long)(arg9); \
5467 __asm__ volatile( \
5468 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005469 "sw $28, 0($29) \n\t" \
5470 "sw $31, 4($29) \n\t" \
5471 "lw $4, 20(%1) \n\t" \
5472 "subu $29, $29, 40\n\t" \
5473 "sw $4, 16($29) \n\t" \
5474 "lw $4, 24(%1) \n\t" \
5475 "sw $4, 20($29) \n\t" \
5476 "lw $4, 28(%1) \n\t" \
5477 "sw $4, 24($29) \n\t" \
5478 "lw $4, 32(%1) \n\t" \
5479 "sw $4, 28($29) \n\t" \
5480 "lw $4, 36(%1) \n\t" \
5481 "sw $4, 32($29) \n\t" \
5482 "lw $4, 4(%1) \n\t" \
5483 "lw $5, 8(%1) \n\t" \
5484 "lw $6, 12(%1) \n\t" \
5485 "lw $7, 16(%1) \n\t" \
5486 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005487 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005488 "addu $29, $29, 40 \n\t" \
5489 "lw $28, 0($29) \n\t" \
5490 "lw $31, 4($29) \n\t" \
5491 "addu $29, $29, 8 \n\t" \
5492 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005493 : /*out*/ "=r" (_res) \
5494 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005495 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005496 ); \
5497 lval = (__typeof__(lval)) _res; \
5498 } while (0)
5499
5500#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5501 arg7,arg8,arg9,arg10) \
5502 do { \
5503 volatile OrigFn _orig = (orig); \
5504 volatile unsigned long _argvec[11]; \
5505 volatile unsigned long _res; \
5506 _argvec[0] = (unsigned long)_orig.nraddr; \
5507 _argvec[1] = (unsigned long)(arg1); \
5508 _argvec[2] = (unsigned long)(arg2); \
5509 _argvec[3] = (unsigned long)(arg3); \
5510 _argvec[4] = (unsigned long)(arg4); \
5511 _argvec[5] = (unsigned long)(arg5); \
5512 _argvec[6] = (unsigned long)(arg6); \
5513 _argvec[7] = (unsigned long)(arg7); \
5514 _argvec[8] = (unsigned long)(arg8); \
5515 _argvec[9] = (unsigned long)(arg9); \
5516 _argvec[10] = (unsigned long)(arg10); \
5517 __asm__ volatile( \
5518 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005519 "sw $28, 0($29) \n\t" \
5520 "sw $31, 4($29) \n\t" \
5521 "lw $4, 20(%1) \n\t" \
5522 "subu $29, $29, 48\n\t" \
5523 "sw $4, 16($29) \n\t" \
5524 "lw $4, 24(%1) \n\t" \
5525 "sw $4, 20($29) \n\t" \
5526 "lw $4, 28(%1) \n\t" \
5527 "sw $4, 24($29) \n\t" \
5528 "lw $4, 32(%1) \n\t" \
5529 "sw $4, 28($29) \n\t" \
5530 "lw $4, 36(%1) \n\t" \
5531 "sw $4, 32($29) \n\t" \
5532 "lw $4, 40(%1) \n\t" \
5533 "sw $4, 36($29) \n\t" \
5534 "lw $4, 4(%1) \n\t" \
5535 "lw $5, 8(%1) \n\t" \
5536 "lw $6, 12(%1) \n\t" \
5537 "lw $7, 16(%1) \n\t" \
5538 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005539 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005540 "addu $29, $29, 48 \n\t" \
5541 "lw $28, 0($29) \n\t" \
5542 "lw $31, 4($29) \n\t" \
5543 "addu $29, $29, 8 \n\t" \
5544 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005545 : /*out*/ "=r" (_res) \
5546 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005547 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005548 ); \
5549 lval = (__typeof__(lval)) _res; \
5550 } while (0)
5551
5552#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5553 arg6,arg7,arg8,arg9,arg10, \
5554 arg11) \
5555 do { \
5556 volatile OrigFn _orig = (orig); \
5557 volatile unsigned long _argvec[12]; \
5558 volatile unsigned long _res; \
5559 _argvec[0] = (unsigned long)_orig.nraddr; \
5560 _argvec[1] = (unsigned long)(arg1); \
5561 _argvec[2] = (unsigned long)(arg2); \
5562 _argvec[3] = (unsigned long)(arg3); \
5563 _argvec[4] = (unsigned long)(arg4); \
5564 _argvec[5] = (unsigned long)(arg5); \
5565 _argvec[6] = (unsigned long)(arg6); \
5566 _argvec[7] = (unsigned long)(arg7); \
5567 _argvec[8] = (unsigned long)(arg8); \
5568 _argvec[9] = (unsigned long)(arg9); \
5569 _argvec[10] = (unsigned long)(arg10); \
5570 _argvec[11] = (unsigned long)(arg11); \
5571 __asm__ volatile( \
5572 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005573 "sw $28, 0($29) \n\t" \
5574 "sw $31, 4($29) \n\t" \
5575 "lw $4, 20(%1) \n\t" \
5576 "subu $29, $29, 48\n\t" \
5577 "sw $4, 16($29) \n\t" \
5578 "lw $4, 24(%1) \n\t" \
5579 "sw $4, 20($29) \n\t" \
5580 "lw $4, 28(%1) \n\t" \
5581 "sw $4, 24($29) \n\t" \
5582 "lw $4, 32(%1) \n\t" \
5583 "sw $4, 28($29) \n\t" \
5584 "lw $4, 36(%1) \n\t" \
5585 "sw $4, 32($29) \n\t" \
5586 "lw $4, 40(%1) \n\t" \
5587 "sw $4, 36($29) \n\t" \
5588 "lw $4, 44(%1) \n\t" \
5589 "sw $4, 40($29) \n\t" \
5590 "lw $4, 4(%1) \n\t" \
5591 "lw $5, 8(%1) \n\t" \
5592 "lw $6, 12(%1) \n\t" \
5593 "lw $7, 16(%1) \n\t" \
5594 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005595 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005596 "addu $29, $29, 48 \n\t" \
5597 "lw $28, 0($29) \n\t" \
5598 "lw $31, 4($29) \n\t" \
5599 "addu $29, $29, 8 \n\t" \
5600 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005601 : /*out*/ "=r" (_res) \
5602 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005603 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005604 ); \
5605 lval = (__typeof__(lval)) _res; \
5606 } while (0)
5607
5608#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5609 arg6,arg7,arg8,arg9,arg10, \
5610 arg11,arg12) \
5611 do { \
5612 volatile OrigFn _orig = (orig); \
5613 volatile unsigned long _argvec[13]; \
5614 volatile unsigned long _res; \
5615 _argvec[0] = (unsigned long)_orig.nraddr; \
5616 _argvec[1] = (unsigned long)(arg1); \
5617 _argvec[2] = (unsigned long)(arg2); \
5618 _argvec[3] = (unsigned long)(arg3); \
5619 _argvec[4] = (unsigned long)(arg4); \
5620 _argvec[5] = (unsigned long)(arg5); \
5621 _argvec[6] = (unsigned long)(arg6); \
5622 _argvec[7] = (unsigned long)(arg7); \
5623 _argvec[8] = (unsigned long)(arg8); \
5624 _argvec[9] = (unsigned long)(arg9); \
5625 _argvec[10] = (unsigned long)(arg10); \
5626 _argvec[11] = (unsigned long)(arg11); \
5627 _argvec[12] = (unsigned long)(arg12); \
5628 __asm__ volatile( \
5629 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005630 "sw $28, 0($29) \n\t" \
5631 "sw $31, 4($29) \n\t" \
5632 "lw $4, 20(%1) \n\t" \
5633 "subu $29, $29, 56\n\t" \
5634 "sw $4, 16($29) \n\t" \
5635 "lw $4, 24(%1) \n\t" \
5636 "sw $4, 20($29) \n\t" \
5637 "lw $4, 28(%1) \n\t" \
5638 "sw $4, 24($29) \n\t" \
5639 "lw $4, 32(%1) \n\t" \
5640 "sw $4, 28($29) \n\t" \
5641 "lw $4, 36(%1) \n\t" \
5642 "sw $4, 32($29) \n\t" \
5643 "lw $4, 40(%1) \n\t" \
5644 "sw $4, 36($29) \n\t" \
5645 "lw $4, 44(%1) \n\t" \
5646 "sw $4, 40($29) \n\t" \
5647 "lw $4, 48(%1) \n\t" \
5648 "sw $4, 44($29) \n\t" \
5649 "lw $4, 4(%1) \n\t" \
5650 "lw $5, 8(%1) \n\t" \
5651 "lw $6, 12(%1) \n\t" \
5652 "lw $7, 16(%1) \n\t" \
5653 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005654 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005655 "addu $29, $29, 56 \n\t" \
5656 "lw $28, 0($29) \n\t" \
5657 "lw $31, 4($29) \n\t" \
5658 "addu $29, $29, 8 \n\t" \
5659 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005660 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00005661 : /*in*/ "r" (&_argvec[0]) \
5662 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005663 ); \
5664 lval = (__typeof__(lval)) _res; \
5665 } while (0)
5666
5667#endif /* PLAT_mips32_linux */
5668
petarj4df0bfc2013-02-27 23:17:33 +00005669/* ------------------------- mips64-linux ------------------------- */
5670
5671#if defined(PLAT_mips64_linux)
5672
5673/* These regs are trashed by the hidden call. */
5674#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5675"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5676"$25", "$31"
5677
5678/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5679 long) == 4. */
5680
5681#define CALL_FN_W_v(lval, orig) \
5682 do { \
5683 volatile OrigFn _orig = (orig); \
5684 volatile unsigned long _argvec[1]; \
5685 volatile unsigned long _res; \
5686 _argvec[0] = (unsigned long)_orig.nraddr; \
5687 __asm__ volatile( \
5688 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5689 VALGRIND_CALL_NOREDIR_T9 \
5690 "move %0, $2\n" \
5691 : /*out*/ "=r" (_res) \
5692 : /*in*/ "0" (&_argvec[0]) \
5693 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5694 ); \
5695 lval = (__typeof__(lval)) _res; \
5696 } while (0)
5697
5698#define CALL_FN_W_W(lval, orig, arg1) \
5699 do { \
5700 volatile OrigFn _orig = (orig); \
5701 volatile unsigned long _argvec[2]; \
5702 volatile unsigned long _res; \
5703 _argvec[0] = (unsigned long)_orig.nraddr; \
5704 _argvec[1] = (unsigned long)(arg1); \
5705 __asm__ volatile( \
5706 "ld $4, 8(%1)\n\t" /* arg1*/ \
5707 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5708 VALGRIND_CALL_NOREDIR_T9 \
5709 "move %0, $2\n" \
5710 : /*out*/ "=r" (_res) \
5711 : /*in*/ "r" (&_argvec[0]) \
5712 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5713 ); \
5714 lval = (__typeof__(lval)) _res; \
5715 } while (0)
5716
5717#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5718 do { \
5719 volatile OrigFn _orig = (orig); \
5720 volatile unsigned long _argvec[3]; \
5721 volatile unsigned long _res; \
5722 _argvec[0] = (unsigned long)_orig.nraddr; \
5723 _argvec[1] = (unsigned long)(arg1); \
5724 _argvec[2] = (unsigned long)(arg2); \
5725 __asm__ volatile( \
5726 "ld $4, 8(%1)\n\t" \
5727 "ld $5, 16(%1)\n\t" \
5728 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5729 VALGRIND_CALL_NOREDIR_T9 \
5730 "move %0, $2\n" \
5731 : /*out*/ "=r" (_res) \
5732 : /*in*/ "r" (&_argvec[0]) \
5733 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5734 ); \
5735 lval = (__typeof__(lval)) _res; \
5736 } while (0)
5737
5738#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5739 do { \
5740 volatile OrigFn _orig = (orig); \
5741 volatile unsigned long _argvec[4]; \
5742 volatile unsigned long _res; \
5743 _argvec[0] = (unsigned long)_orig.nraddr; \
5744 _argvec[1] = (unsigned long)(arg1); \
5745 _argvec[2] = (unsigned long)(arg2); \
5746 _argvec[3] = (unsigned long)(arg3); \
5747 __asm__ volatile( \
5748 "ld $4, 8(%1)\n\t" \
5749 "ld $5, 16(%1)\n\t" \
5750 "ld $6, 24(%1)\n\t" \
5751 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5752 VALGRIND_CALL_NOREDIR_T9 \
5753 "move %0, $2\n" \
5754 : /*out*/ "=r" (_res) \
5755 : /*in*/ "r" (&_argvec[0]) \
5756 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5757 ); \
5758 lval = (__typeof__(lval)) _res; \
5759 } while (0)
5760
5761#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5762 do { \
5763 volatile OrigFn _orig = (orig); \
5764 volatile unsigned long _argvec[5]; \
5765 volatile unsigned long _res; \
5766 _argvec[0] = (unsigned long)_orig.nraddr; \
5767 _argvec[1] = (unsigned long)(arg1); \
5768 _argvec[2] = (unsigned long)(arg2); \
5769 _argvec[3] = (unsigned long)(arg3); \
5770 _argvec[4] = (unsigned long)(arg4); \
5771 __asm__ volatile( \
5772 "ld $4, 8(%1)\n\t" \
5773 "ld $5, 16(%1)\n\t" \
5774 "ld $6, 24(%1)\n\t" \
5775 "ld $7, 32(%1)\n\t" \
5776 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5777 VALGRIND_CALL_NOREDIR_T9 \
5778 "move %0, $2\n" \
5779 : /*out*/ "=r" (_res) \
5780 : /*in*/ "r" (&_argvec[0]) \
5781 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5782 ); \
5783 lval = (__typeof__(lval)) _res; \
5784 } while (0)
5785
5786#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5787 do { \
5788 volatile OrigFn _orig = (orig); \
5789 volatile unsigned long _argvec[6]; \
5790 volatile unsigned long _res; \
5791 _argvec[0] = (unsigned long)_orig.nraddr; \
5792 _argvec[1] = (unsigned long)(arg1); \
5793 _argvec[2] = (unsigned long)(arg2); \
5794 _argvec[3] = (unsigned long)(arg3); \
5795 _argvec[4] = (unsigned long)(arg4); \
5796 _argvec[5] = (unsigned long)(arg5); \
5797 __asm__ volatile( \
5798 "ld $4, 8(%1)\n\t" \
5799 "ld $5, 16(%1)\n\t" \
5800 "ld $6, 24(%1)\n\t" \
5801 "ld $7, 32(%1)\n\t" \
5802 "ld $8, 40(%1)\n\t" \
5803 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5804 VALGRIND_CALL_NOREDIR_T9 \
5805 "move %0, $2\n" \
5806 : /*out*/ "=r" (_res) \
5807 : /*in*/ "r" (&_argvec[0]) \
5808 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5809 ); \
5810 lval = (__typeof__(lval)) _res; \
5811 } while (0)
5812
5813#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5814 do { \
5815 volatile OrigFn _orig = (orig); \
5816 volatile unsigned long _argvec[7]; \
5817 volatile unsigned long _res; \
5818 _argvec[0] = (unsigned long)_orig.nraddr; \
5819 _argvec[1] = (unsigned long)(arg1); \
5820 _argvec[2] = (unsigned long)(arg2); \
5821 _argvec[3] = (unsigned long)(arg3); \
5822 _argvec[4] = (unsigned long)(arg4); \
5823 _argvec[5] = (unsigned long)(arg5); \
5824 _argvec[6] = (unsigned long)(arg6); \
5825 __asm__ volatile( \
5826 "ld $4, 8(%1)\n\t" \
5827 "ld $5, 16(%1)\n\t" \
5828 "ld $6, 24(%1)\n\t" \
5829 "ld $7, 32(%1)\n\t" \
5830 "ld $8, 40(%1)\n\t" \
5831 "ld $9, 48(%1)\n\t" \
5832 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5833 VALGRIND_CALL_NOREDIR_T9 \
5834 "move %0, $2\n" \
5835 : /*out*/ "=r" (_res) \
5836 : /*in*/ "r" (&_argvec[0]) \
5837 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5838 ); \
5839 lval = (__typeof__(lval)) _res; \
5840 } while (0)
5841
5842#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5843 arg7) \
5844 do { \
5845 volatile OrigFn _orig = (orig); \
5846 volatile unsigned long _argvec[8]; \
5847 volatile unsigned long _res; \
5848 _argvec[0] = (unsigned long)_orig.nraddr; \
5849 _argvec[1] = (unsigned long)(arg1); \
5850 _argvec[2] = (unsigned long)(arg2); \
5851 _argvec[3] = (unsigned long)(arg3); \
5852 _argvec[4] = (unsigned long)(arg4); \
5853 _argvec[5] = (unsigned long)(arg5); \
5854 _argvec[6] = (unsigned long)(arg6); \
5855 _argvec[7] = (unsigned long)(arg7); \
5856 __asm__ volatile( \
5857 "ld $4, 8(%1)\n\t" \
5858 "ld $5, 16(%1)\n\t" \
5859 "ld $6, 24(%1)\n\t" \
5860 "ld $7, 32(%1)\n\t" \
5861 "ld $8, 40(%1)\n\t" \
5862 "ld $9, 48(%1)\n\t" \
5863 "ld $10, 56(%1)\n\t" \
5864 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5865 VALGRIND_CALL_NOREDIR_T9 \
5866 "move %0, $2\n" \
5867 : /*out*/ "=r" (_res) \
5868 : /*in*/ "r" (&_argvec[0]) \
5869 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5870 ); \
5871 lval = (__typeof__(lval)) _res; \
5872 } while (0)
5873
5874#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5875 arg7,arg8) \
5876 do { \
5877 volatile OrigFn _orig = (orig); \
5878 volatile unsigned long _argvec[9]; \
5879 volatile unsigned long _res; \
5880 _argvec[0] = (unsigned long)_orig.nraddr; \
5881 _argvec[1] = (unsigned long)(arg1); \
5882 _argvec[2] = (unsigned long)(arg2); \
5883 _argvec[3] = (unsigned long)(arg3); \
5884 _argvec[4] = (unsigned long)(arg4); \
5885 _argvec[5] = (unsigned long)(arg5); \
5886 _argvec[6] = (unsigned long)(arg6); \
5887 _argvec[7] = (unsigned long)(arg7); \
5888 _argvec[8] = (unsigned long)(arg8); \
5889 __asm__ volatile( \
5890 "ld $4, 8(%1)\n\t" \
5891 "ld $5, 16(%1)\n\t" \
5892 "ld $6, 24(%1)\n\t" \
5893 "ld $7, 32(%1)\n\t" \
5894 "ld $8, 40(%1)\n\t" \
5895 "ld $9, 48(%1)\n\t" \
5896 "ld $10, 56(%1)\n\t" \
5897 "ld $11, 64(%1)\n\t" \
5898 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5899 VALGRIND_CALL_NOREDIR_T9 \
5900 "move %0, $2\n" \
5901 : /*out*/ "=r" (_res) \
5902 : /*in*/ "r" (&_argvec[0]) \
5903 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5904 ); \
5905 lval = (__typeof__(lval)) _res; \
5906 } while (0)
5907
5908#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5909 arg7,arg8,arg9) \
5910 do { \
5911 volatile OrigFn _orig = (orig); \
5912 volatile unsigned long _argvec[10]; \
5913 volatile unsigned long _res; \
5914 _argvec[0] = (unsigned long)_orig.nraddr; \
5915 _argvec[1] = (unsigned long)(arg1); \
5916 _argvec[2] = (unsigned long)(arg2); \
5917 _argvec[3] = (unsigned long)(arg3); \
5918 _argvec[4] = (unsigned long)(arg4); \
5919 _argvec[5] = (unsigned long)(arg5); \
5920 _argvec[6] = (unsigned long)(arg6); \
5921 _argvec[7] = (unsigned long)(arg7); \
5922 _argvec[8] = (unsigned long)(arg8); \
5923 _argvec[9] = (unsigned long)(arg9); \
5924 __asm__ volatile( \
5925 "dsubu $29, $29, 8\n\t" \
5926 "ld $4, 72(%1)\n\t" \
5927 "sd $4, 0($29)\n\t" \
5928 "ld $4, 8(%1)\n\t" \
5929 "ld $5, 16(%1)\n\t" \
5930 "ld $6, 24(%1)\n\t" \
5931 "ld $7, 32(%1)\n\t" \
5932 "ld $8, 40(%1)\n\t" \
5933 "ld $9, 48(%1)\n\t" \
5934 "ld $10, 56(%1)\n\t" \
5935 "ld $11, 64(%1)\n\t" \
5936 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5937 VALGRIND_CALL_NOREDIR_T9 \
5938 "daddu $29, $29, 8\n\t" \
5939 "move %0, $2\n" \
5940 : /*out*/ "=r" (_res) \
5941 : /*in*/ "r" (&_argvec[0]) \
5942 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5943 ); \
5944 lval = (__typeof__(lval)) _res; \
5945 } while (0)
5946
5947#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5948 arg7,arg8,arg9,arg10) \
5949 do { \
5950 volatile OrigFn _orig = (orig); \
5951 volatile unsigned long _argvec[11]; \
5952 volatile unsigned long _res; \
5953 _argvec[0] = (unsigned long)_orig.nraddr; \
5954 _argvec[1] = (unsigned long)(arg1); \
5955 _argvec[2] = (unsigned long)(arg2); \
5956 _argvec[3] = (unsigned long)(arg3); \
5957 _argvec[4] = (unsigned long)(arg4); \
5958 _argvec[5] = (unsigned long)(arg5); \
5959 _argvec[6] = (unsigned long)(arg6); \
5960 _argvec[7] = (unsigned long)(arg7); \
5961 _argvec[8] = (unsigned long)(arg8); \
5962 _argvec[9] = (unsigned long)(arg9); \
5963 _argvec[10] = (unsigned long)(arg10); \
5964 __asm__ volatile( \
5965 "dsubu $29, $29, 16\n\t" \
5966 "ld $4, 72(%1)\n\t" \
5967 "sd $4, 0($29)\n\t" \
5968 "ld $4, 80(%1)\n\t" \
5969 "sd $4, 8($29)\n\t" \
5970 "ld $4, 8(%1)\n\t" \
5971 "ld $5, 16(%1)\n\t" \
5972 "ld $6, 24(%1)\n\t" \
5973 "ld $7, 32(%1)\n\t" \
5974 "ld $8, 40(%1)\n\t" \
5975 "ld $9, 48(%1)\n\t" \
5976 "ld $10, 56(%1)\n\t" \
5977 "ld $11, 64(%1)\n\t" \
5978 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5979 VALGRIND_CALL_NOREDIR_T9 \
5980 "daddu $29, $29, 16\n\t" \
5981 "move %0, $2\n" \
5982 : /*out*/ "=r" (_res) \
5983 : /*in*/ "r" (&_argvec[0]) \
5984 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5985 ); \
5986 lval = (__typeof__(lval)) _res; \
5987 } while (0)
5988
5989#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5990 arg6,arg7,arg8,arg9,arg10, \
5991 arg11) \
5992 do { \
5993 volatile OrigFn _orig = (orig); \
5994 volatile unsigned long _argvec[12]; \
5995 volatile unsigned long _res; \
5996 _argvec[0] = (unsigned long)_orig.nraddr; \
5997 _argvec[1] = (unsigned long)(arg1); \
5998 _argvec[2] = (unsigned long)(arg2); \
5999 _argvec[3] = (unsigned long)(arg3); \
6000 _argvec[4] = (unsigned long)(arg4); \
6001 _argvec[5] = (unsigned long)(arg5); \
6002 _argvec[6] = (unsigned long)(arg6); \
6003 _argvec[7] = (unsigned long)(arg7); \
6004 _argvec[8] = (unsigned long)(arg8); \
6005 _argvec[9] = (unsigned long)(arg9); \
6006 _argvec[10] = (unsigned long)(arg10); \
6007 _argvec[11] = (unsigned long)(arg11); \
6008 __asm__ volatile( \
6009 "dsubu $29, $29, 24\n\t" \
6010 "ld $4, 72(%1)\n\t" \
6011 "sd $4, 0($29)\n\t" \
6012 "ld $4, 80(%1)\n\t" \
6013 "sd $4, 8($29)\n\t" \
6014 "ld $4, 88(%1)\n\t" \
6015 "sd $4, 16($29)\n\t" \
6016 "ld $4, 8(%1)\n\t" \
6017 "ld $5, 16(%1)\n\t" \
6018 "ld $6, 24(%1)\n\t" \
6019 "ld $7, 32(%1)\n\t" \
6020 "ld $8, 40(%1)\n\t" \
6021 "ld $9, 48(%1)\n\t" \
6022 "ld $10, 56(%1)\n\t" \
6023 "ld $11, 64(%1)\n\t" \
6024 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6025 VALGRIND_CALL_NOREDIR_T9 \
6026 "daddu $29, $29, 24\n\t" \
6027 "move %0, $2\n" \
6028 : /*out*/ "=r" (_res) \
6029 : /*in*/ "r" (&_argvec[0]) \
6030 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6031 ); \
6032 lval = (__typeof__(lval)) _res; \
6033 } while (0)
6034
6035#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
6036 arg6,arg7,arg8,arg9,arg10, \
6037 arg11,arg12) \
6038 do { \
6039 volatile OrigFn _orig = (orig); \
6040 volatile unsigned long _argvec[13]; \
6041 volatile unsigned long _res; \
6042 _argvec[0] = (unsigned long)_orig.nraddr; \
6043 _argvec[1] = (unsigned long)(arg1); \
6044 _argvec[2] = (unsigned long)(arg2); \
6045 _argvec[3] = (unsigned long)(arg3); \
6046 _argvec[4] = (unsigned long)(arg4); \
6047 _argvec[5] = (unsigned long)(arg5); \
6048 _argvec[6] = (unsigned long)(arg6); \
6049 _argvec[7] = (unsigned long)(arg7); \
6050 _argvec[8] = (unsigned long)(arg8); \
6051 _argvec[9] = (unsigned long)(arg9); \
6052 _argvec[10] = (unsigned long)(arg10); \
6053 _argvec[11] = (unsigned long)(arg11); \
6054 _argvec[12] = (unsigned long)(arg12); \
6055 __asm__ volatile( \
6056 "dsubu $29, $29, 32\n\t" \
6057 "ld $4, 72(%1)\n\t" \
6058 "sd $4, 0($29)\n\t" \
6059 "ld $4, 80(%1)\n\t" \
6060 "sd $4, 8($29)\n\t" \
6061 "ld $4, 88(%1)\n\t" \
6062 "sd $4, 16($29)\n\t" \
6063 "ld $4, 96(%1)\n\t" \
6064 "sd $4, 24($29)\n\t" \
6065 "ld $4, 8(%1)\n\t" \
6066 "ld $5, 16(%1)\n\t" \
6067 "ld $6, 24(%1)\n\t" \
6068 "ld $7, 32(%1)\n\t" \
6069 "ld $8, 40(%1)\n\t" \
6070 "ld $9, 48(%1)\n\t" \
6071 "ld $10, 56(%1)\n\t" \
6072 "ld $11, 64(%1)\n\t" \
6073 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6074 VALGRIND_CALL_NOREDIR_T9 \
6075 "daddu $29, $29, 32\n\t" \
6076 "move %0, $2\n" \
6077 : /*out*/ "=r" (_res) \
6078 : /*in*/ "r" (&_argvec[0]) \
6079 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6080 ); \
6081 lval = (__typeof__(lval)) _res; \
6082 } while (0)
6083
6084#endif /* PLAT_mips64_linux */
6085
sewardj0ec07f32006-01-12 12:32:32 +00006086
6087/* ------------------------------------------------------------------ */
6088/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
6089/* */
njn30d76c62005-06-18 15:07:39 +00006090/* ------------------------------------------------------------------ */
6091
sewardj2e93c502002-04-12 11:12:52 +00006092/* Some request codes. There are many more of these, but most are not
6093 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00006094 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00006095
sewardj0ec07f32006-01-12 12:32:32 +00006096 Core ones are in the range 0x00000000--0x0000ffff. The non-public
6097 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00006098*/
6099
sewardj0ec07f32006-01-12 12:32:32 +00006100/* These macros are used by tools -- they must be public, but don't
6101 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00006102#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00006103 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00006104#define VG_IS_TOOL_USERREQ(a, b, v) \
6105 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00006106
sewardj5ce4b152006-03-11 12:57:41 +00006107/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
6108 This enum comprises an ABI exported by Valgrind to programs
6109 which use client requests. DO NOT CHANGE THE ORDER OF THESE
6110 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00006111typedef
njn4c791212003-05-02 17:53:54 +00006112 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
6113 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00006114
sewardj0ec07f32006-01-12 12:32:32 +00006115 /* These allow any function to be called from the simulated
6116 CPU but run on the real CPU. Nb: the first arg passed to
6117 the function is always the ThreadId of the running
6118 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00006119 function, etc. */
njn4c791212003-05-02 17:53:54 +00006120 VG_USERREQ__CLIENT_CALL0 = 0x1101,
6121 VG_USERREQ__CLIENT_CALL1 = 0x1102,
6122 VG_USERREQ__CLIENT_CALL2 = 0x1103,
6123 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00006124
sewardj0ec07f32006-01-12 12:32:32 +00006125 /* Can be useful in regression testing suites -- eg. can
6126 send Valgrind's output to /dev/null and still count
6127 errors. */
njn4c791212003-05-02 17:53:54 +00006128 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00006129
philippe46207652013-01-20 17:11:58 +00006130 /* Allows the client program and/or gdbserver to execute a monitor
6131 command. */
sewardj3b290482011-05-06 21:02:55 +00006132 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
6133
sewardj0ec07f32006-01-12 12:32:32 +00006134 /* These are useful and can be interpreted by any tool that
6135 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00006136 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00006137 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00006138 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00006139 /* Memory pool support. */
6140 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
6141 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
6142 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
6143 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00006144 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00006145 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
6146 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
6147 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00006148
fitzhardinge39de4b42003-10-31 07:12:21 +00006149 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00006150 /* The first two pass the va_list argument by value, which
6151 assumes it is the same size as or smaller than a UWord,
6152 which generally isn't the case. Hence are deprecated.
6153 The second two pass the vargs by reference and so are
6154 immune to this problem. */
6155 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00006156 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00006157 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00006158 /* both :: char* fmt, va_list* vargs */
6159 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
6160 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00006161
6162 /* Stack support. */
6163 VG_USERREQ__STACK_REGISTER = 0x1501,
6164 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00006165 VG_USERREQ__STACK_CHANGE = 0x1503,
6166
6167 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00006168 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
6169
6170 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00006171 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
6172
6173 /* Disable/enable error reporting level. Takes a single
6174 Word arg which is the delta to this thread's error
6175 disablement indicator. Hence 1 disables or further
6176 disables errors, and -1 moves back towards enablement.
6177 Other values are not allowed. */
florianbb913cd2012-08-28 16:50:39 +00006178 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
6179
6180 /* Initialise IR injection */
6181 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901
njn25e49d8e72002-09-23 09:36:25 +00006182 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00006183
sewardj0ec07f32006-01-12 12:32:32 +00006184#if !defined(__GNUC__)
6185# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00006186#endif
sewardj2e93c502002-04-12 11:12:52 +00006187
bartfa5115a2010-09-02 09:33:02 +00006188
sewardj0ec07f32006-01-12 12:32:32 +00006189/* Returns the number of Valgrinds this code is running under. That
6190 is, 0 if running natively, 1 if running under Valgrind, 2 if
6191 running under Valgrind which is running under another Valgrind,
6192 etc. */
bartfa5115a2010-09-02 09:33:02 +00006193#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00006194 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00006195 VG_USERREQ__RUNNING_ON_VALGRIND, \
6196 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00006197
6198
sewardj18d75132002-05-16 11:06:21 +00006199/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
6200 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
6201 since it provides a way to make sure valgrind will retranslate the
6202 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00006203#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
6204 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
6205 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00006206
njn26aba4d2005-05-16 13:31:23 +00006207
sewardj0ec07f32006-01-12 12:32:32 +00006208/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00006209 Possibly with a backtrace. This is a really ugly hack. The return value
6210 is the number of characters printed, excluding the "**<pid>** " part at the
6211 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00006212
bart42f83fe2012-01-31 10:13:51 +00006213#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00006214/* Modern GCC will optimize the static routine out if unused,
6215 and unused attribute will shut down warnings about it. */
6216static int VALGRIND_PRINTF(const char *format, ...)
6217 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00006218#endif
sewardj7eca0cc2006-04-12 17:15:35 +00006219static int
bart0da2c772010-09-01 10:18:36 +00006220#if defined(_MSC_VER)
6221__inline
6222#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00006223VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00006224{
bart8c7e25f2011-03-04 16:55:56 +00006225#if defined(NVALGRIND)
6226 return 0;
6227#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00006228#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006229 uintptr_t _qzz_res;
6230#else
njnc6168192004-11-29 13:54:10 +00006231 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00006232#endif
sewardjc560fb32010-01-28 15:23:54 +00006233 va_list vargs;
6234 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00006235#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006236 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00006237 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00006238 (uintptr_t)format,
6239 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00006240 0, 0, 0);
6241#else
bart575ce8e2011-05-15 07:04:03 +00006242 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00006243 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00006244 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00006245 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00006246 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00006247#endif
sewardjc560fb32010-01-28 15:23:54 +00006248 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00006249 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00006250#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00006251}
6252
bart42f83fe2012-01-31 10:13:51 +00006253#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00006254static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6255 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00006256#endif
sewardj7eca0cc2006-04-12 17:15:35 +00006257static int
bart0da2c772010-09-01 10:18:36 +00006258#if defined(_MSC_VER)
6259__inline
6260#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00006261VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00006262{
bart8c7e25f2011-03-04 16:55:56 +00006263#if defined(NVALGRIND)
6264 return 0;
6265#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00006266#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006267 uintptr_t _qzz_res;
6268#else
njnc6168192004-11-29 13:54:10 +00006269 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00006270#endif
sewardjc560fb32010-01-28 15:23:54 +00006271 va_list vargs;
6272 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00006273#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006274 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00006275 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00006276 (uintptr_t)format,
6277 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00006278 0, 0, 0);
6279#else
bart575ce8e2011-05-15 07:04:03 +00006280 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00006281 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00006282 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00006283 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00006284 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00006285#endif
sewardjc560fb32010-01-28 15:23:54 +00006286 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00006287 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00006288#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00006289}
sewardj18d75132002-05-16 11:06:21 +00006290
sewardj0ec07f32006-01-12 12:32:32 +00006291
njn3e884182003-04-15 13:03:23 +00006292/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00006293 real CPU, calling an arbitary function.
6294
6295 Note that the current ThreadId is inserted as the first argument.
6296 So this call:
6297
6298 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
6299
6300 requires f to have this signature:
6301
6302 Word f(Word tid, Word arg1, Word arg2)
6303
6304 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00006305
6306 Note that these client requests are not entirely reliable. For example,
6307 if you call a function with them that subsequently calls printf(),
6308 there's a high chance Valgrind will crash. Generally, your prospects of
6309 these working are made higher if the called function does not refer to
6310 any global variables, and does not refer to any libc or other functions
6311 (printf et al). Any kind of entanglement with libc or dynamic linking is
6312 likely to have a bad outcome, for tricky reasons which we've grappled
6313 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00006314*/
sewardj0ec07f32006-01-12 12:32:32 +00006315#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00006316 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6317 VG_USERREQ__CLIENT_CALL0, \
6318 _qyy_fn, \
6319 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00006320
bart575ce8e2011-05-15 07:04:03 +00006321#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
6322 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6323 VG_USERREQ__CLIENT_CALL1, \
6324 _qyy_fn, \
6325 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00006326
bart575ce8e2011-05-15 07:04:03 +00006327#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
6328 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6329 VG_USERREQ__CLIENT_CALL2, \
6330 _qyy_fn, \
6331 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00006332
sewardj0ec07f32006-01-12 12:32:32 +00006333#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00006334 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6335 VG_USERREQ__CLIENT_CALL3, \
6336 _qyy_fn, \
6337 _qyy_arg1, _qyy_arg2, \
6338 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00006339
6340
nethercote7cc9c232004-01-21 15:08:04 +00006341/* Counts the number of errors that have been recorded by a tool. Nb:
6342 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00006343 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00006344#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00006345 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
6346 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00006347 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00006348 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00006349
njn3ac96952009-07-09 23:35:44 +00006350/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
6351 when heap blocks are allocated in order to give accurate results. This
6352 happens automatically for the standard allocator functions such as
6353 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
6354 delete[], etc.
njnd7994182003-10-02 13:44:04 +00006355
njn3ac96952009-07-09 23:35:44 +00006356 But if your program uses a custom allocator, this doesn't automatically
6357 happen, and Valgrind will not do as well. For example, if you allocate
6358 superblocks with mmap() and then allocates chunks of the superblocks, all
6359 Valgrind's observations will be at the mmap() level and it won't know that
6360 the chunks should be considered separate entities. In Memcheck's case,
6361 that means you probably won't get heap block overrun detection (because
6362 there won't be redzones marked as unaddressable) and you definitely won't
6363 get any leak detection.
6364
6365 The following client requests allow a custom allocator to be annotated so
6366 that it can be handled accurately by Valgrind.
6367
6368 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
6369 by a malloc()-like function. For Memcheck (an illustrative case), this
6370 does two things:
6371
6372 - It records that the block has been allocated. This means any addresses
6373 within the block mentioned in error messages will be
6374 identified as belonging to the block. It also means that if the block
6375 isn't freed it will be detected by the leak checker.
6376
6377 - It marks the block as being addressable and undefined (if 'is_zeroed' is
6378 not set), or addressable and defined (if 'is_zeroed' is set). This
6379 controls how accesses to the block by the program are handled.
6380
6381 'addr' is the start of the usable block (ie. after any
6382 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
6383 can apply redzones -- these are blocks of padding at the start and end of
6384 each block. Adding redzones is recommended as it makes it much more likely
6385 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
6386 zeroed (or filled with another predictable value), as is the case for
6387 calloc().
6388
6389 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
6390 heap block -- that will be used by the client program -- is allocated.
6391 It's best to put it at the outermost level of the allocator if possible;
6392 for example, if you have a function my_alloc() which calls
6393 internal_alloc(), and the client request is put inside internal_alloc(),
6394 stack traces relating to the heap block will contain entries for both
6395 my_alloc() and internal_alloc(), which is probably not what you want.
6396
njnb965efb2009-08-10 07:36:54 +00006397 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
6398 custom blocks from within a heap block, B, that has been allocated with
6399 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
6400 -- the custom blocks will take precedence.
6401
njn3ac96952009-07-09 23:35:44 +00006402 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
6403 Memcheck, it does two things:
6404
6405 - It records that the block has been deallocated. This assumes that the
6406 block was annotated as having been allocated via
6407 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
6408
6409 - It marks the block as being unaddressable.
6410
6411 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
6412 heap block is deallocated.
6413
bart91347382011-03-25 20:07:25 +00006414 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
6415 Memcheck, it does four things:
6416
6417 - It records that the size of a block has been changed. This assumes that
6418 the block was annotated as having been allocated via
6419 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
6420
6421 - If the block shrunk, it marks the freed memory as being unaddressable.
6422
6423 - If the block grew, it marks the new area as undefined and defines a red
6424 zone past the end of the new block.
6425
6426 - The V-bits of the overlap between the old and the new block are preserved.
6427
6428 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
6429 and before deallocation of the old block.
6430
6431 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00006432 allocator working well with Memcheck. More specifically, if your allocator
6433 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
6434 will be necessary to mark the memory as addressable just before the zeroing
6435 occurs, otherwise you'll get a lot of invalid write errors. For example,
6436 you'll need to do this if your allocator recycles freed blocks, but it
6437 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
6438 Alternatively, if your allocator reuses freed blocks for allocator-internal
6439 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
6440
6441 Really, what's happening is a blurring of the lines between the client
6442 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
6443 memory should be considered unaddressable to the client program, but the
6444 allocator knows more than the rest of the client program and so may be able
6445 to safely access it. Extra client requests are necessary for Valgrind to
6446 understand the distinction between the allocator and the rest of the
6447 program.
6448
njn32f8d8c2009-07-15 02:31:45 +00006449 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00006450*/
sewardj4b3a7422011-10-24 13:21:57 +00006451#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
6452 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
6453 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00006454
njn32f8d8c2009-07-15 02:31:45 +00006455/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6456 Ignored if addr == 0.
6457*/
sewardj4b3a7422011-10-24 13:21:57 +00006458#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
6459 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
6460 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00006461
6462/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6463 Ignored if addr == 0.
6464*/
sewardj4b3a7422011-10-24 13:21:57 +00006465#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
6466 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
6467 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00006468
rjwalshbc0bb832004-06-19 18:12:36 +00006469/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00006470#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00006471 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
6472 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00006473
6474/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00006475#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00006476 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
6477 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00006478
6479/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00006480#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00006481 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
6482 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00006483
6484/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00006485#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00006486 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
6487 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00006488
sewardj2c1c9df2006-07-28 00:06:37 +00006489/* Disassociate any pieces outside a particular range. */
6490#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00006491 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
6492 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00006493
sewardjc740d762006-10-05 17:59:23 +00006494/* Resize and/or move a piece associated with a memory pool. */
6495#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00006496 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
6497 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00006498
6499/* Resize and/or move a piece associated with a memory pool. */
6500#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00006501 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
6502 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00006503
6504/* Return 1 if a mempool exists, else 0. */
6505#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00006506 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00006507 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00006508 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00006509
rjwalsh0140af52005-06-04 20:42:33 +00006510/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00006511#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00006512 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00006513 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00006514 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00006515
6516/* Unmark the piece of memory associated with a stack id as being a
6517 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00006518#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00006519 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
6520 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00006521
6522/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00006523#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00006524 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
6525 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00006526
sewardjc8259b82009-04-22 22:42:10 +00006527/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00006528#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
6529 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
6530 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00006531
sewardj5c659622010-08-20 18:22:07 +00006532/* Map a code address to a source file name and line number. buf64
6533 must point to a 64-byte buffer in the caller's address space. The
6534 result will be dumped in there and is guaranteed to be zero
6535 terminated. If no info is found, the first byte is set to zero. */
6536#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00006537 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00006538 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00006539 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00006540
sewardjdc873c02011-07-24 16:02:33 +00006541/* Disable error reporting for this thread. Behaves in a stack like
6542 way, so you can safely call this multiple times provided that
6543 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
6544 to re-enable reporting. The first call of this macro disables
6545 reporting. Subsequent calls have no effect except to increase the
6546 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
6547 reporting. Child threads do not inherit this setting from their
6548 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00006549#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00006550 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6551 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00006552
6553/* Re-enable error reporting, as per comments on
6554 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00006555#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00006556 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6557 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00006558
philippe46207652013-01-20 17:11:58 +00006559/* Execute a monitor command from the client program.
6560 If a connection is opened with GDB, the output will be sent
6561 according to the output mode set for vgdb.
6562 If no connection is opened, output will go to the log output.
6563 Returns 1 if command not recognised, 0 otherwise. */
6564#define VALGRIND_MONITOR_COMMAND(command) \
6565 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
6566 command, 0, 0, 0, 0)
6567
6568
sewardjc112c8e2011-06-24 18:26:11 +00006569#undef PLAT_x86_darwin
6570#undef PLAT_amd64_darwin
6571#undef PLAT_x86_win32
bartaaaf21d2013-08-25 06:10:24 +00006572#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +00006573#undef PLAT_x86_linux
6574#undef PLAT_amd64_linux
6575#undef PLAT_ppc32_linux
carllcae0cc22014-08-07 23:17:29 +00006576#undef PLAT_ppc64be_linux
carll582d5822014-08-07 23:35:54 +00006577#undef PLAT_ppc64le_linux
sewardj59570ff2010-01-01 11:59:33 +00006578#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00006579#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +00006580#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +00006581#undef PLAT_mips64_linux
sewardj0ec07f32006-01-12 12:32:32 +00006582
njn3e884182003-04-15 13:03:23 +00006583#endif /* __VALGRIND_H */