blob: 13e34da21b99990ec03968b3280b038d57a769ed [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
118#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000119#undef PLAT_arm_linux
sewardjf0c12502014-01-12 12:54:00 +0000120#undef PLAT_arm64_linux
sewardjb5b87402011-03-07 16:05:35 +0000121#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +0000122#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +0000123#undef PLAT_mips64_linux
sewardjb5b87402011-03-07 16:05:35 +0000124
sewardj0ec07f32006-01-12 12:32:32 +0000125
sewardj6e9de462011-06-28 07:25:29 +0000126#if defined(__APPLE__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000127# define PLAT_x86_darwin 1
128#elif defined(__APPLE__) && defined(__x86_64__)
129# define PLAT_amd64_darwin 1
sewardj6e9de462011-06-28 07:25:29 +0000130#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
131 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000132# define PLAT_x86_win32 1
bartaaaf21d2013-08-25 06:10:24 +0000133#elif defined(__MINGW64__) || (defined(_WIN64) && defined(_M_X64))
134# define PLAT_amd64_win64 1
sewardj59570ff2010-01-01 11:59:33 +0000135#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000136# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000137#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000138# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000139#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000140# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000141#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000142# define PLAT_ppc64_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000143#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
sewardj59570ff2010-01-01 11:59:33 +0000144# define PLAT_arm_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000145#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
146# define PLAT_arm64_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000147#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
148# define PLAT_s390x_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000149#elif defined(__linux__) && defined(__mips__) && (__mips==64)
petarj4df0bfc2013-02-27 23:17:33 +0000150# define PLAT_mips64_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000151#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
sewardj5db15402012-06-07 09:13:21 +0000152# define PLAT_mips32_linux 1
njnf76d27a2009-05-28 01:53:07 +0000153#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000154/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000155 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000156# if !defined(NVALGRIND)
157# define NVALGRIND 1
158# endif
159#endif
160
161
njn30d76c62005-06-18 15:07:39 +0000162/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000163/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
164/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000165/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000166
bart575ce8e2011-05-15 07:04:03 +0000167/*
168 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
169 * request. Accepts both pointers and integers as arguments.
170 *
sewardj4b3a7422011-10-24 13:21:57 +0000171 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
172 * client request that does not return a value.
173
bart575ce8e2011-05-15 07:04:03 +0000174 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000175 * client request and whose value equals the client request result. Accepts
176 * both pointers and integers as arguments. Note that such calls are not
177 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000178 */
179
180#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
181 _zzq_request, _zzq_arg1, _zzq_arg2, \
182 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000183 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000184 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000185 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000186
sewardj4b3a7422011-10-24 13:21:57 +0000187#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
188 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
189 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
190 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
191 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
192
sewardj0ec07f32006-01-12 12:32:32 +0000193#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000194
195/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000196 from the compiled code (analogous to NDEBUG's effects on
197 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000198#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
199 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000200 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000201 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000202
sewardj0ec07f32006-01-12 12:32:32 +0000203#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000204
sewardj0ec07f32006-01-12 12:32:32 +0000205/* The following defines the magic code sequences which the JITter
206 spots and handles magically. Don't look too closely at them as
207 they will rot your brain.
208
209 The assembly code sequences for all architectures is in this one
210 file. This is because this file must be stand-alone, and we don't
211 want to have multiple files.
212
213 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
214 value gets put in the return slot, so that everything works when
215 this is executed not under Valgrind. Args are passed in a memory
216 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000217 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000218
nethercote54265442004-10-26 12:56:58 +0000219 The macro args are:
220 _zzq_rlval result lvalue
221 _zzq_default default value (result returned when running on real CPU)
222 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000223 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000224
sewardj0ec07f32006-01-12 12:32:32 +0000225 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000226 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
227 guest's NRADDR pseudo-register and whatever other information is
228 needed to safely run the call original from the wrapper: on
229 ppc64-linux, the R2 value at the divert point is also needed. This
230 information is abstracted into a user-visible type, OrigFn.
231
232 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
233 guest, but guarantees that the branch instruction will not be
234 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
235 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
236 complete inline asm, since it needs to be combined with more magic
237 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000238*/
239
njnf76d27a2009-05-28 01:53:07 +0000240/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000241
sewardj520a03a2010-10-07 10:46:15 +0000242#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000243 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000244
245typedef
246 struct {
247 unsigned int nraddr; /* where's the code? */
248 }
249 OrigFn;
250
sewardj0ec07f32006-01-12 12:32:32 +0000251#define __SPECIAL_INSTRUCTION_PREAMBLE \
252 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000253 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000254
bart575ce8e2011-05-15 07:04:03 +0000255#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
256 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000257 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000258 __extension__ \
259 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000260 volatile unsigned int _zzq_result; \
261 _zzq_args[0] = (unsigned int)(_zzq_request); \
262 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
263 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
264 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
265 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000266 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000267 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
268 /* %EDX = client_request ( %EAX ) */ \
269 "xchgl %%ebx,%%ebx" \
270 : "=d" (_zzq_result) \
271 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
272 : "cc", "memory" \
273 ); \
bart575ce8e2011-05-15 07:04:03 +0000274 _zzq_result; \
275 })
sewardj2c48c7b2005-11-29 13:05:56 +0000276
sewardjc8858442006-01-20 15:17:20 +0000277#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
278 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
279 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000280 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
281 /* %EAX = guest_NRADDR */ \
282 "xchgl %%ecx,%%ecx" \
283 : "=a" (__addr) \
284 : \
285 : "cc", "memory" \
286 ); \
sewardjc8858442006-01-20 15:17:20 +0000287 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000288 }
sewardj0ec07f32006-01-12 12:32:32 +0000289
290#define VALGRIND_CALL_NOREDIR_EAX \
291 __SPECIAL_INSTRUCTION_PREAMBLE \
292 /* call-noredir *%EAX */ \
293 "xchgl %%edx,%%edx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000294
295#define VALGRIND_VEX_INJECT_IR() \
296 do { \
297 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
298 "xchgl %%edi,%%edi\n\t" \
299 : : : "cc", "memory" \
300 ); \
301 } while (0)
302
sewardj60227842010-10-07 10:00:56 +0000303#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000304
305/* ------------------------- x86-Win32 ------------------------- */
306
307#if defined(PLAT_x86_win32) && !defined(__GNUC__)
308
309typedef
310 struct {
311 unsigned int nraddr; /* where's the code? */
312 }
313 OrigFn;
314
315#if defined(_MSC_VER)
316
317#define __SPECIAL_INSTRUCTION_PREAMBLE \
318 __asm rol edi, 3 __asm rol edi, 13 \
319 __asm rol edi, 29 __asm rol edi, 19
320
bart575ce8e2011-05-15 07:04:03 +0000321#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
322 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000323 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000324 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
325 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
326 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
327 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
328
329static __inline uintptr_t
330valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
331 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
332 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
333 uintptr_t _zzq_arg5)
334{
335 volatile uintptr_t _zzq_args[6];
336 volatile unsigned int _zzq_result;
337 _zzq_args[0] = (uintptr_t)(_zzq_request);
338 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
339 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
340 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
341 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
342 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
343 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
344 __SPECIAL_INSTRUCTION_PREAMBLE
345 /* %EDX = client_request ( %EAX ) */
346 __asm xchg ebx,ebx
347 __asm mov _zzq_result, edx
348 }
349 return _zzq_result;
350}
bart7f489812010-08-27 10:05:27 +0000351
352#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
353 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
354 volatile unsigned int __addr; \
355 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
356 /* %EAX = guest_NRADDR */ \
357 __asm xchg ecx,ecx \
358 __asm mov __addr, eax \
359 } \
360 _zzq_orig->nraddr = __addr; \
361 }
362
363#define VALGRIND_CALL_NOREDIR_EAX ERROR
364
florianbb913cd2012-08-28 16:50:39 +0000365#define VALGRIND_VEX_INJECT_IR() \
366 do { \
367 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
368 __asm xchg edi,edi \
369 } \
370 } while (0)
371
bart7f489812010-08-27 10:05:27 +0000372#else
373#error Unsupported compiler.
374#endif
375
376#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000377
njnf76d27a2009-05-28 01:53:07 +0000378/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000379
njnf76d27a2009-05-28 01:53:07 +0000380#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000381
382typedef
383 struct {
384 unsigned long long int nraddr; /* where's the code? */
385 }
386 OrigFn;
387
sewardj0ec07f32006-01-12 12:32:32 +0000388#define __SPECIAL_INSTRUCTION_PREAMBLE \
389 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000390 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000391
bart575ce8e2011-05-15 07:04:03 +0000392#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
393 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000394 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000395 __extension__ \
396 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000397 volatile unsigned long long int _zzq_result; \
398 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
399 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
400 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
401 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
402 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000403 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000404 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
405 /* %RDX = client_request ( %RAX ) */ \
406 "xchgq %%rbx,%%rbx" \
407 : "=d" (_zzq_result) \
408 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
409 : "cc", "memory" \
410 ); \
bart575ce8e2011-05-15 07:04:03 +0000411 _zzq_result; \
412 })
sewardj0ec07f32006-01-12 12:32:32 +0000413
sewardjc8858442006-01-20 15:17:20 +0000414#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
415 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
416 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000417 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
418 /* %RAX = guest_NRADDR */ \
419 "xchgq %%rcx,%%rcx" \
420 : "=a" (__addr) \
421 : \
422 : "cc", "memory" \
423 ); \
sewardjc8858442006-01-20 15:17:20 +0000424 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000425 }
426
427#define VALGRIND_CALL_NOREDIR_RAX \
428 __SPECIAL_INSTRUCTION_PREAMBLE \
429 /* call-noredir *%RAX */ \
430 "xchgq %%rdx,%%rdx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000431
432#define VALGRIND_VEX_INJECT_IR() \
433 do { \
434 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
435 "xchgq %%rdi,%%rdi\n\t" \
436 : : : "cc", "memory" \
437 ); \
438 } while (0)
439
njnf76d27a2009-05-28 01:53:07 +0000440#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000441
sewardjf5c1a7f2006-10-17 01:32:48 +0000442/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000443
sewardjf5c1a7f2006-10-17 01:32:48 +0000444#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000445
446typedef
447 struct {
sewardjc8858442006-01-20 15:17:20 +0000448 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000449 }
450 OrigFn;
451
sewardj0ec07f32006-01-12 12:32:32 +0000452#define __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj4decb262014-02-10 12:26:12 +0000453 "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \
454 "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000455
bart575ce8e2011-05-15 07:04:03 +0000456#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
457 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000458 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000459 \
bart575ce8e2011-05-15 07:04:03 +0000460 __extension__ \
461 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000462 unsigned int _zzq_result; \
463 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000464 _zzq_args[0] = (unsigned int)(_zzq_request); \
465 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
466 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
467 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
468 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000469 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000470 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000471 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
472 "mr 4,%2\n\t" /*ptr*/ \
473 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000474 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000475 "or 1,1,1\n\t" \
476 "mr %0,3" /*result*/ \
477 : "=b" (_zzq_result) \
478 : "b" (_zzq_default), "b" (_zzq_ptr) \
479 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000480 _zzq_result; \
481 })
sewardj0ec07f32006-01-12 12:32:32 +0000482
sewardjd68ac3e2006-01-20 14:31:57 +0000483#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
484 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000485 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000486 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
487 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000488 "or 2,2,2\n\t" \
489 "mr %0,3" \
490 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000491 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000492 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000493 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000494 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000495 }
496
497#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
498 __SPECIAL_INSTRUCTION_PREAMBLE \
499 /* branch-and-link-to-noredir *%R11 */ \
500 "or 3,3,3\n\t"
florian4d261bb2012-08-29 14:59:13 +0000501
502#define VALGRIND_VEX_INJECT_IR() \
503 do { \
504 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
505 "or 5,5,5\n\t" \
506 ); \
507 } while (0)
508
sewardjf5c1a7f2006-10-17 01:32:48 +0000509#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000510
sewardjf5c1a7f2006-10-17 01:32:48 +0000511/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000512
sewardjf5c1a7f2006-10-17 01:32:48 +0000513#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000514
515typedef
516 struct {
517 unsigned long long int nraddr; /* where's the code? */
518 unsigned long long int r2; /* what tocptr do we need? */
519 }
520 OrigFn;
521
sewardj1a85f4f2006-01-12 21:15:35 +0000522#define __SPECIAL_INSTRUCTION_PREAMBLE \
523 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
524 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
525
bart575ce8e2011-05-15 07:04:03 +0000526#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
527 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000528 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000529 \
bart575ce8e2011-05-15 07:04:03 +0000530 __extension__ \
531 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000532 unsigned long long int _zzq_result; \
533 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000534 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
535 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
536 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
537 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
538 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000539 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000540 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000541 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
542 "mr 4,%2\n\t" /*ptr*/ \
543 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000544 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000545 "or 1,1,1\n\t" \
546 "mr %0,3" /*result*/ \
547 : "=b" (_zzq_result) \
548 : "b" (_zzq_default), "b" (_zzq_ptr) \
549 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000550 _zzq_result; \
551 })
sewardj1a85f4f2006-01-12 21:15:35 +0000552
sewardjd68ac3e2006-01-20 14:31:57 +0000553#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
554 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000555 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000556 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
557 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000558 "or 2,2,2\n\t" \
559 "mr %0,3" \
560 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000561 : \
sewardj8258a3a2011-10-05 07:39:07 +0000562 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000563 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000564 _zzq_orig->nraddr = __addr; \
565 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
566 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000567 "or 4,4,4\n\t" \
568 "mr %0,3" \
569 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000570 : \
sewardj8258a3a2011-10-05 07:39:07 +0000571 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000572 ); \
573 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000574 }
575
576#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
577 __SPECIAL_INSTRUCTION_PREAMBLE \
578 /* branch-and-link-to-noredir *%R11 */ \
579 "or 3,3,3\n\t"
580
florianbb913cd2012-08-28 16:50:39 +0000581#define VALGRIND_VEX_INJECT_IR() \
582 do { \
583 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
584 "or 5,5,5\n\t" \
585 ); \
586 } while (0)
587
sewardjf5c1a7f2006-10-17 01:32:48 +0000588#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000589
sewardj59570ff2010-01-01 11:59:33 +0000590/* ------------------------- arm-linux ------------------------- */
591
592#if defined(PLAT_arm_linux)
593
594typedef
595 struct {
596 unsigned int nraddr; /* where's the code? */
597 }
598 OrigFn;
599
600#define __SPECIAL_INSTRUCTION_PREAMBLE \
601 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
602 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
603
bart575ce8e2011-05-15 07:04:03 +0000604#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
605 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000606 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
607 \
bart575ce8e2011-05-15 07:04:03 +0000608 __extension__ \
609 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000610 volatile unsigned int _zzq_result; \
611 _zzq_args[0] = (unsigned int)(_zzq_request); \
612 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
613 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
614 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
615 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
616 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
617 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
618 "mov r4, %2\n\t" /*ptr*/ \
619 __SPECIAL_INSTRUCTION_PREAMBLE \
620 /* R3 = client_request ( R4 ) */ \
621 "orr r10, r10, r10\n\t" \
622 "mov %0, r3" /*result*/ \
623 : "=r" (_zzq_result) \
624 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
625 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000626 _zzq_result; \
627 })
sewardj59570ff2010-01-01 11:59:33 +0000628
629#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
630 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
631 unsigned int __addr; \
632 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
633 /* R3 = guest_NRADDR */ \
634 "orr r11, r11, r11\n\t" \
635 "mov %0, r3" \
636 : "=r" (__addr) \
637 : \
638 : "cc", "memory", "r3" \
639 ); \
640 _zzq_orig->nraddr = __addr; \
641 }
642
643#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
644 __SPECIAL_INSTRUCTION_PREAMBLE \
645 /* branch-and-link-to-noredir *%R4 */ \
646 "orr r12, r12, r12\n\t"
647
florianbb913cd2012-08-28 16:50:39 +0000648#define VALGRIND_VEX_INJECT_IR() \
649 do { \
650 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
sewardjc379fec2012-09-03 21:51:02 +0000651 "orr r9, r9, r9\n\t" \
florianbb913cd2012-08-28 16:50:39 +0000652 : : : "cc", "memory" \
653 ); \
654 } while (0)
655
sewardj59570ff2010-01-01 11:59:33 +0000656#endif /* PLAT_arm_linux */
657
sewardjf0c12502014-01-12 12:54:00 +0000658/* ------------------------ arm64-linux ------------------------- */
659
660#if defined(PLAT_arm64_linux)
661
662typedef
663 struct {
664 unsigned long long int nraddr; /* where's the code? */
665 }
666 OrigFn;
667
668#define __SPECIAL_INSTRUCTION_PREAMBLE \
669 "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
670 "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
671
672#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
673 _zzq_default, _zzq_request, \
674 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
675 \
676 __extension__ \
677 ({volatile unsigned long long int _zzq_args[6]; \
678 volatile unsigned long long int _zzq_result; \
679 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
680 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
681 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
682 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
683 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
684 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
685 __asm__ volatile("mov x3, %1\n\t" /*default*/ \
686 "mov x4, %2\n\t" /*ptr*/ \
687 __SPECIAL_INSTRUCTION_PREAMBLE \
688 /* X3 = client_request ( X4 ) */ \
689 "orr x10, x10, x10\n\t" \
690 "mov %0, x3" /*result*/ \
691 : "=r" (_zzq_result) \
692 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
693 : "cc","memory", "x3", "x4"); \
694 _zzq_result; \
695 })
696
697#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
698 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
699 unsigned long long int __addr; \
700 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
701 /* X3 = guest_NRADDR */ \
702 "orr x11, x11, x11\n\t" \
703 "mov %0, x3" \
704 : "=r" (__addr) \
705 : \
706 : "cc", "memory", "x3" \
707 ); \
708 _zzq_orig->nraddr = __addr; \
709 }
710
711#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
712 __SPECIAL_INSTRUCTION_PREAMBLE \
713 /* branch-and-link-to-noredir X8 */ \
714 "orr x12, x12, x12\n\t"
715
716#define VALGRIND_VEX_INJECT_IR() \
717 do { \
718 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
719 "orr x9, x9, x9\n\t" \
720 : : : "cc", "memory" \
721 ); \
722 } while (0)
723
724#endif /* PLAT_arm64_linux */
725
sewardjb5b87402011-03-07 16:05:35 +0000726/* ------------------------ s390x-linux ------------------------ */
727
728#if defined(PLAT_s390x_linux)
729
730typedef
731 struct {
732 unsigned long long int nraddr; /* where's the code? */
733 }
734 OrigFn;
735
736/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
737 * code. This detection is implemented in platform specific toIR.c
738 * (e.g. VEX/priv/guest_s390_decoder.c).
739 */
740#define __SPECIAL_INSTRUCTION_PREAMBLE \
741 "lr 15,15\n\t" \
742 "lr 1,1\n\t" \
743 "lr 2,2\n\t" \
744 "lr 3,3\n\t"
745
746#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
747#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
748#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
florianbb913cd2012-08-28 16:50:39 +0000749#define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
sewardjb5b87402011-03-07 16:05:35 +0000750
bart575ce8e2011-05-15 07:04:03 +0000751#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
752 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000753 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000754 __extension__ \
755 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000756 volatile unsigned long long int _zzq_result; \
757 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
758 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
759 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
760 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
761 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
762 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
763 __asm__ volatile(/* r2 = args */ \
764 "lgr 2,%1\n\t" \
765 /* r3 = default */ \
766 "lgr 3,%2\n\t" \
767 __SPECIAL_INSTRUCTION_PREAMBLE \
768 __CLIENT_REQUEST_CODE \
769 /* results = r3 */ \
770 "lgr %0, 3\n\t" \
771 : "=d" (_zzq_result) \
772 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
773 : "cc", "2", "3", "memory" \
774 ); \
bart575ce8e2011-05-15 07:04:03 +0000775 _zzq_result; \
776 })
sewardjb5b87402011-03-07 16:05:35 +0000777
778#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
779 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
780 volatile unsigned long long int __addr; \
781 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
782 __GET_NR_CONTEXT_CODE \
783 "lgr %0, 3\n\t" \
784 : "=a" (__addr) \
785 : \
786 : "cc", "3", "memory" \
787 ); \
788 _zzq_orig->nraddr = __addr; \
789 }
790
791#define VALGRIND_CALL_NOREDIR_R1 \
792 __SPECIAL_INSTRUCTION_PREAMBLE \
793 __CALL_NO_REDIR_CODE
794
florianbb913cd2012-08-28 16:50:39 +0000795#define VALGRIND_VEX_INJECT_IR() \
796 do { \
797 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
798 __VEX_INJECT_IR_CODE); \
799 } while (0)
800
sewardjb5b87402011-03-07 16:05:35 +0000801#endif /* PLAT_s390x_linux */
802
sewardj5db15402012-06-07 09:13:21 +0000803/* ------------------------- mips32-linux ---------------- */
804
805#if defined(PLAT_mips32_linux)
806
807typedef
808 struct {
809 unsigned int nraddr; /* where's the code? */
810 }
811 OrigFn;
812
813/* .word 0x342
814 * .word 0x742
815 * .word 0xC2
816 * .word 0x4C2*/
817#define __SPECIAL_INSTRUCTION_PREAMBLE \
818 "srl $0, $0, 13\n\t" \
819 "srl $0, $0, 29\n\t" \
820 "srl $0, $0, 3\n\t" \
821 "srl $0, $0, 19\n\t"
822
823#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
824 _zzq_default, _zzq_request, \
825 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
826 __extension__ \
827 ({ volatile unsigned int _zzq_args[6]; \
828 volatile unsigned int _zzq_result; \
829 _zzq_args[0] = (unsigned int)(_zzq_request); \
830 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
831 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
832 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
833 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
834 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
835 __asm__ volatile("move $11, %1\n\t" /*default*/ \
836 "move $12, %2\n\t" /*ptr*/ \
837 __SPECIAL_INSTRUCTION_PREAMBLE \
838 /* T3 = client_request ( T4 ) */ \
839 "or $13, $13, $13\n\t" \
840 "move %0, $11\n\t" /*result*/ \
841 : "=r" (_zzq_result) \
842 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
petarj4df0bfc2013-02-27 23:17:33 +0000843 : "$11", "$12"); \
sewardj5db15402012-06-07 09:13:21 +0000844 _zzq_result; \
845 })
846
847#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
848 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
849 volatile unsigned int __addr; \
850 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
851 /* %t9 = guest_NRADDR */ \
852 "or $14, $14, $14\n\t" \
853 "move %0, $11" /*result*/ \
854 : "=r" (__addr) \
855 : \
petarj4df0bfc2013-02-27 23:17:33 +0000856 : "$11" \
sewardj5db15402012-06-07 09:13:21 +0000857 ); \
858 _zzq_orig->nraddr = __addr; \
859 }
860
861#define VALGRIND_CALL_NOREDIR_T9 \
862 __SPECIAL_INSTRUCTION_PREAMBLE \
863 /* call-noredir *%t9 */ \
florianbb913cd2012-08-28 16:50:39 +0000864 "or $15, $15, $15\n\t"
865
866#define VALGRIND_VEX_INJECT_IR() \
867 do { \
868 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
869 "or $11, $11, $11\n\t" \
870 ); \
871 } while (0)
872
873
sewardj5db15402012-06-07 09:13:21 +0000874#endif /* PLAT_mips32_linux */
875
petarj4df0bfc2013-02-27 23:17:33 +0000876/* ------------------------- mips64-linux ---------------- */
877
878#if defined(PLAT_mips64_linux)
879
880typedef
881 struct {
882 unsigned long long nraddr; /* where's the code? */
883 }
884 OrigFn;
885
886/* dsll $0,$0, 3
887 * dsll $0,$0, 13
888 * dsll $0,$0, 29
889 * dsll $0,$0, 19*/
890#define __SPECIAL_INSTRUCTION_PREAMBLE \
891 "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \
892 "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
893
894#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
895 _zzq_default, _zzq_request, \
896 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
897 __extension__ \
898 ({ volatile unsigned long long int _zzq_args[6]; \
899 volatile unsigned long long int _zzq_result; \
900 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
901 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
902 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
903 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
904 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
905 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
906 __asm__ volatile("move $11, %1\n\t" /*default*/ \
907 "move $12, %2\n\t" /*ptr*/ \
908 __SPECIAL_INSTRUCTION_PREAMBLE \
909 /* $11 = client_request ( $12 ) */ \
910 "or $13, $13, $13\n\t" \
911 "move %0, $11\n\t" /*result*/ \
912 : "=r" (_zzq_result) \
913 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
914 : "$11", "$12"); \
915 _zzq_result; \
916 })
917
918#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
919 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
920 volatile unsigned long long int __addr; \
921 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
922 /* $11 = guest_NRADDR */ \
923 "or $14, $14, $14\n\t" \
924 "move %0, $11" /*result*/ \
925 : "=r" (__addr) \
926 : \
927 : "$11"); \
928 _zzq_orig->nraddr = __addr; \
929 }
930
931#define VALGRIND_CALL_NOREDIR_T9 \
932 __SPECIAL_INSTRUCTION_PREAMBLE \
933 /* call-noredir $25 */ \
934 "or $15, $15, $15\n\t"
935
936#define VALGRIND_VEX_INJECT_IR() \
937 do { \
938 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
939 "or $11, $11, $11\n\t" \
940 ); \
941 } while (0)
942
943#endif /* PLAT_mips64_linux */
944
sewardjf5c1a7f2006-10-17 01:32:48 +0000945/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000946
sewardj37091fb2002-11-16 11:06:50 +0000947#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000948
nethercote69d9c462004-10-26 13:00:12 +0000949
njn30d76c62005-06-18 15:07:39 +0000950/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000951/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000952/* ugly. It's the least-worst tradeoff I can think of. */
953/* ------------------------------------------------------------------ */
954
955/* This section defines magic (a.k.a appalling-hack) macros for doing
956 guaranteed-no-redirection macros, so as to get from function
957 wrappers to the functions they are wrapping. The whole point is to
958 construct standard call sequences, but to do the call itself with a
959 special no-redirect call pseudo-instruction that the JIT
960 understands and handles specially. This section is long and
961 repetitious, and I can't see a way to make it shorter.
962
963 The naming scheme is as follows:
964
965 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
966
967 'W' stands for "word" and 'v' for "void". Hence there are
968 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
969 and for each, the possibility of returning a word-typed result, or
970 no result.
971*/
972
973/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +0000974 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
975 the default behaviour equivalance class tag "0000" into the name.
976 See pub_tool_redir.h for details -- normally you don't need to
977 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +0000978
njn5f5ef2a2009-05-11 08:01:09 +0000979/* Use an extra level of macroisation so as to ensure the soname/fnname
980 args are fully macro-expanded before pasting them together. */
981#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
982
sewardj0ec07f32006-01-12 12:32:32 +0000983#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000984 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000985
986#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000987 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000988
sewardjd68ac3e2006-01-20 14:31:57 +0000989/* Use this macro from within a wrapper function to collect the
990 context (address and possibly other info) of the original function.
991 Once you have that you can then use it in one of the CALL_FN_
992 macros. The type of the argument _lval is OrigFn. */
993#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000994
sewardj573f8bc2012-06-05 07:12:15 +0000995/* Also provide end-user facilities for function replacement, rather
996 than wrapping. A replacement function differs from a wrapper in
997 that it has no way to get hold of the original function being
998 called, and hence no way to call onwards to it. In a replacement
999 function, VALGRIND_GET_ORIG_FN always returns zero. */
1000
1001#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
1002 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1003
1004#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
1005 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1006
sewardj0ec07f32006-01-12 12:32:32 +00001007/* Derivatives of the main macros below, for calling functions
1008 returning void. */
1009
1010#define CALL_FN_v_v(fnptr) \
1011 do { volatile unsigned long _junk; \
1012 CALL_FN_W_v(_junk,fnptr); } while (0)
1013
1014#define CALL_FN_v_W(fnptr, arg1) \
1015 do { volatile unsigned long _junk; \
1016 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1017
1018#define CALL_FN_v_WW(fnptr, arg1,arg2) \
1019 do { volatile unsigned long _junk; \
1020 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1021
sewardj5ce4b152006-03-11 12:57:41 +00001022#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
1023 do { volatile unsigned long _junk; \
1024 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1025
njn2b5f0a92009-05-19 01:24:50 +00001026#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
1027 do { volatile unsigned long _junk; \
1028 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1029
1030#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
1031 do { volatile unsigned long _junk; \
1032 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1033
1034#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
1035 do { volatile unsigned long _junk; \
1036 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1037
1038#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
1039 do { volatile unsigned long _junk; \
1040 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1041
njnf76d27a2009-05-28 01:53:07 +00001042/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001043
njnf76d27a2009-05-28 01:53:07 +00001044#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001045
1046/* These regs are trashed by the hidden call. No need to mention eax
1047 as gcc can already see that, plus causes gcc to bomb. */
1048#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1049
tom4118e0f2012-08-02 09:23:45 +00001050/* Macros to save and align the stack before making a function
1051 call and restore it afterwards as gcc may not keep the stack
1052 pointer aligned if it doesn't realise calls are being made
1053 to other functions. */
1054
1055#define VALGRIND_ALIGN_STACK \
1056 "movl %%esp,%%edi\n\t" \
1057 "andl $0xfffffff0,%%esp\n\t"
1058#define VALGRIND_RESTORE_STACK \
1059 "movl %%edi,%%esp\n\t"
1060
sewardj0ec07f32006-01-12 12:32:32 +00001061/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1062 long) == 4. */
1063
sewardj66226cc2006-01-20 15:46:46 +00001064#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001065 do { \
sewardj66226cc2006-01-20 15:46:46 +00001066 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001067 volatile unsigned long _argvec[1]; \
1068 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001069 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001070 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001071 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001072 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1073 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001074 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001075 : /*out*/ "=a" (_res) \
1076 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001077 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001078 ); \
1079 lval = (__typeof__(lval)) _res; \
1080 } while (0)
1081
sewardj66226cc2006-01-20 15:46:46 +00001082#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001083 do { \
sewardj66226cc2006-01-20 15:46:46 +00001084 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001085 volatile unsigned long _argvec[2]; \
1086 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001087 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001088 _argvec[1] = (unsigned long)(arg1); \
1089 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001090 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001091 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001092 "pushl 4(%%eax)\n\t" \
1093 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1094 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001095 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001096 : /*out*/ "=a" (_res) \
1097 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001098 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001099 ); \
1100 lval = (__typeof__(lval)) _res; \
1101 } while (0)
1102
sewardj66226cc2006-01-20 15:46:46 +00001103#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001104 do { \
sewardj66226cc2006-01-20 15:46:46 +00001105 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001106 volatile unsigned long _argvec[3]; \
1107 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001108 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001109 _argvec[1] = (unsigned long)(arg1); \
1110 _argvec[2] = (unsigned long)(arg2); \
1111 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001112 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001113 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001114 "pushl 8(%%eax)\n\t" \
1115 "pushl 4(%%eax)\n\t" \
1116 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1117 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001118 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001119 : /*out*/ "=a" (_res) \
1120 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001121 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001122 ); \
1123 lval = (__typeof__(lval)) _res; \
1124 } while (0)
1125
sewardj9e8b07a2006-02-18 21:13:29 +00001126#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1127 do { \
1128 volatile OrigFn _orig = (orig); \
1129 volatile unsigned long _argvec[4]; \
1130 volatile unsigned long _res; \
1131 _argvec[0] = (unsigned long)_orig.nraddr; \
1132 _argvec[1] = (unsigned long)(arg1); \
1133 _argvec[2] = (unsigned long)(arg2); \
1134 _argvec[3] = (unsigned long)(arg3); \
1135 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001136 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001137 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +00001138 "pushl 12(%%eax)\n\t" \
1139 "pushl 8(%%eax)\n\t" \
1140 "pushl 4(%%eax)\n\t" \
1141 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1142 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001143 VALGRIND_RESTORE_STACK \
sewardj9e8b07a2006-02-18 21:13:29 +00001144 : /*out*/ "=a" (_res) \
1145 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj9e8b07a2006-02-18 21:13:29 +00001147 ); \
1148 lval = (__typeof__(lval)) _res; \
1149 } while (0)
1150
sewardj66226cc2006-01-20 15:46:46 +00001151#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +00001152 do { \
sewardj66226cc2006-01-20 15:46:46 +00001153 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001154 volatile unsigned long _argvec[5]; \
1155 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001156 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001157 _argvec[1] = (unsigned long)(arg1); \
1158 _argvec[2] = (unsigned long)(arg2); \
1159 _argvec[3] = (unsigned long)(arg3); \
1160 _argvec[4] = (unsigned long)(arg4); \
1161 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001162 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001163 "pushl 16(%%eax)\n\t" \
1164 "pushl 12(%%eax)\n\t" \
1165 "pushl 8(%%eax)\n\t" \
1166 "pushl 4(%%eax)\n\t" \
1167 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1168 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001169 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001170 : /*out*/ "=a" (_res) \
1171 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001172 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001173 ); \
1174 lval = (__typeof__(lval)) _res; \
1175 } while (0)
1176
sewardj66226cc2006-01-20 15:46:46 +00001177#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +00001178 do { \
sewardj66226cc2006-01-20 15:46:46 +00001179 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001180 volatile unsigned long _argvec[6]; \
1181 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001182 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001183 _argvec[1] = (unsigned long)(arg1); \
1184 _argvec[2] = (unsigned long)(arg2); \
1185 _argvec[3] = (unsigned long)(arg3); \
1186 _argvec[4] = (unsigned long)(arg4); \
1187 _argvec[5] = (unsigned long)(arg5); \
1188 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001189 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001190 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001191 "pushl 20(%%eax)\n\t" \
1192 "pushl 16(%%eax)\n\t" \
1193 "pushl 12(%%eax)\n\t" \
1194 "pushl 8(%%eax)\n\t" \
1195 "pushl 4(%%eax)\n\t" \
1196 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1197 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001198 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001199 : /*out*/ "=a" (_res) \
1200 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001201 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001202 ); \
1203 lval = (__typeof__(lval)) _res; \
1204 } while (0)
1205
sewardj66226cc2006-01-20 15:46:46 +00001206#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +00001207 do { \
sewardj66226cc2006-01-20 15:46:46 +00001208 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001209 volatile unsigned long _argvec[7]; \
1210 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001211 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001212 _argvec[1] = (unsigned long)(arg1); \
1213 _argvec[2] = (unsigned long)(arg2); \
1214 _argvec[3] = (unsigned long)(arg3); \
1215 _argvec[4] = (unsigned long)(arg4); \
1216 _argvec[5] = (unsigned long)(arg5); \
1217 _argvec[6] = (unsigned long)(arg6); \
1218 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001219 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001220 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001221 "pushl 24(%%eax)\n\t" \
1222 "pushl 20(%%eax)\n\t" \
1223 "pushl 16(%%eax)\n\t" \
1224 "pushl 12(%%eax)\n\t" \
1225 "pushl 8(%%eax)\n\t" \
1226 "pushl 4(%%eax)\n\t" \
1227 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1228 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001229 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001230 : /*out*/ "=a" (_res) \
1231 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001232 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001233 ); \
1234 lval = (__typeof__(lval)) _res; \
1235 } while (0)
1236
sewardj66226cc2006-01-20 15:46:46 +00001237#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1238 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +00001239 do { \
sewardj66226cc2006-01-20 15:46:46 +00001240 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001241 volatile unsigned long _argvec[8]; \
1242 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001243 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001244 _argvec[1] = (unsigned long)(arg1); \
1245 _argvec[2] = (unsigned long)(arg2); \
1246 _argvec[3] = (unsigned long)(arg3); \
1247 _argvec[4] = (unsigned long)(arg4); \
1248 _argvec[5] = (unsigned long)(arg5); \
1249 _argvec[6] = (unsigned long)(arg6); \
1250 _argvec[7] = (unsigned long)(arg7); \
1251 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001252 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001253 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001254 "pushl 28(%%eax)\n\t" \
1255 "pushl 24(%%eax)\n\t" \
1256 "pushl 20(%%eax)\n\t" \
1257 "pushl 16(%%eax)\n\t" \
1258 "pushl 12(%%eax)\n\t" \
1259 "pushl 8(%%eax)\n\t" \
1260 "pushl 4(%%eax)\n\t" \
1261 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1262 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001263 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001264 : /*out*/ "=a" (_res) \
1265 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001266 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001267 ); \
1268 lval = (__typeof__(lval)) _res; \
1269 } while (0)
1270
sewardj66226cc2006-01-20 15:46:46 +00001271#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1272 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +00001273 do { \
sewardj66226cc2006-01-20 15:46:46 +00001274 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001275 volatile unsigned long _argvec[9]; \
1276 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001277 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001278 _argvec[1] = (unsigned long)(arg1); \
1279 _argvec[2] = (unsigned long)(arg2); \
1280 _argvec[3] = (unsigned long)(arg3); \
1281 _argvec[4] = (unsigned long)(arg4); \
1282 _argvec[5] = (unsigned long)(arg5); \
1283 _argvec[6] = (unsigned long)(arg6); \
1284 _argvec[7] = (unsigned long)(arg7); \
1285 _argvec[8] = (unsigned long)(arg8); \
1286 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001287 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001288 "pushl 32(%%eax)\n\t" \
1289 "pushl 28(%%eax)\n\t" \
1290 "pushl 24(%%eax)\n\t" \
1291 "pushl 20(%%eax)\n\t" \
1292 "pushl 16(%%eax)\n\t" \
1293 "pushl 12(%%eax)\n\t" \
1294 "pushl 8(%%eax)\n\t" \
1295 "pushl 4(%%eax)\n\t" \
1296 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1297 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001298 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001299 : /*out*/ "=a" (_res) \
1300 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001301 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001302 ); \
1303 lval = (__typeof__(lval)) _res; \
1304 } while (0)
1305
sewardj45fa5b02006-03-09 19:06:23 +00001306#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1307 arg7,arg8,arg9) \
1308 do { \
1309 volatile OrigFn _orig = (orig); \
1310 volatile unsigned long _argvec[10]; \
1311 volatile unsigned long _res; \
1312 _argvec[0] = (unsigned long)_orig.nraddr; \
1313 _argvec[1] = (unsigned long)(arg1); \
1314 _argvec[2] = (unsigned long)(arg2); \
1315 _argvec[3] = (unsigned long)(arg3); \
1316 _argvec[4] = (unsigned long)(arg4); \
1317 _argvec[5] = (unsigned long)(arg5); \
1318 _argvec[6] = (unsigned long)(arg6); \
1319 _argvec[7] = (unsigned long)(arg7); \
1320 _argvec[8] = (unsigned long)(arg8); \
1321 _argvec[9] = (unsigned long)(arg9); \
1322 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001323 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001324 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001325 "pushl 36(%%eax)\n\t" \
1326 "pushl 32(%%eax)\n\t" \
1327 "pushl 28(%%eax)\n\t" \
1328 "pushl 24(%%eax)\n\t" \
1329 "pushl 20(%%eax)\n\t" \
1330 "pushl 16(%%eax)\n\t" \
1331 "pushl 12(%%eax)\n\t" \
1332 "pushl 8(%%eax)\n\t" \
1333 "pushl 4(%%eax)\n\t" \
1334 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1335 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001336 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001337 : /*out*/ "=a" (_res) \
1338 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001339 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001340 ); \
1341 lval = (__typeof__(lval)) _res; \
1342 } while (0)
1343
1344#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1345 arg7,arg8,arg9,arg10) \
1346 do { \
1347 volatile OrigFn _orig = (orig); \
1348 volatile unsigned long _argvec[11]; \
1349 volatile unsigned long _res; \
1350 _argvec[0] = (unsigned long)_orig.nraddr; \
1351 _argvec[1] = (unsigned long)(arg1); \
1352 _argvec[2] = (unsigned long)(arg2); \
1353 _argvec[3] = (unsigned long)(arg3); \
1354 _argvec[4] = (unsigned long)(arg4); \
1355 _argvec[5] = (unsigned long)(arg5); \
1356 _argvec[6] = (unsigned long)(arg6); \
1357 _argvec[7] = (unsigned long)(arg7); \
1358 _argvec[8] = (unsigned long)(arg8); \
1359 _argvec[9] = (unsigned long)(arg9); \
1360 _argvec[10] = (unsigned long)(arg10); \
1361 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001362 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001363 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001364 "pushl 40(%%eax)\n\t" \
1365 "pushl 36(%%eax)\n\t" \
1366 "pushl 32(%%eax)\n\t" \
1367 "pushl 28(%%eax)\n\t" \
1368 "pushl 24(%%eax)\n\t" \
1369 "pushl 20(%%eax)\n\t" \
1370 "pushl 16(%%eax)\n\t" \
1371 "pushl 12(%%eax)\n\t" \
1372 "pushl 8(%%eax)\n\t" \
1373 "pushl 4(%%eax)\n\t" \
1374 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1375 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001376 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001377 : /*out*/ "=a" (_res) \
1378 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001379 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001380 ); \
1381 lval = (__typeof__(lval)) _res; \
1382 } while (0)
1383
sewardj5ce4b152006-03-11 12:57:41 +00001384#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1385 arg6,arg7,arg8,arg9,arg10, \
1386 arg11) \
1387 do { \
1388 volatile OrigFn _orig = (orig); \
1389 volatile unsigned long _argvec[12]; \
1390 volatile unsigned long _res; \
1391 _argvec[0] = (unsigned long)_orig.nraddr; \
1392 _argvec[1] = (unsigned long)(arg1); \
1393 _argvec[2] = (unsigned long)(arg2); \
1394 _argvec[3] = (unsigned long)(arg3); \
1395 _argvec[4] = (unsigned long)(arg4); \
1396 _argvec[5] = (unsigned long)(arg5); \
1397 _argvec[6] = (unsigned long)(arg6); \
1398 _argvec[7] = (unsigned long)(arg7); \
1399 _argvec[8] = (unsigned long)(arg8); \
1400 _argvec[9] = (unsigned long)(arg9); \
1401 _argvec[10] = (unsigned long)(arg10); \
1402 _argvec[11] = (unsigned long)(arg11); \
1403 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001404 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001405 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001406 "pushl 44(%%eax)\n\t" \
1407 "pushl 40(%%eax)\n\t" \
1408 "pushl 36(%%eax)\n\t" \
1409 "pushl 32(%%eax)\n\t" \
1410 "pushl 28(%%eax)\n\t" \
1411 "pushl 24(%%eax)\n\t" \
1412 "pushl 20(%%eax)\n\t" \
1413 "pushl 16(%%eax)\n\t" \
1414 "pushl 12(%%eax)\n\t" \
1415 "pushl 8(%%eax)\n\t" \
1416 "pushl 4(%%eax)\n\t" \
1417 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1418 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001419 VALGRIND_RESTORE_STACK \
sewardj5ce4b152006-03-11 12:57:41 +00001420 : /*out*/ "=a" (_res) \
1421 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001422 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj5ce4b152006-03-11 12:57:41 +00001423 ); \
1424 lval = (__typeof__(lval)) _res; \
1425 } while (0)
1426
sewardj66226cc2006-01-20 15:46:46 +00001427#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1428 arg6,arg7,arg8,arg9,arg10, \
1429 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001430 do { \
sewardj66226cc2006-01-20 15:46:46 +00001431 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001432 volatile unsigned long _argvec[13]; \
1433 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001434 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001435 _argvec[1] = (unsigned long)(arg1); \
1436 _argvec[2] = (unsigned long)(arg2); \
1437 _argvec[3] = (unsigned long)(arg3); \
1438 _argvec[4] = (unsigned long)(arg4); \
1439 _argvec[5] = (unsigned long)(arg5); \
1440 _argvec[6] = (unsigned long)(arg6); \
1441 _argvec[7] = (unsigned long)(arg7); \
1442 _argvec[8] = (unsigned long)(arg8); \
1443 _argvec[9] = (unsigned long)(arg9); \
1444 _argvec[10] = (unsigned long)(arg10); \
1445 _argvec[11] = (unsigned long)(arg11); \
1446 _argvec[12] = (unsigned long)(arg12); \
1447 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001448 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001449 "pushl 48(%%eax)\n\t" \
1450 "pushl 44(%%eax)\n\t" \
1451 "pushl 40(%%eax)\n\t" \
1452 "pushl 36(%%eax)\n\t" \
1453 "pushl 32(%%eax)\n\t" \
1454 "pushl 28(%%eax)\n\t" \
1455 "pushl 24(%%eax)\n\t" \
1456 "pushl 20(%%eax)\n\t" \
1457 "pushl 16(%%eax)\n\t" \
1458 "pushl 12(%%eax)\n\t" \
1459 "pushl 8(%%eax)\n\t" \
1460 "pushl 4(%%eax)\n\t" \
1461 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1462 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001463 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001464 : /*out*/ "=a" (_res) \
1465 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001466 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001467 ); \
1468 lval = (__typeof__(lval)) _res; \
1469 } while (0)
1470
njnf76d27a2009-05-28 01:53:07 +00001471#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001472
njnf76d27a2009-05-28 01:53:07 +00001473/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001474
njnf76d27a2009-05-28 01:53:07 +00001475#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001476
1477/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1478
1479/* These regs are trashed by the hidden call. */
1480#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1481 "rdi", "r8", "r9", "r10", "r11"
1482
sewardjdfa55cf2010-10-06 22:07:06 +00001483/* This is all pretty complex. It's so as to make stack unwinding
1484 work reliably. See bug 243270. The basic problem is the sub and
1485 add of 128 of %rsp in all of the following macros. If gcc believes
1486 the CFA is in %rsp, then unwinding may fail, because what's at the
1487 CFA is not what gcc "expected" when it constructs the CFIs for the
1488 places where the macros are instantiated.
1489
1490 But we can't just add a CFI annotation to increase the CFA offset
1491 by 128, to match the sub of 128 from %rsp, because we don't know
1492 whether gcc has chosen %rsp as the CFA at that point, or whether it
1493 has chosen some other register (eg, %rbp). In the latter case,
1494 adding a CFI annotation to change the CFA offset is simply wrong.
1495
1496 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001497 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001498 CFI annotation to say what the register is. We choose %rbp for
1499 this (perhaps perversely), because:
1500
1501 (1) %rbp is already subject to unwinding. If a new register was
1502 chosen then the unwinder would have to unwind it in all stack
1503 traces, which is expensive, and
1504
1505 (2) %rbp is already subject to precise exception updates in the
1506 JIT. If a new register was chosen, we'd have to have precise
1507 exceptions for it too, which reduces performance of the
1508 generated code.
1509
1510 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001511 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001512 list of trashed registers at the end of the inline assembly
1513 fragments; gcc won't allow %rbp to appear in that list. Hence
1514 instead we need to stash %rbp in %r15 for the duration of the asm,
1515 and say that %r15 is trashed instead. gcc seems happy to go with
1516 that.
1517
1518 Oh .. and this all needs to be conditionalised so that it is
1519 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001520 that don't support __builtin_dwarf_cfa. Furthermore, since
1521 this header file is freestanding, it has to be independent of
1522 config.h, and so the following conditionalisation cannot depend on
1523 configure time checks.
1524
1525 Although it's not clear from
1526 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1527 this expression excludes Darwin.
1528 .cfi directives in Darwin assembly appear to be completely
1529 different and I haven't investigated how they work.
1530
1531 For even more entertainment value, note we have to use the
1532 completely undocumented __builtin_dwarf_cfa(), which appears to
1533 really compute the CFA, whereas __builtin_frame_address(0) claims
1534 to but actually doesn't. See
1535 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001536*/
sewardj8d1dc152010-10-08 17:43:26 +00001537#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001538# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001539 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001540# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001541 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001542 "movq %2, %%rbp\n\t" \
1543 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001544 ".cfi_def_cfa rbp, 0\n\t"
1545# define VALGRIND_CFI_EPILOGUE \
1546 "movq %%r15, %%rbp\n\t" \
1547 ".cfi_restore_state\n\t"
1548#else
1549# define __FRAME_POINTER
1550# define VALGRIND_CFI_PROLOGUE
1551# define VALGRIND_CFI_EPILOGUE
1552#endif
1553
tom4118e0f2012-08-02 09:23:45 +00001554/* Macros to save and align the stack before making a function
1555 call and restore it afterwards as gcc may not keep the stack
1556 pointer aligned if it doesn't realise calls are being made
1557 to other functions. */
1558
1559#define VALGRIND_ALIGN_STACK \
1560 "movq %%rsp,%%r14\n\t" \
1561 "andq $0xfffffffffffffff0,%%rsp\n\t"
1562#define VALGRIND_RESTORE_STACK \
1563 "movq %%r14,%%rsp\n\t"
sewardjdfa55cf2010-10-06 22:07:06 +00001564
sewardj0ec07f32006-01-12 12:32:32 +00001565/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1566 long) == 8. */
1567
sewardja07c2e12007-11-09 23:09:50 +00001568/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1569 macros. In order not to trash the stack redzone, we need to drop
1570 %rsp by 128 before the hidden call, and restore afterwards. The
1571 nastyness is that it is only by luck that the stack still appears
1572 to be unwindable during the hidden call - since then the behaviour
1573 of any routine using this macro does not match what the CFI data
1574 says. Sigh.
1575
1576 Why is this important? Imagine that a wrapper has a stack
1577 allocated local, and passes to the hidden call, a pointer to it.
1578 Because gcc does not know about the hidden call, it may allocate
1579 that local in the redzone. Unfortunately the hidden call may then
1580 trash it before it comes to use it. So we must step clear of the
1581 redzone, for the duration of the hidden call, to make it safe.
1582
1583 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001584 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001585 self describing (none of this CFI nonsense) so at least messing
1586 with the stack pointer doesn't give a danger of non-unwindable
1587 stack. */
1588
tom4118e0f2012-08-02 09:23:45 +00001589#define CALL_FN_W_v(lval, orig) \
1590 do { \
1591 volatile OrigFn _orig = (orig); \
1592 volatile unsigned long _argvec[1]; \
1593 volatile unsigned long _res; \
1594 _argvec[0] = (unsigned long)_orig.nraddr; \
1595 __asm__ volatile( \
1596 VALGRIND_CFI_PROLOGUE \
1597 VALGRIND_ALIGN_STACK \
1598 "subq $128,%%rsp\n\t" \
1599 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1600 VALGRIND_CALL_NOREDIR_RAX \
1601 VALGRIND_RESTORE_STACK \
1602 VALGRIND_CFI_EPILOGUE \
1603 : /*out*/ "=a" (_res) \
1604 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1605 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1606 ); \
1607 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001608 } while (0)
1609
tom4118e0f2012-08-02 09:23:45 +00001610#define CALL_FN_W_W(lval, orig, arg1) \
1611 do { \
1612 volatile OrigFn _orig = (orig); \
1613 volatile unsigned long _argvec[2]; \
1614 volatile unsigned long _res; \
1615 _argvec[0] = (unsigned long)_orig.nraddr; \
1616 _argvec[1] = (unsigned long)(arg1); \
1617 __asm__ volatile( \
1618 VALGRIND_CFI_PROLOGUE \
1619 VALGRIND_ALIGN_STACK \
1620 "subq $128,%%rsp\n\t" \
1621 "movq 8(%%rax), %%rdi\n\t" \
1622 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1623 VALGRIND_CALL_NOREDIR_RAX \
1624 VALGRIND_RESTORE_STACK \
1625 VALGRIND_CFI_EPILOGUE \
1626 : /*out*/ "=a" (_res) \
1627 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1628 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1629 ); \
1630 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001631 } while (0)
1632
tom4118e0f2012-08-02 09:23:45 +00001633#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1634 do { \
1635 volatile OrigFn _orig = (orig); \
1636 volatile unsigned long _argvec[3]; \
1637 volatile unsigned long _res; \
1638 _argvec[0] = (unsigned long)_orig.nraddr; \
1639 _argvec[1] = (unsigned long)(arg1); \
1640 _argvec[2] = (unsigned long)(arg2); \
1641 __asm__ volatile( \
1642 VALGRIND_CFI_PROLOGUE \
1643 VALGRIND_ALIGN_STACK \
1644 "subq $128,%%rsp\n\t" \
1645 "movq 16(%%rax), %%rsi\n\t" \
1646 "movq 8(%%rax), %%rdi\n\t" \
1647 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1648 VALGRIND_CALL_NOREDIR_RAX \
1649 VALGRIND_RESTORE_STACK \
1650 VALGRIND_CFI_EPILOGUE \
1651 : /*out*/ "=a" (_res) \
1652 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1653 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1654 ); \
1655 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001656 } while (0)
1657
tom4118e0f2012-08-02 09:23:45 +00001658#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1659 do { \
1660 volatile OrigFn _orig = (orig); \
1661 volatile unsigned long _argvec[4]; \
1662 volatile unsigned long _res; \
1663 _argvec[0] = (unsigned long)_orig.nraddr; \
1664 _argvec[1] = (unsigned long)(arg1); \
1665 _argvec[2] = (unsigned long)(arg2); \
1666 _argvec[3] = (unsigned long)(arg3); \
1667 __asm__ volatile( \
1668 VALGRIND_CFI_PROLOGUE \
1669 VALGRIND_ALIGN_STACK \
1670 "subq $128,%%rsp\n\t" \
1671 "movq 24(%%rax), %%rdx\n\t" \
1672 "movq 16(%%rax), %%rsi\n\t" \
1673 "movq 8(%%rax), %%rdi\n\t" \
1674 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1675 VALGRIND_CALL_NOREDIR_RAX \
1676 VALGRIND_RESTORE_STACK \
1677 VALGRIND_CFI_EPILOGUE \
1678 : /*out*/ "=a" (_res) \
1679 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1680 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1681 ); \
1682 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001683 } while (0)
1684
tom4118e0f2012-08-02 09:23:45 +00001685#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1686 do { \
1687 volatile OrigFn _orig = (orig); \
1688 volatile unsigned long _argvec[5]; \
1689 volatile unsigned long _res; \
1690 _argvec[0] = (unsigned long)_orig.nraddr; \
1691 _argvec[1] = (unsigned long)(arg1); \
1692 _argvec[2] = (unsigned long)(arg2); \
1693 _argvec[3] = (unsigned long)(arg3); \
1694 _argvec[4] = (unsigned long)(arg4); \
1695 __asm__ volatile( \
1696 VALGRIND_CFI_PROLOGUE \
1697 VALGRIND_ALIGN_STACK \
1698 "subq $128,%%rsp\n\t" \
1699 "movq 32(%%rax), %%rcx\n\t" \
1700 "movq 24(%%rax), %%rdx\n\t" \
1701 "movq 16(%%rax), %%rsi\n\t" \
1702 "movq 8(%%rax), %%rdi\n\t" \
1703 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1704 VALGRIND_CALL_NOREDIR_RAX \
1705 VALGRIND_RESTORE_STACK \
1706 VALGRIND_CFI_EPILOGUE \
1707 : /*out*/ "=a" (_res) \
1708 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1710 ); \
1711 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001712 } while (0)
1713
tom4118e0f2012-08-02 09:23:45 +00001714#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1715 do { \
1716 volatile OrigFn _orig = (orig); \
1717 volatile unsigned long _argvec[6]; \
1718 volatile unsigned long _res; \
1719 _argvec[0] = (unsigned long)_orig.nraddr; \
1720 _argvec[1] = (unsigned long)(arg1); \
1721 _argvec[2] = (unsigned long)(arg2); \
1722 _argvec[3] = (unsigned long)(arg3); \
1723 _argvec[4] = (unsigned long)(arg4); \
1724 _argvec[5] = (unsigned long)(arg5); \
1725 __asm__ volatile( \
1726 VALGRIND_CFI_PROLOGUE \
1727 VALGRIND_ALIGN_STACK \
1728 "subq $128,%%rsp\n\t" \
1729 "movq 40(%%rax), %%r8\n\t" \
1730 "movq 32(%%rax), %%rcx\n\t" \
1731 "movq 24(%%rax), %%rdx\n\t" \
1732 "movq 16(%%rax), %%rsi\n\t" \
1733 "movq 8(%%rax), %%rdi\n\t" \
1734 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1735 VALGRIND_CALL_NOREDIR_RAX \
1736 VALGRIND_RESTORE_STACK \
1737 VALGRIND_CFI_EPILOGUE \
1738 : /*out*/ "=a" (_res) \
1739 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1740 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1741 ); \
1742 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001743 } while (0)
1744
tom4118e0f2012-08-02 09:23:45 +00001745#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1746 do { \
1747 volatile OrigFn _orig = (orig); \
1748 volatile unsigned long _argvec[7]; \
1749 volatile unsigned long _res; \
1750 _argvec[0] = (unsigned long)_orig.nraddr; \
1751 _argvec[1] = (unsigned long)(arg1); \
1752 _argvec[2] = (unsigned long)(arg2); \
1753 _argvec[3] = (unsigned long)(arg3); \
1754 _argvec[4] = (unsigned long)(arg4); \
1755 _argvec[5] = (unsigned long)(arg5); \
1756 _argvec[6] = (unsigned long)(arg6); \
1757 __asm__ volatile( \
1758 VALGRIND_CFI_PROLOGUE \
1759 VALGRIND_ALIGN_STACK \
1760 "subq $128,%%rsp\n\t" \
1761 "movq 48(%%rax), %%r9\n\t" \
1762 "movq 40(%%rax), %%r8\n\t" \
1763 "movq 32(%%rax), %%rcx\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_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1779 arg7) \
1780 do { \
1781 volatile OrigFn _orig = (orig); \
1782 volatile unsigned long _argvec[8]; \
1783 volatile unsigned long _res; \
1784 _argvec[0] = (unsigned long)_orig.nraddr; \
1785 _argvec[1] = (unsigned long)(arg1); \
1786 _argvec[2] = (unsigned long)(arg2); \
1787 _argvec[3] = (unsigned long)(arg3); \
1788 _argvec[4] = (unsigned long)(arg4); \
1789 _argvec[5] = (unsigned long)(arg5); \
1790 _argvec[6] = (unsigned long)(arg6); \
1791 _argvec[7] = (unsigned long)(arg7); \
1792 __asm__ volatile( \
1793 VALGRIND_CFI_PROLOGUE \
1794 VALGRIND_ALIGN_STACK \
1795 "subq $136,%%rsp\n\t" \
1796 "pushq 56(%%rax)\n\t" \
1797 "movq 48(%%rax), %%r9\n\t" \
1798 "movq 40(%%rax), %%r8\n\t" \
1799 "movq 32(%%rax), %%rcx\n\t" \
1800 "movq 24(%%rax), %%rdx\n\t" \
1801 "movq 16(%%rax), %%rsi\n\t" \
1802 "movq 8(%%rax), %%rdi\n\t" \
1803 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1804 VALGRIND_CALL_NOREDIR_RAX \
1805 VALGRIND_RESTORE_STACK \
1806 VALGRIND_CFI_EPILOGUE \
1807 : /*out*/ "=a" (_res) \
1808 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1809 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1810 ); \
1811 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001812 } while (0)
1813
tom4118e0f2012-08-02 09:23:45 +00001814#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1815 arg7,arg8) \
1816 do { \
1817 volatile OrigFn _orig = (orig); \
1818 volatile unsigned long _argvec[9]; \
1819 volatile unsigned long _res; \
1820 _argvec[0] = (unsigned long)_orig.nraddr; \
1821 _argvec[1] = (unsigned long)(arg1); \
1822 _argvec[2] = (unsigned long)(arg2); \
1823 _argvec[3] = (unsigned long)(arg3); \
1824 _argvec[4] = (unsigned long)(arg4); \
1825 _argvec[5] = (unsigned long)(arg5); \
1826 _argvec[6] = (unsigned long)(arg6); \
1827 _argvec[7] = (unsigned long)(arg7); \
1828 _argvec[8] = (unsigned long)(arg8); \
1829 __asm__ volatile( \
1830 VALGRIND_CFI_PROLOGUE \
1831 VALGRIND_ALIGN_STACK \
1832 "subq $128,%%rsp\n\t" \
1833 "pushq 64(%%rax)\n\t" \
1834 "pushq 56(%%rax)\n\t" \
1835 "movq 48(%%rax), %%r9\n\t" \
1836 "movq 40(%%rax), %%r8\n\t" \
1837 "movq 32(%%rax), %%rcx\n\t" \
1838 "movq 24(%%rax), %%rdx\n\t" \
1839 "movq 16(%%rax), %%rsi\n\t" \
1840 "movq 8(%%rax), %%rdi\n\t" \
1841 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1842 VALGRIND_CALL_NOREDIR_RAX \
1843 VALGRIND_RESTORE_STACK \
1844 VALGRIND_CFI_EPILOGUE \
1845 : /*out*/ "=a" (_res) \
1846 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1848 ); \
1849 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001850 } while (0)
1851
tom4118e0f2012-08-02 09:23:45 +00001852#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1853 arg7,arg8,arg9) \
1854 do { \
1855 volatile OrigFn _orig = (orig); \
1856 volatile unsigned long _argvec[10]; \
1857 volatile unsigned long _res; \
1858 _argvec[0] = (unsigned long)_orig.nraddr; \
1859 _argvec[1] = (unsigned long)(arg1); \
1860 _argvec[2] = (unsigned long)(arg2); \
1861 _argvec[3] = (unsigned long)(arg3); \
1862 _argvec[4] = (unsigned long)(arg4); \
1863 _argvec[5] = (unsigned long)(arg5); \
1864 _argvec[6] = (unsigned long)(arg6); \
1865 _argvec[7] = (unsigned long)(arg7); \
1866 _argvec[8] = (unsigned long)(arg8); \
1867 _argvec[9] = (unsigned long)(arg9); \
1868 __asm__ volatile( \
1869 VALGRIND_CFI_PROLOGUE \
1870 VALGRIND_ALIGN_STACK \
1871 "subq $136,%%rsp\n\t" \
1872 "pushq 72(%%rax)\n\t" \
1873 "pushq 64(%%rax)\n\t" \
1874 "pushq 56(%%rax)\n\t" \
1875 "movq 48(%%rax), %%r9\n\t" \
1876 "movq 40(%%rax), %%r8\n\t" \
1877 "movq 32(%%rax), %%rcx\n\t" \
1878 "movq 24(%%rax), %%rdx\n\t" \
1879 "movq 16(%%rax), %%rsi\n\t" \
1880 "movq 8(%%rax), %%rdi\n\t" \
1881 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1882 VALGRIND_CALL_NOREDIR_RAX \
1883 VALGRIND_RESTORE_STACK \
1884 VALGRIND_CFI_EPILOGUE \
1885 : /*out*/ "=a" (_res) \
1886 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1887 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1888 ); \
1889 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001890 } while (0)
1891
tom4118e0f2012-08-02 09:23:45 +00001892#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1893 arg7,arg8,arg9,arg10) \
1894 do { \
1895 volatile OrigFn _orig = (orig); \
1896 volatile unsigned long _argvec[11]; \
1897 volatile unsigned long _res; \
1898 _argvec[0] = (unsigned long)_orig.nraddr; \
1899 _argvec[1] = (unsigned long)(arg1); \
1900 _argvec[2] = (unsigned long)(arg2); \
1901 _argvec[3] = (unsigned long)(arg3); \
1902 _argvec[4] = (unsigned long)(arg4); \
1903 _argvec[5] = (unsigned long)(arg5); \
1904 _argvec[6] = (unsigned long)(arg6); \
1905 _argvec[7] = (unsigned long)(arg7); \
1906 _argvec[8] = (unsigned long)(arg8); \
1907 _argvec[9] = (unsigned long)(arg9); \
1908 _argvec[10] = (unsigned long)(arg10); \
1909 __asm__ volatile( \
1910 VALGRIND_CFI_PROLOGUE \
1911 VALGRIND_ALIGN_STACK \
1912 "subq $128,%%rsp\n\t" \
1913 "pushq 80(%%rax)\n\t" \
1914 "pushq 72(%%rax)\n\t" \
1915 "pushq 64(%%rax)\n\t" \
1916 "pushq 56(%%rax)\n\t" \
1917 "movq 48(%%rax), %%r9\n\t" \
1918 "movq 40(%%rax), %%r8\n\t" \
1919 "movq 32(%%rax), %%rcx\n\t" \
1920 "movq 24(%%rax), %%rdx\n\t" \
1921 "movq 16(%%rax), %%rsi\n\t" \
1922 "movq 8(%%rax), %%rdi\n\t" \
1923 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1924 VALGRIND_CALL_NOREDIR_RAX \
1925 VALGRIND_RESTORE_STACK \
1926 VALGRIND_CFI_EPILOGUE \
1927 : /*out*/ "=a" (_res) \
1928 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1929 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1930 ); \
1931 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001932 } while (0)
1933
tom4118e0f2012-08-02 09:23:45 +00001934#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1935 arg7,arg8,arg9,arg10,arg11) \
1936 do { \
1937 volatile OrigFn _orig = (orig); \
1938 volatile unsigned long _argvec[12]; \
1939 volatile unsigned long _res; \
1940 _argvec[0] = (unsigned long)_orig.nraddr; \
1941 _argvec[1] = (unsigned long)(arg1); \
1942 _argvec[2] = (unsigned long)(arg2); \
1943 _argvec[3] = (unsigned long)(arg3); \
1944 _argvec[4] = (unsigned long)(arg4); \
1945 _argvec[5] = (unsigned long)(arg5); \
1946 _argvec[6] = (unsigned long)(arg6); \
1947 _argvec[7] = (unsigned long)(arg7); \
1948 _argvec[8] = (unsigned long)(arg8); \
1949 _argvec[9] = (unsigned long)(arg9); \
1950 _argvec[10] = (unsigned long)(arg10); \
1951 _argvec[11] = (unsigned long)(arg11); \
1952 __asm__ volatile( \
1953 VALGRIND_CFI_PROLOGUE \
1954 VALGRIND_ALIGN_STACK \
1955 "subq $136,%%rsp\n\t" \
1956 "pushq 88(%%rax)\n\t" \
1957 "pushq 80(%%rax)\n\t" \
1958 "pushq 72(%%rax)\n\t" \
1959 "pushq 64(%%rax)\n\t" \
1960 "pushq 56(%%rax)\n\t" \
1961 "movq 48(%%rax), %%r9\n\t" \
1962 "movq 40(%%rax), %%r8\n\t" \
1963 "movq 32(%%rax), %%rcx\n\t" \
1964 "movq 24(%%rax), %%rdx\n\t" \
1965 "movq 16(%%rax), %%rsi\n\t" \
1966 "movq 8(%%rax), %%rdi\n\t" \
1967 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1968 VALGRIND_CALL_NOREDIR_RAX \
1969 VALGRIND_RESTORE_STACK \
1970 VALGRIND_CFI_EPILOGUE \
1971 : /*out*/ "=a" (_res) \
1972 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1973 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1974 ); \
1975 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001976 } while (0)
1977
tom4118e0f2012-08-02 09:23:45 +00001978#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1979 arg7,arg8,arg9,arg10,arg11,arg12) \
1980 do { \
1981 volatile OrigFn _orig = (orig); \
1982 volatile unsigned long _argvec[13]; \
1983 volatile unsigned long _res; \
1984 _argvec[0] = (unsigned long)_orig.nraddr; \
1985 _argvec[1] = (unsigned long)(arg1); \
1986 _argvec[2] = (unsigned long)(arg2); \
1987 _argvec[3] = (unsigned long)(arg3); \
1988 _argvec[4] = (unsigned long)(arg4); \
1989 _argvec[5] = (unsigned long)(arg5); \
1990 _argvec[6] = (unsigned long)(arg6); \
1991 _argvec[7] = (unsigned long)(arg7); \
1992 _argvec[8] = (unsigned long)(arg8); \
1993 _argvec[9] = (unsigned long)(arg9); \
1994 _argvec[10] = (unsigned long)(arg10); \
1995 _argvec[11] = (unsigned long)(arg11); \
1996 _argvec[12] = (unsigned long)(arg12); \
1997 __asm__ volatile( \
1998 VALGRIND_CFI_PROLOGUE \
1999 VALGRIND_ALIGN_STACK \
2000 "subq $128,%%rsp\n\t" \
2001 "pushq 96(%%rax)\n\t" \
2002 "pushq 88(%%rax)\n\t" \
2003 "pushq 80(%%rax)\n\t" \
2004 "pushq 72(%%rax)\n\t" \
2005 "pushq 64(%%rax)\n\t" \
2006 "pushq 56(%%rax)\n\t" \
2007 "movq 48(%%rax), %%r9\n\t" \
2008 "movq 40(%%rax), %%r8\n\t" \
2009 "movq 32(%%rax), %%rcx\n\t" \
2010 "movq 24(%%rax), %%rdx\n\t" \
2011 "movq 16(%%rax), %%rsi\n\t" \
2012 "movq 8(%%rax), %%rdi\n\t" \
2013 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2014 VALGRIND_CALL_NOREDIR_RAX \
2015 VALGRIND_RESTORE_STACK \
2016 VALGRIND_CFI_EPILOGUE \
2017 : /*out*/ "=a" (_res) \
2018 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2019 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2020 ); \
2021 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002022 } while (0)
2023
njnf76d27a2009-05-28 01:53:07 +00002024#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00002025
sewardjf5c1a7f2006-10-17 01:32:48 +00002026/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002027
sewardjf5c1a7f2006-10-17 01:32:48 +00002028#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00002029
sewardjead61df2006-03-12 13:39:15 +00002030/* This is useful for finding out about the on-stack stuff:
2031
2032 extern int f9 ( int,int,int,int,int,int,int,int,int );
2033 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2034 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2035 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2036
2037 int g9 ( void ) {
2038 return f9(11,22,33,44,55,66,77,88,99);
2039 }
2040 int g10 ( void ) {
2041 return f10(11,22,33,44,55,66,77,88,99,110);
2042 }
2043 int g11 ( void ) {
2044 return f11(11,22,33,44,55,66,77,88,99,110,121);
2045 }
2046 int g12 ( void ) {
2047 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2048 }
2049*/
2050
sewardj0ec07f32006-01-12 12:32:32 +00002051/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2052
2053/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00002054#define __CALLER_SAVED_REGS \
2055 "lr", "ctr", "xer", \
2056 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2057 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2058 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00002059
tom4118e0f2012-08-02 09:23:45 +00002060/* Macros to save and align the stack before making a function
2061 call and restore it afterwards as gcc may not keep the stack
2062 pointer aligned if it doesn't realise calls are being made
2063 to other functions. */
2064
2065#define VALGRIND_ALIGN_STACK \
2066 "mr 28,1\n\t" \
2067 "rlwinm 1,1,0,0,27\n\t"
2068#define VALGRIND_RESTORE_STACK \
2069 "mr 1,28\n\t"
2070
sewardjead61df2006-03-12 13:39:15 +00002071/* These CALL_FN_ macros assume that on ppc32-linux,
2072 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00002073
sewardj38de0992006-01-20 16:46:34 +00002074#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00002075 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002076 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002077 volatile unsigned long _argvec[1]; \
2078 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002079 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002080 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002081 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002082 "mr 11,%1\n\t" \
2083 "lwz 11,0(11)\n\t" /* target->r11 */ \
2084 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002085 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002086 "mr %0,3" \
2087 : /*out*/ "=r" (_res) \
2088 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002089 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002090 ); \
2091 lval = (__typeof__(lval)) _res; \
2092 } while (0)
2093
sewardj38de0992006-01-20 16:46:34 +00002094#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00002095 do { \
sewardj38de0992006-01-20 16:46:34 +00002096 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002097 volatile unsigned long _argvec[2]; \
2098 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002099 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002100 _argvec[1] = (unsigned long)arg1; \
2101 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002102 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002103 "mr 11,%1\n\t" \
2104 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2105 "lwz 11,0(11)\n\t" /* target->r11 */ \
2106 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002107 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002108 "mr %0,3" \
2109 : /*out*/ "=r" (_res) \
2110 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002111 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002112 ); \
2113 lval = (__typeof__(lval)) _res; \
2114 } while (0)
2115
sewardj38de0992006-01-20 16:46:34 +00002116#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00002117 do { \
sewardj38de0992006-01-20 16:46:34 +00002118 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002119 volatile unsigned long _argvec[3]; \
2120 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002121 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002122 _argvec[1] = (unsigned long)arg1; \
2123 _argvec[2] = (unsigned long)arg2; \
2124 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002125 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002126 "mr 11,%1\n\t" \
2127 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2128 "lwz 4,8(11)\n\t" \
2129 "lwz 11,0(11)\n\t" /* target->r11 */ \
2130 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002131 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002132 "mr %0,3" \
2133 : /*out*/ "=r" (_res) \
2134 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002135 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002136 ); \
2137 lval = (__typeof__(lval)) _res; \
2138 } while (0)
2139
sewardjead61df2006-03-12 13:39:15 +00002140#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2141 do { \
2142 volatile OrigFn _orig = (orig); \
2143 volatile unsigned long _argvec[4]; \
2144 volatile unsigned long _res; \
2145 _argvec[0] = (unsigned long)_orig.nraddr; \
2146 _argvec[1] = (unsigned long)arg1; \
2147 _argvec[2] = (unsigned long)arg2; \
2148 _argvec[3] = (unsigned long)arg3; \
2149 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002150 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002151 "mr 11,%1\n\t" \
2152 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2153 "lwz 4,8(11)\n\t" \
2154 "lwz 5,12(11)\n\t" \
2155 "lwz 11,0(11)\n\t" /* target->r11 */ \
2156 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002157 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002158 "mr %0,3" \
2159 : /*out*/ "=r" (_res) \
2160 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002161 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002162 ); \
2163 lval = (__typeof__(lval)) _res; \
2164 } while (0)
2165
2166#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2167 do { \
2168 volatile OrigFn _orig = (orig); \
2169 volatile unsigned long _argvec[5]; \
2170 volatile unsigned long _res; \
2171 _argvec[0] = (unsigned long)_orig.nraddr; \
2172 _argvec[1] = (unsigned long)arg1; \
2173 _argvec[2] = (unsigned long)arg2; \
2174 _argvec[3] = (unsigned long)arg3; \
2175 _argvec[4] = (unsigned long)arg4; \
2176 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002177 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002178 "mr 11,%1\n\t" \
2179 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2180 "lwz 4,8(11)\n\t" \
2181 "lwz 5,12(11)\n\t" \
2182 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2183 "lwz 11,0(11)\n\t" /* target->r11 */ \
2184 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002185 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002186 "mr %0,3" \
2187 : /*out*/ "=r" (_res) \
2188 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002189 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002190 ); \
2191 lval = (__typeof__(lval)) _res; \
2192 } while (0)
2193
2194#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2195 do { \
2196 volatile OrigFn _orig = (orig); \
2197 volatile unsigned long _argvec[6]; \
2198 volatile unsigned long _res; \
2199 _argvec[0] = (unsigned long)_orig.nraddr; \
2200 _argvec[1] = (unsigned long)arg1; \
2201 _argvec[2] = (unsigned long)arg2; \
2202 _argvec[3] = (unsigned long)arg3; \
2203 _argvec[4] = (unsigned long)arg4; \
2204 _argvec[5] = (unsigned long)arg5; \
2205 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002206 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002207 "mr 11,%1\n\t" \
2208 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2209 "lwz 4,8(11)\n\t" \
2210 "lwz 5,12(11)\n\t" \
2211 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2212 "lwz 7,20(11)\n\t" \
2213 "lwz 11,0(11)\n\t" /* target->r11 */ \
2214 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002215 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002216 "mr %0,3" \
2217 : /*out*/ "=r" (_res) \
2218 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002219 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002220 ); \
2221 lval = (__typeof__(lval)) _res; \
2222 } while (0)
2223
2224#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2225 do { \
2226 volatile OrigFn _orig = (orig); \
2227 volatile unsigned long _argvec[7]; \
2228 volatile unsigned long _res; \
2229 _argvec[0] = (unsigned long)_orig.nraddr; \
2230 _argvec[1] = (unsigned long)arg1; \
2231 _argvec[2] = (unsigned long)arg2; \
2232 _argvec[3] = (unsigned long)arg3; \
2233 _argvec[4] = (unsigned long)arg4; \
2234 _argvec[5] = (unsigned long)arg5; \
2235 _argvec[6] = (unsigned long)arg6; \
2236 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002237 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002238 "mr 11,%1\n\t" \
2239 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2240 "lwz 4,8(11)\n\t" \
2241 "lwz 5,12(11)\n\t" \
2242 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2243 "lwz 7,20(11)\n\t" \
2244 "lwz 8,24(11)\n\t" \
2245 "lwz 11,0(11)\n\t" /* target->r11 */ \
2246 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002247 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002248 "mr %0,3" \
2249 : /*out*/ "=r" (_res) \
2250 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002251 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002252 ); \
2253 lval = (__typeof__(lval)) _res; \
2254 } while (0)
2255
2256#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2257 arg7) \
2258 do { \
2259 volatile OrigFn _orig = (orig); \
2260 volatile unsigned long _argvec[8]; \
2261 volatile unsigned long _res; \
2262 _argvec[0] = (unsigned long)_orig.nraddr; \
2263 _argvec[1] = (unsigned long)arg1; \
2264 _argvec[2] = (unsigned long)arg2; \
2265 _argvec[3] = (unsigned long)arg3; \
2266 _argvec[4] = (unsigned long)arg4; \
2267 _argvec[5] = (unsigned long)arg5; \
2268 _argvec[6] = (unsigned long)arg6; \
2269 _argvec[7] = (unsigned long)arg7; \
2270 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002271 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002272 "mr 11,%1\n\t" \
2273 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2274 "lwz 4,8(11)\n\t" \
2275 "lwz 5,12(11)\n\t" \
2276 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2277 "lwz 7,20(11)\n\t" \
2278 "lwz 8,24(11)\n\t" \
2279 "lwz 9,28(11)\n\t" \
2280 "lwz 11,0(11)\n\t" /* target->r11 */ \
2281 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002282 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002283 "mr %0,3" \
2284 : /*out*/ "=r" (_res) \
2285 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002286 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002287 ); \
2288 lval = (__typeof__(lval)) _res; \
2289 } while (0)
2290
2291#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2292 arg7,arg8) \
2293 do { \
2294 volatile OrigFn _orig = (orig); \
2295 volatile unsigned long _argvec[9]; \
2296 volatile unsigned long _res; \
2297 _argvec[0] = (unsigned long)_orig.nraddr; \
2298 _argvec[1] = (unsigned long)arg1; \
2299 _argvec[2] = (unsigned long)arg2; \
2300 _argvec[3] = (unsigned long)arg3; \
2301 _argvec[4] = (unsigned long)arg4; \
2302 _argvec[5] = (unsigned long)arg5; \
2303 _argvec[6] = (unsigned long)arg6; \
2304 _argvec[7] = (unsigned long)arg7; \
2305 _argvec[8] = (unsigned long)arg8; \
2306 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002307 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002308 "mr 11,%1\n\t" \
2309 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2310 "lwz 4,8(11)\n\t" \
2311 "lwz 5,12(11)\n\t" \
2312 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2313 "lwz 7,20(11)\n\t" \
2314 "lwz 8,24(11)\n\t" \
2315 "lwz 9,28(11)\n\t" \
2316 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2317 "lwz 11,0(11)\n\t" /* target->r11 */ \
2318 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002319 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002320 "mr %0,3" \
2321 : /*out*/ "=r" (_res) \
2322 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002323 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002324 ); \
2325 lval = (__typeof__(lval)) _res; \
2326 } while (0)
2327
2328#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2329 arg7,arg8,arg9) \
2330 do { \
2331 volatile OrigFn _orig = (orig); \
2332 volatile unsigned long _argvec[10]; \
2333 volatile unsigned long _res; \
2334 _argvec[0] = (unsigned long)_orig.nraddr; \
2335 _argvec[1] = (unsigned long)arg1; \
2336 _argvec[2] = (unsigned long)arg2; \
2337 _argvec[3] = (unsigned long)arg3; \
2338 _argvec[4] = (unsigned long)arg4; \
2339 _argvec[5] = (unsigned long)arg5; \
2340 _argvec[6] = (unsigned long)arg6; \
2341 _argvec[7] = (unsigned long)arg7; \
2342 _argvec[8] = (unsigned long)arg8; \
2343 _argvec[9] = (unsigned long)arg9; \
2344 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002345 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002346 "mr 11,%1\n\t" \
2347 "addi 1,1,-16\n\t" \
2348 /* arg9 */ \
2349 "lwz 3,36(11)\n\t" \
2350 "stw 3,8(1)\n\t" \
2351 /* args1-8 */ \
2352 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2353 "lwz 4,8(11)\n\t" \
2354 "lwz 5,12(11)\n\t" \
2355 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2356 "lwz 7,20(11)\n\t" \
2357 "lwz 8,24(11)\n\t" \
2358 "lwz 9,28(11)\n\t" \
2359 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2360 "lwz 11,0(11)\n\t" /* target->r11 */ \
2361 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002362 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002363 "mr %0,3" \
2364 : /*out*/ "=r" (_res) \
2365 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002366 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002367 ); \
2368 lval = (__typeof__(lval)) _res; \
2369 } while (0)
2370
2371#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2372 arg7,arg8,arg9,arg10) \
2373 do { \
2374 volatile OrigFn _orig = (orig); \
2375 volatile unsigned long _argvec[11]; \
2376 volatile unsigned long _res; \
2377 _argvec[0] = (unsigned long)_orig.nraddr; \
2378 _argvec[1] = (unsigned long)arg1; \
2379 _argvec[2] = (unsigned long)arg2; \
2380 _argvec[3] = (unsigned long)arg3; \
2381 _argvec[4] = (unsigned long)arg4; \
2382 _argvec[5] = (unsigned long)arg5; \
2383 _argvec[6] = (unsigned long)arg6; \
2384 _argvec[7] = (unsigned long)arg7; \
2385 _argvec[8] = (unsigned long)arg8; \
2386 _argvec[9] = (unsigned long)arg9; \
2387 _argvec[10] = (unsigned long)arg10; \
2388 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002389 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002390 "mr 11,%1\n\t" \
2391 "addi 1,1,-16\n\t" \
2392 /* arg10 */ \
2393 "lwz 3,40(11)\n\t" \
2394 "stw 3,12(1)\n\t" \
2395 /* arg9 */ \
2396 "lwz 3,36(11)\n\t" \
2397 "stw 3,8(1)\n\t" \
2398 /* args1-8 */ \
2399 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2400 "lwz 4,8(11)\n\t" \
2401 "lwz 5,12(11)\n\t" \
2402 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2403 "lwz 7,20(11)\n\t" \
2404 "lwz 8,24(11)\n\t" \
2405 "lwz 9,28(11)\n\t" \
2406 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2407 "lwz 11,0(11)\n\t" /* target->r11 */ \
2408 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002409 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002410 "mr %0,3" \
2411 : /*out*/ "=r" (_res) \
2412 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002413 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002414 ); \
2415 lval = (__typeof__(lval)) _res; \
2416 } while (0)
2417
2418#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2419 arg7,arg8,arg9,arg10,arg11) \
2420 do { \
2421 volatile OrigFn _orig = (orig); \
2422 volatile unsigned long _argvec[12]; \
2423 volatile unsigned long _res; \
2424 _argvec[0] = (unsigned long)_orig.nraddr; \
2425 _argvec[1] = (unsigned long)arg1; \
2426 _argvec[2] = (unsigned long)arg2; \
2427 _argvec[3] = (unsigned long)arg3; \
2428 _argvec[4] = (unsigned long)arg4; \
2429 _argvec[5] = (unsigned long)arg5; \
2430 _argvec[6] = (unsigned long)arg6; \
2431 _argvec[7] = (unsigned long)arg7; \
2432 _argvec[8] = (unsigned long)arg8; \
2433 _argvec[9] = (unsigned long)arg9; \
2434 _argvec[10] = (unsigned long)arg10; \
2435 _argvec[11] = (unsigned long)arg11; \
2436 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002437 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002438 "mr 11,%1\n\t" \
2439 "addi 1,1,-32\n\t" \
2440 /* arg11 */ \
2441 "lwz 3,44(11)\n\t" \
2442 "stw 3,16(1)\n\t" \
2443 /* arg10 */ \
2444 "lwz 3,40(11)\n\t" \
2445 "stw 3,12(1)\n\t" \
2446 /* arg9 */ \
2447 "lwz 3,36(11)\n\t" \
2448 "stw 3,8(1)\n\t" \
2449 /* args1-8 */ \
2450 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2451 "lwz 4,8(11)\n\t" \
2452 "lwz 5,12(11)\n\t" \
2453 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2454 "lwz 7,20(11)\n\t" \
2455 "lwz 8,24(11)\n\t" \
2456 "lwz 9,28(11)\n\t" \
2457 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2458 "lwz 11,0(11)\n\t" /* target->r11 */ \
2459 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002460 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002461 "mr %0,3" \
2462 : /*out*/ "=r" (_res) \
2463 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002464 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002465 ); \
2466 lval = (__typeof__(lval)) _res; \
2467 } while (0)
2468
2469#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2470 arg7,arg8,arg9,arg10,arg11,arg12) \
2471 do { \
2472 volatile OrigFn _orig = (orig); \
2473 volatile unsigned long _argvec[13]; \
2474 volatile unsigned long _res; \
2475 _argvec[0] = (unsigned long)_orig.nraddr; \
2476 _argvec[1] = (unsigned long)arg1; \
2477 _argvec[2] = (unsigned long)arg2; \
2478 _argvec[3] = (unsigned long)arg3; \
2479 _argvec[4] = (unsigned long)arg4; \
2480 _argvec[5] = (unsigned long)arg5; \
2481 _argvec[6] = (unsigned long)arg6; \
2482 _argvec[7] = (unsigned long)arg7; \
2483 _argvec[8] = (unsigned long)arg8; \
2484 _argvec[9] = (unsigned long)arg9; \
2485 _argvec[10] = (unsigned long)arg10; \
2486 _argvec[11] = (unsigned long)arg11; \
2487 _argvec[12] = (unsigned long)arg12; \
2488 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002489 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002490 "mr 11,%1\n\t" \
2491 "addi 1,1,-32\n\t" \
2492 /* arg12 */ \
2493 "lwz 3,48(11)\n\t" \
2494 "stw 3,20(1)\n\t" \
2495 /* arg11 */ \
2496 "lwz 3,44(11)\n\t" \
2497 "stw 3,16(1)\n\t" \
2498 /* arg10 */ \
2499 "lwz 3,40(11)\n\t" \
2500 "stw 3,12(1)\n\t" \
2501 /* arg9 */ \
2502 "lwz 3,36(11)\n\t" \
2503 "stw 3,8(1)\n\t" \
2504 /* args1-8 */ \
2505 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2506 "lwz 4,8(11)\n\t" \
2507 "lwz 5,12(11)\n\t" \
2508 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2509 "lwz 7,20(11)\n\t" \
2510 "lwz 8,24(11)\n\t" \
2511 "lwz 9,28(11)\n\t" \
2512 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2513 "lwz 11,0(11)\n\t" /* target->r11 */ \
2514 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002515 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002516 "mr %0,3" \
2517 : /*out*/ "=r" (_res) \
2518 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002519 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002520 ); \
2521 lval = (__typeof__(lval)) _res; \
2522 } while (0)
2523
sewardjf5c1a7f2006-10-17 01:32:48 +00002524#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002525
sewardjf5c1a7f2006-10-17 01:32:48 +00002526/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002527
sewardjf5c1a7f2006-10-17 01:32:48 +00002528#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002529
2530/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2531
2532/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002533#define __CALLER_SAVED_REGS \
2534 "lr", "ctr", "xer", \
2535 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2536 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2537 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002538
tom4118e0f2012-08-02 09:23:45 +00002539/* Macros to save and align the stack before making a function
2540 call and restore it afterwards as gcc may not keep the stack
2541 pointer aligned if it doesn't realise calls are being made
2542 to other functions. */
2543
2544#define VALGRIND_ALIGN_STACK \
2545 "mr 28,1\n\t" \
2546 "rldicr 1,1,0,59\n\t"
2547#define VALGRIND_RESTORE_STACK \
2548 "mr 1,28\n\t"
2549
sewardj9734b202006-01-17 01:49:37 +00002550/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2551 long) == 8. */
2552
sewardjd68ac3e2006-01-20 14:31:57 +00002553#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002554 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002555 volatile OrigFn _orig = (orig); \
2556 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002557 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002558 /* _argvec[0] holds current r2 across the call */ \
2559 _argvec[1] = (unsigned long)_orig.r2; \
2560 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002561 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002562 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002563 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002564 "std 2,-16(11)\n\t" /* save tocptr */ \
2565 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2566 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002567 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2568 "mr 11,%1\n\t" \
2569 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002570 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2571 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002572 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002573 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002574 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002575 ); \
2576 lval = (__typeof__(lval)) _res; \
2577 } while (0)
2578
sewardjd68ac3e2006-01-20 14:31:57 +00002579#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002580 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002581 volatile OrigFn _orig = (orig); \
2582 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002583 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002584 /* _argvec[0] holds current r2 across the call */ \
2585 _argvec[1] = (unsigned long)_orig.r2; \
2586 _argvec[2] = (unsigned long)_orig.nraddr; \
2587 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002588 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002589 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002590 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002591 "std 2,-16(11)\n\t" /* save tocptr */ \
2592 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2593 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2594 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002595 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2596 "mr 11,%1\n\t" \
2597 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002598 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2599 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002600 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002601 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002602 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002603 ); \
2604 lval = (__typeof__(lval)) _res; \
2605 } while (0)
2606
sewardjd68ac3e2006-01-20 14:31:57 +00002607#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002608 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002609 volatile OrigFn _orig = (orig); \
2610 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002611 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002612 /* _argvec[0] holds current r2 across the call */ \
2613 _argvec[1] = (unsigned long)_orig.r2; \
2614 _argvec[2] = (unsigned long)_orig.nraddr; \
2615 _argvec[2+1] = (unsigned long)arg1; \
2616 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002617 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002618 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002619 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002620 "std 2,-16(11)\n\t" /* save tocptr */ \
2621 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2622 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002623 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002624 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002625 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2626 "mr 11,%1\n\t" \
2627 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002628 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2629 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002630 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002631 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002632 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002633 ); \
2634 lval = (__typeof__(lval)) _res; \
2635 } while (0)
2636
sewardjcd636392006-03-12 16:48:14 +00002637#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2638 do { \
2639 volatile OrigFn _orig = (orig); \
2640 volatile unsigned long _argvec[3+3]; \
2641 volatile unsigned long _res; \
2642 /* _argvec[0] holds current r2 across the call */ \
2643 _argvec[1] = (unsigned long)_orig.r2; \
2644 _argvec[2] = (unsigned long)_orig.nraddr; \
2645 _argvec[2+1] = (unsigned long)arg1; \
2646 _argvec[2+2] = (unsigned long)arg2; \
2647 _argvec[2+3] = (unsigned long)arg3; \
2648 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002649 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002650 "mr 11,%1\n\t" \
2651 "std 2,-16(11)\n\t" /* save tocptr */ \
2652 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2653 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2654 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2655 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2656 "ld 11, 0(11)\n\t" /* target->r11 */ \
2657 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2658 "mr 11,%1\n\t" \
2659 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002660 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2661 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002662 : /*out*/ "=r" (_res) \
2663 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002664 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002665 ); \
2666 lval = (__typeof__(lval)) _res; \
2667 } while (0)
2668
2669#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2670 do { \
2671 volatile OrigFn _orig = (orig); \
2672 volatile unsigned long _argvec[3+4]; \
2673 volatile unsigned long _res; \
2674 /* _argvec[0] holds current r2 across the call */ \
2675 _argvec[1] = (unsigned long)_orig.r2; \
2676 _argvec[2] = (unsigned long)_orig.nraddr; \
2677 _argvec[2+1] = (unsigned long)arg1; \
2678 _argvec[2+2] = (unsigned long)arg2; \
2679 _argvec[2+3] = (unsigned long)arg3; \
2680 _argvec[2+4] = (unsigned long)arg4; \
2681 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002682 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002683 "mr 11,%1\n\t" \
2684 "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 4, 16(11)\n\t" /* arg2->r4 */ \
2688 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2689 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2690 "ld 11, 0(11)\n\t" /* target->r11 */ \
2691 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2692 "mr 11,%1\n\t" \
2693 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002694 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2695 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002696 : /*out*/ "=r" (_res) \
2697 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002698 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002699 ); \
2700 lval = (__typeof__(lval)) _res; \
2701 } while (0)
2702
2703#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2704 do { \
2705 volatile OrigFn _orig = (orig); \
2706 volatile unsigned long _argvec[3+5]; \
2707 volatile unsigned long _res; \
2708 /* _argvec[0] holds current r2 across the call */ \
2709 _argvec[1] = (unsigned long)_orig.r2; \
2710 _argvec[2] = (unsigned long)_orig.nraddr; \
2711 _argvec[2+1] = (unsigned long)arg1; \
2712 _argvec[2+2] = (unsigned long)arg2; \
2713 _argvec[2+3] = (unsigned long)arg3; \
2714 _argvec[2+4] = (unsigned long)arg4; \
2715 _argvec[2+5] = (unsigned long)arg5; \
2716 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002717 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002718 "mr 11,%1\n\t" \
2719 "std 2,-16(11)\n\t" /* save tocptr */ \
2720 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2721 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2722 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2723 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2724 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2725 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2726 "ld 11, 0(11)\n\t" /* target->r11 */ \
2727 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2728 "mr 11,%1\n\t" \
2729 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002730 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2731 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002732 : /*out*/ "=r" (_res) \
2733 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002734 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002735 ); \
2736 lval = (__typeof__(lval)) _res; \
2737 } while (0)
2738
2739#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2740 do { \
2741 volatile OrigFn _orig = (orig); \
2742 volatile unsigned long _argvec[3+6]; \
2743 volatile unsigned long _res; \
2744 /* _argvec[0] holds current r2 across the call */ \
2745 _argvec[1] = (unsigned long)_orig.r2; \
2746 _argvec[2] = (unsigned long)_orig.nraddr; \
2747 _argvec[2+1] = (unsigned long)arg1; \
2748 _argvec[2+2] = (unsigned long)arg2; \
2749 _argvec[2+3] = (unsigned long)arg3; \
2750 _argvec[2+4] = (unsigned long)arg4; \
2751 _argvec[2+5] = (unsigned long)arg5; \
2752 _argvec[2+6] = (unsigned long)arg6; \
2753 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002754 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002755 "mr 11,%1\n\t" \
2756 "std 2,-16(11)\n\t" /* save tocptr */ \
2757 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2758 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2759 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2760 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2761 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2762 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2763 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2764 "ld 11, 0(11)\n\t" /* target->r11 */ \
2765 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2766 "mr 11,%1\n\t" \
2767 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002768 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2769 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002770 : /*out*/ "=r" (_res) \
2771 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002772 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002773 ); \
2774 lval = (__typeof__(lval)) _res; \
2775 } while (0)
2776
2777#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2778 arg7) \
2779 do { \
2780 volatile OrigFn _orig = (orig); \
2781 volatile unsigned long _argvec[3+7]; \
2782 volatile unsigned long _res; \
2783 /* _argvec[0] holds current r2 across the call */ \
2784 _argvec[1] = (unsigned long)_orig.r2; \
2785 _argvec[2] = (unsigned long)_orig.nraddr; \
2786 _argvec[2+1] = (unsigned long)arg1; \
2787 _argvec[2+2] = (unsigned long)arg2; \
2788 _argvec[2+3] = (unsigned long)arg3; \
2789 _argvec[2+4] = (unsigned long)arg4; \
2790 _argvec[2+5] = (unsigned long)arg5; \
2791 _argvec[2+6] = (unsigned long)arg6; \
2792 _argvec[2+7] = (unsigned long)arg7; \
2793 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002794 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002795 "mr 11,%1\n\t" \
2796 "std 2,-16(11)\n\t" /* save tocptr */ \
2797 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2798 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2799 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2800 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2801 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2802 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2803 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2804 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2805 "ld 11, 0(11)\n\t" /* target->r11 */ \
2806 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2807 "mr 11,%1\n\t" \
2808 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002809 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2810 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002811 : /*out*/ "=r" (_res) \
2812 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002813 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002814 ); \
2815 lval = (__typeof__(lval)) _res; \
2816 } while (0)
2817
2818#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2819 arg7,arg8) \
2820 do { \
2821 volatile OrigFn _orig = (orig); \
2822 volatile unsigned long _argvec[3+8]; \
2823 volatile unsigned long _res; \
2824 /* _argvec[0] holds current r2 across the call */ \
2825 _argvec[1] = (unsigned long)_orig.r2; \
2826 _argvec[2] = (unsigned long)_orig.nraddr; \
2827 _argvec[2+1] = (unsigned long)arg1; \
2828 _argvec[2+2] = (unsigned long)arg2; \
2829 _argvec[2+3] = (unsigned long)arg3; \
2830 _argvec[2+4] = (unsigned long)arg4; \
2831 _argvec[2+5] = (unsigned long)arg5; \
2832 _argvec[2+6] = (unsigned long)arg6; \
2833 _argvec[2+7] = (unsigned long)arg7; \
2834 _argvec[2+8] = (unsigned long)arg8; \
2835 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002836 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002837 "mr 11,%1\n\t" \
2838 "std 2,-16(11)\n\t" /* save tocptr */ \
2839 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2840 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2841 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2842 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2843 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2844 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2845 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2846 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2847 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2848 "ld 11, 0(11)\n\t" /* target->r11 */ \
2849 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2850 "mr 11,%1\n\t" \
2851 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002852 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2853 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002854 : /*out*/ "=r" (_res) \
2855 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002856 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002857 ); \
2858 lval = (__typeof__(lval)) _res; \
2859 } while (0)
2860
2861#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2862 arg7,arg8,arg9) \
2863 do { \
2864 volatile OrigFn _orig = (orig); \
2865 volatile unsigned long _argvec[3+9]; \
2866 volatile unsigned long _res; \
2867 /* _argvec[0] holds current r2 across the call */ \
2868 _argvec[1] = (unsigned long)_orig.r2; \
2869 _argvec[2] = (unsigned long)_orig.nraddr; \
2870 _argvec[2+1] = (unsigned long)arg1; \
2871 _argvec[2+2] = (unsigned long)arg2; \
2872 _argvec[2+3] = (unsigned long)arg3; \
2873 _argvec[2+4] = (unsigned long)arg4; \
2874 _argvec[2+5] = (unsigned long)arg5; \
2875 _argvec[2+6] = (unsigned long)arg6; \
2876 _argvec[2+7] = (unsigned long)arg7; \
2877 _argvec[2+8] = (unsigned long)arg8; \
2878 _argvec[2+9] = (unsigned long)arg9; \
2879 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002880 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002881 "mr 11,%1\n\t" \
2882 "std 2,-16(11)\n\t" /* save tocptr */ \
2883 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2884 "addi 1,1,-128\n\t" /* expand stack frame */ \
2885 /* arg9 */ \
2886 "ld 3,72(11)\n\t" \
2887 "std 3,112(1)\n\t" \
2888 /* args1-8 */ \
2889 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2890 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2891 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2892 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2893 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2894 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2895 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2896 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2897 "ld 11, 0(11)\n\t" /* target->r11 */ \
2898 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2899 "mr 11,%1\n\t" \
2900 "mr %0,3\n\t" \
2901 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002902 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002903 : /*out*/ "=r" (_res) \
2904 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002905 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002906 ); \
2907 lval = (__typeof__(lval)) _res; \
2908 } while (0)
2909
2910#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2911 arg7,arg8,arg9,arg10) \
2912 do { \
2913 volatile OrigFn _orig = (orig); \
2914 volatile unsigned long _argvec[3+10]; \
2915 volatile unsigned long _res; \
2916 /* _argvec[0] holds current r2 across the call */ \
2917 _argvec[1] = (unsigned long)_orig.r2; \
2918 _argvec[2] = (unsigned long)_orig.nraddr; \
2919 _argvec[2+1] = (unsigned long)arg1; \
2920 _argvec[2+2] = (unsigned long)arg2; \
2921 _argvec[2+3] = (unsigned long)arg3; \
2922 _argvec[2+4] = (unsigned long)arg4; \
2923 _argvec[2+5] = (unsigned long)arg5; \
2924 _argvec[2+6] = (unsigned long)arg6; \
2925 _argvec[2+7] = (unsigned long)arg7; \
2926 _argvec[2+8] = (unsigned long)arg8; \
2927 _argvec[2+9] = (unsigned long)arg9; \
2928 _argvec[2+10] = (unsigned long)arg10; \
2929 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002930 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002931 "mr 11,%1\n\t" \
2932 "std 2,-16(11)\n\t" /* save tocptr */ \
2933 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2934 "addi 1,1,-128\n\t" /* expand stack frame */ \
2935 /* arg10 */ \
2936 "ld 3,80(11)\n\t" \
2937 "std 3,120(1)\n\t" \
2938 /* arg9 */ \
2939 "ld 3,72(11)\n\t" \
2940 "std 3,112(1)\n\t" \
2941 /* args1-8 */ \
2942 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2943 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2944 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2945 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2946 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2947 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2948 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2949 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2950 "ld 11, 0(11)\n\t" /* target->r11 */ \
2951 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2952 "mr 11,%1\n\t" \
2953 "mr %0,3\n\t" \
2954 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002955 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002956 : /*out*/ "=r" (_res) \
2957 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002958 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002959 ); \
2960 lval = (__typeof__(lval)) _res; \
2961 } while (0)
2962
2963#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2964 arg7,arg8,arg9,arg10,arg11) \
2965 do { \
2966 volatile OrigFn _orig = (orig); \
2967 volatile unsigned long _argvec[3+11]; \
2968 volatile unsigned long _res; \
2969 /* _argvec[0] holds current r2 across the call */ \
2970 _argvec[1] = (unsigned long)_orig.r2; \
2971 _argvec[2] = (unsigned long)_orig.nraddr; \
2972 _argvec[2+1] = (unsigned long)arg1; \
2973 _argvec[2+2] = (unsigned long)arg2; \
2974 _argvec[2+3] = (unsigned long)arg3; \
2975 _argvec[2+4] = (unsigned long)arg4; \
2976 _argvec[2+5] = (unsigned long)arg5; \
2977 _argvec[2+6] = (unsigned long)arg6; \
2978 _argvec[2+7] = (unsigned long)arg7; \
2979 _argvec[2+8] = (unsigned long)arg8; \
2980 _argvec[2+9] = (unsigned long)arg9; \
2981 _argvec[2+10] = (unsigned long)arg10; \
2982 _argvec[2+11] = (unsigned long)arg11; \
2983 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002984 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002985 "mr 11,%1\n\t" \
2986 "std 2,-16(11)\n\t" /* save tocptr */ \
2987 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2988 "addi 1,1,-144\n\t" /* expand stack frame */ \
2989 /* arg11 */ \
2990 "ld 3,88(11)\n\t" \
2991 "std 3,128(1)\n\t" \
2992 /* arg10 */ \
2993 "ld 3,80(11)\n\t" \
2994 "std 3,120(1)\n\t" \
2995 /* arg9 */ \
2996 "ld 3,72(11)\n\t" \
2997 "std 3,112(1)\n\t" \
2998 /* args1-8 */ \
2999 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3000 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3001 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3002 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3003 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3004 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3005 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3006 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3007 "ld 11, 0(11)\n\t" /* target->r11 */ \
3008 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3009 "mr 11,%1\n\t" \
3010 "mr %0,3\n\t" \
3011 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003012 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003013 : /*out*/ "=r" (_res) \
3014 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003015 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003016 ); \
3017 lval = (__typeof__(lval)) _res; \
3018 } while (0)
3019
3020#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3021 arg7,arg8,arg9,arg10,arg11,arg12) \
3022 do { \
3023 volatile OrigFn _orig = (orig); \
3024 volatile unsigned long _argvec[3+12]; \
3025 volatile unsigned long _res; \
3026 /* _argvec[0] holds current r2 across the call */ \
3027 _argvec[1] = (unsigned long)_orig.r2; \
3028 _argvec[2] = (unsigned long)_orig.nraddr; \
3029 _argvec[2+1] = (unsigned long)arg1; \
3030 _argvec[2+2] = (unsigned long)arg2; \
3031 _argvec[2+3] = (unsigned long)arg3; \
3032 _argvec[2+4] = (unsigned long)arg4; \
3033 _argvec[2+5] = (unsigned long)arg5; \
3034 _argvec[2+6] = (unsigned long)arg6; \
3035 _argvec[2+7] = (unsigned long)arg7; \
3036 _argvec[2+8] = (unsigned long)arg8; \
3037 _argvec[2+9] = (unsigned long)arg9; \
3038 _argvec[2+10] = (unsigned long)arg10; \
3039 _argvec[2+11] = (unsigned long)arg11; \
3040 _argvec[2+12] = (unsigned long)arg12; \
3041 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003042 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003043 "mr 11,%1\n\t" \
3044 "std 2,-16(11)\n\t" /* save tocptr */ \
3045 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3046 "addi 1,1,-144\n\t" /* expand stack frame */ \
3047 /* arg12 */ \
3048 "ld 3,96(11)\n\t" \
3049 "std 3,136(1)\n\t" \
3050 /* arg11 */ \
3051 "ld 3,88(11)\n\t" \
3052 "std 3,128(1)\n\t" \
3053 /* arg10 */ \
3054 "ld 3,80(11)\n\t" \
3055 "std 3,120(1)\n\t" \
3056 /* arg9 */ \
3057 "ld 3,72(11)\n\t" \
3058 "std 3,112(1)\n\t" \
3059 /* args1-8 */ \
3060 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3061 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3062 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3063 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3064 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3065 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3066 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3067 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3068 "ld 11, 0(11)\n\t" /* target->r11 */ \
3069 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3070 "mr 11,%1\n\t" \
3071 "mr %0,3\n\t" \
3072 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003073 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003074 : /*out*/ "=r" (_res) \
3075 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003076 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003077 ); \
3078 lval = (__typeof__(lval)) _res; \
3079 } while (0)
3080
sewardjf5c1a7f2006-10-17 01:32:48 +00003081#endif /* PLAT_ppc64_linux */
3082
sewardj59570ff2010-01-01 11:59:33 +00003083/* ------------------------- arm-linux ------------------------- */
3084
3085#if defined(PLAT_arm_linux)
3086
3087/* These regs are trashed by the hidden call. */
3088#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
3089
tom4118e0f2012-08-02 09:23:45 +00003090/* Macros to save and align the stack before making a function
3091 call and restore it afterwards as gcc may not keep the stack
3092 pointer aligned if it doesn't realise calls are being made
3093 to other functions. */
3094
sewardj567e5bb2012-08-04 19:23:54 +00003095/* This is a bit tricky. We store the original stack pointer in r10
3096 as it is callee-saves. gcc doesn't allow the use of r11 for some
3097 reason. Also, we can't directly "bic" the stack pointer in thumb
3098 mode since r13 isn't an allowed register number in that context.
3099 So use r4 as a temporary, since that is about to get trashed
3100 anyway, just after each use of this macro. Side effect is we need
3101 to be very careful about any future changes, since
3102 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
tom4118e0f2012-08-02 09:23:45 +00003103#define VALGRIND_ALIGN_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003104 "mov r10, sp\n\t" \
3105 "mov r4, sp\n\t" \
3106 "bic r4, r4, #7\n\t" \
3107 "mov sp, r4\n\t"
tom4118e0f2012-08-02 09:23:45 +00003108#define VALGRIND_RESTORE_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003109 "mov sp, r10\n\t"
tom4118e0f2012-08-02 09:23:45 +00003110
sewardj59570ff2010-01-01 11:59:33 +00003111/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3112 long) == 4. */
3113
3114#define CALL_FN_W_v(lval, orig) \
3115 do { \
3116 volatile OrigFn _orig = (orig); \
3117 volatile unsigned long _argvec[1]; \
3118 volatile unsigned long _res; \
3119 _argvec[0] = (unsigned long)_orig.nraddr; \
3120 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003121 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003122 "ldr r4, [%1] \n\t" /* target->r4 */ \
3123 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003124 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003125 "mov %0, r0\n" \
3126 : /*out*/ "=r" (_res) \
3127 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003128 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003129 ); \
3130 lval = (__typeof__(lval)) _res; \
3131 } while (0)
3132
3133#define CALL_FN_W_W(lval, orig, arg1) \
3134 do { \
3135 volatile OrigFn _orig = (orig); \
3136 volatile unsigned long _argvec[2]; \
3137 volatile unsigned long _res; \
3138 _argvec[0] = (unsigned long)_orig.nraddr; \
3139 _argvec[1] = (unsigned long)(arg1); \
3140 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003141 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003142 "ldr r0, [%1, #4] \n\t" \
3143 "ldr r4, [%1] \n\t" /* target->r4 */ \
3144 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003145 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003146 "mov %0, r0\n" \
3147 : /*out*/ "=r" (_res) \
3148 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003149 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003150 ); \
3151 lval = (__typeof__(lval)) _res; \
3152 } while (0)
3153
3154#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3155 do { \
3156 volatile OrigFn _orig = (orig); \
3157 volatile unsigned long _argvec[3]; \
3158 volatile unsigned long _res; \
3159 _argvec[0] = (unsigned long)_orig.nraddr; \
3160 _argvec[1] = (unsigned long)(arg1); \
3161 _argvec[2] = (unsigned long)(arg2); \
3162 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003163 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003164 "ldr r0, [%1, #4] \n\t" \
3165 "ldr r1, [%1, #8] \n\t" \
3166 "ldr r4, [%1] \n\t" /* target->r4 */ \
3167 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003168 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003169 "mov %0, r0\n" \
3170 : /*out*/ "=r" (_res) \
3171 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003172 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003173 ); \
3174 lval = (__typeof__(lval)) _res; \
3175 } while (0)
3176
3177#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3178 do { \
3179 volatile OrigFn _orig = (orig); \
3180 volatile unsigned long _argvec[4]; \
3181 volatile unsigned long _res; \
3182 _argvec[0] = (unsigned long)_orig.nraddr; \
3183 _argvec[1] = (unsigned long)(arg1); \
3184 _argvec[2] = (unsigned long)(arg2); \
3185 _argvec[3] = (unsigned long)(arg3); \
3186 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003187 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003188 "ldr r0, [%1, #4] \n\t" \
3189 "ldr r1, [%1, #8] \n\t" \
3190 "ldr r2, [%1, #12] \n\t" \
3191 "ldr r4, [%1] \n\t" /* target->r4 */ \
3192 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003193 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003194 "mov %0, r0\n" \
3195 : /*out*/ "=r" (_res) \
3196 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003197 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003198 ); \
3199 lval = (__typeof__(lval)) _res; \
3200 } while (0)
3201
3202#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3203 do { \
3204 volatile OrigFn _orig = (orig); \
3205 volatile unsigned long _argvec[5]; \
3206 volatile unsigned long _res; \
3207 _argvec[0] = (unsigned long)_orig.nraddr; \
3208 _argvec[1] = (unsigned long)(arg1); \
3209 _argvec[2] = (unsigned long)(arg2); \
3210 _argvec[3] = (unsigned long)(arg3); \
3211 _argvec[4] = (unsigned long)(arg4); \
3212 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003213 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003214 "ldr r0, [%1, #4] \n\t" \
3215 "ldr r1, [%1, #8] \n\t" \
3216 "ldr r2, [%1, #12] \n\t" \
3217 "ldr r3, [%1, #16] \n\t" \
3218 "ldr r4, [%1] \n\t" /* target->r4 */ \
3219 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003220 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003221 "mov %0, r0" \
3222 : /*out*/ "=r" (_res) \
3223 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003224 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003225 ); \
3226 lval = (__typeof__(lval)) _res; \
3227 } while (0)
3228
3229#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3230 do { \
3231 volatile OrigFn _orig = (orig); \
3232 volatile unsigned long _argvec[6]; \
3233 volatile unsigned long _res; \
3234 _argvec[0] = (unsigned long)_orig.nraddr; \
3235 _argvec[1] = (unsigned long)(arg1); \
3236 _argvec[2] = (unsigned long)(arg2); \
3237 _argvec[3] = (unsigned long)(arg3); \
3238 _argvec[4] = (unsigned long)(arg4); \
3239 _argvec[5] = (unsigned long)(arg5); \
3240 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003241 VALGRIND_ALIGN_STACK \
3242 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003243 "ldr r0, [%1, #20] \n\t" \
3244 "push {r0} \n\t" \
3245 "ldr r0, [%1, #4] \n\t" \
3246 "ldr r1, [%1, #8] \n\t" \
3247 "ldr r2, [%1, #12] \n\t" \
3248 "ldr r3, [%1, #16] \n\t" \
3249 "ldr r4, [%1] \n\t" /* target->r4 */ \
3250 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003251 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003252 "mov %0, r0" \
3253 : /*out*/ "=r" (_res) \
3254 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003255 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003256 ); \
3257 lval = (__typeof__(lval)) _res; \
3258 } while (0)
3259
3260#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3261 do { \
3262 volatile OrigFn _orig = (orig); \
3263 volatile unsigned long _argvec[7]; \
3264 volatile unsigned long _res; \
3265 _argvec[0] = (unsigned long)_orig.nraddr; \
3266 _argvec[1] = (unsigned long)(arg1); \
3267 _argvec[2] = (unsigned long)(arg2); \
3268 _argvec[3] = (unsigned long)(arg3); \
3269 _argvec[4] = (unsigned long)(arg4); \
3270 _argvec[5] = (unsigned long)(arg5); \
3271 _argvec[6] = (unsigned long)(arg6); \
3272 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003273 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003274 "ldr r0, [%1, #20] \n\t" \
3275 "ldr r1, [%1, #24] \n\t" \
3276 "push {r0, r1} \n\t" \
3277 "ldr r0, [%1, #4] \n\t" \
3278 "ldr r1, [%1, #8] \n\t" \
3279 "ldr r2, [%1, #12] \n\t" \
3280 "ldr r3, [%1, #16] \n\t" \
3281 "ldr r4, [%1] \n\t" /* target->r4 */ \
3282 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003283 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003284 "mov %0, r0" \
3285 : /*out*/ "=r" (_res) \
3286 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003287 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003288 ); \
3289 lval = (__typeof__(lval)) _res; \
3290 } while (0)
3291
3292#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3293 arg7) \
3294 do { \
3295 volatile OrigFn _orig = (orig); \
3296 volatile unsigned long _argvec[8]; \
3297 volatile unsigned long _res; \
3298 _argvec[0] = (unsigned long)_orig.nraddr; \
3299 _argvec[1] = (unsigned long)(arg1); \
3300 _argvec[2] = (unsigned long)(arg2); \
3301 _argvec[3] = (unsigned long)(arg3); \
3302 _argvec[4] = (unsigned long)(arg4); \
3303 _argvec[5] = (unsigned long)(arg5); \
3304 _argvec[6] = (unsigned long)(arg6); \
3305 _argvec[7] = (unsigned long)(arg7); \
3306 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003307 VALGRIND_ALIGN_STACK \
3308 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003309 "ldr r0, [%1, #20] \n\t" \
3310 "ldr r1, [%1, #24] \n\t" \
3311 "ldr r2, [%1, #28] \n\t" \
3312 "push {r0, r1, r2} \n\t" \
3313 "ldr r0, [%1, #4] \n\t" \
3314 "ldr r1, [%1, #8] \n\t" \
3315 "ldr r2, [%1, #12] \n\t" \
3316 "ldr r3, [%1, #16] \n\t" \
3317 "ldr r4, [%1] \n\t" /* target->r4 */ \
3318 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003319 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003320 "mov %0, r0" \
3321 : /*out*/ "=r" (_res) \
3322 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003323 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003324 ); \
3325 lval = (__typeof__(lval)) _res; \
3326 } while (0)
3327
3328#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3329 arg7,arg8) \
3330 do { \
3331 volatile OrigFn _orig = (orig); \
3332 volatile unsigned long _argvec[9]; \
3333 volatile unsigned long _res; \
3334 _argvec[0] = (unsigned long)_orig.nraddr; \
3335 _argvec[1] = (unsigned long)(arg1); \
3336 _argvec[2] = (unsigned long)(arg2); \
3337 _argvec[3] = (unsigned long)(arg3); \
3338 _argvec[4] = (unsigned long)(arg4); \
3339 _argvec[5] = (unsigned long)(arg5); \
3340 _argvec[6] = (unsigned long)(arg6); \
3341 _argvec[7] = (unsigned long)(arg7); \
3342 _argvec[8] = (unsigned long)(arg8); \
3343 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003344 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003345 "ldr r0, [%1, #20] \n\t" \
3346 "ldr r1, [%1, #24] \n\t" \
3347 "ldr r2, [%1, #28] \n\t" \
3348 "ldr r3, [%1, #32] \n\t" \
3349 "push {r0, r1, r2, r3} \n\t" \
3350 "ldr r0, [%1, #4] \n\t" \
3351 "ldr r1, [%1, #8] \n\t" \
3352 "ldr r2, [%1, #12] \n\t" \
3353 "ldr r3, [%1, #16] \n\t" \
3354 "ldr r4, [%1] \n\t" /* target->r4 */ \
3355 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003356 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003357 "mov %0, r0" \
3358 : /*out*/ "=r" (_res) \
3359 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003360 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003361 ); \
3362 lval = (__typeof__(lval)) _res; \
3363 } while (0)
3364
3365#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3366 arg7,arg8,arg9) \
3367 do { \
3368 volatile OrigFn _orig = (orig); \
3369 volatile unsigned long _argvec[10]; \
3370 volatile unsigned long _res; \
3371 _argvec[0] = (unsigned long)_orig.nraddr; \
3372 _argvec[1] = (unsigned long)(arg1); \
3373 _argvec[2] = (unsigned long)(arg2); \
3374 _argvec[3] = (unsigned long)(arg3); \
3375 _argvec[4] = (unsigned long)(arg4); \
3376 _argvec[5] = (unsigned long)(arg5); \
3377 _argvec[6] = (unsigned long)(arg6); \
3378 _argvec[7] = (unsigned long)(arg7); \
3379 _argvec[8] = (unsigned long)(arg8); \
3380 _argvec[9] = (unsigned long)(arg9); \
3381 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003382 VALGRIND_ALIGN_STACK \
3383 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003384 "ldr r0, [%1, #20] \n\t" \
3385 "ldr r1, [%1, #24] \n\t" \
3386 "ldr r2, [%1, #28] \n\t" \
3387 "ldr r3, [%1, #32] \n\t" \
3388 "ldr r4, [%1, #36] \n\t" \
3389 "push {r0, r1, r2, r3, r4} \n\t" \
3390 "ldr r0, [%1, #4] \n\t" \
3391 "ldr r1, [%1, #8] \n\t" \
3392 "ldr r2, [%1, #12] \n\t" \
3393 "ldr r3, [%1, #16] \n\t" \
3394 "ldr r4, [%1] \n\t" /* target->r4 */ \
3395 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003396 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003397 "mov %0, r0" \
3398 : /*out*/ "=r" (_res) \
3399 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003400 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003401 ); \
3402 lval = (__typeof__(lval)) _res; \
3403 } while (0)
3404
3405#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3406 arg7,arg8,arg9,arg10) \
3407 do { \
3408 volatile OrigFn _orig = (orig); \
3409 volatile unsigned long _argvec[11]; \
3410 volatile unsigned long _res; \
3411 _argvec[0] = (unsigned long)_orig.nraddr; \
3412 _argvec[1] = (unsigned long)(arg1); \
3413 _argvec[2] = (unsigned long)(arg2); \
3414 _argvec[3] = (unsigned long)(arg3); \
3415 _argvec[4] = (unsigned long)(arg4); \
3416 _argvec[5] = (unsigned long)(arg5); \
3417 _argvec[6] = (unsigned long)(arg6); \
3418 _argvec[7] = (unsigned long)(arg7); \
3419 _argvec[8] = (unsigned long)(arg8); \
3420 _argvec[9] = (unsigned long)(arg9); \
3421 _argvec[10] = (unsigned long)(arg10); \
3422 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003423 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003424 "ldr r0, [%1, #40] \n\t" \
3425 "push {r0} \n\t" \
3426 "ldr r0, [%1, #20] \n\t" \
3427 "ldr r1, [%1, #24] \n\t" \
3428 "ldr r2, [%1, #28] \n\t" \
3429 "ldr r3, [%1, #32] \n\t" \
3430 "ldr r4, [%1, #36] \n\t" \
3431 "push {r0, r1, r2, r3, r4} \n\t" \
3432 "ldr r0, [%1, #4] \n\t" \
3433 "ldr r1, [%1, #8] \n\t" \
3434 "ldr r2, [%1, #12] \n\t" \
3435 "ldr r3, [%1, #16] \n\t" \
3436 "ldr r4, [%1] \n\t" /* target->r4 */ \
3437 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003438 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003439 "mov %0, r0" \
3440 : /*out*/ "=r" (_res) \
3441 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003442 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003443 ); \
3444 lval = (__typeof__(lval)) _res; \
3445 } while (0)
3446
3447#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3448 arg6,arg7,arg8,arg9,arg10, \
3449 arg11) \
3450 do { \
3451 volatile OrigFn _orig = (orig); \
3452 volatile unsigned long _argvec[12]; \
3453 volatile unsigned long _res; \
3454 _argvec[0] = (unsigned long)_orig.nraddr; \
3455 _argvec[1] = (unsigned long)(arg1); \
3456 _argvec[2] = (unsigned long)(arg2); \
3457 _argvec[3] = (unsigned long)(arg3); \
3458 _argvec[4] = (unsigned long)(arg4); \
3459 _argvec[5] = (unsigned long)(arg5); \
3460 _argvec[6] = (unsigned long)(arg6); \
3461 _argvec[7] = (unsigned long)(arg7); \
3462 _argvec[8] = (unsigned long)(arg8); \
3463 _argvec[9] = (unsigned long)(arg9); \
3464 _argvec[10] = (unsigned long)(arg10); \
3465 _argvec[11] = (unsigned long)(arg11); \
3466 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003467 VALGRIND_ALIGN_STACK \
3468 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003469 "ldr r0, [%1, #40] \n\t" \
3470 "ldr r1, [%1, #44] \n\t" \
3471 "push {r0, r1} \n\t" \
3472 "ldr r0, [%1, #20] \n\t" \
3473 "ldr r1, [%1, #24] \n\t" \
3474 "ldr r2, [%1, #28] \n\t" \
3475 "ldr r3, [%1, #32] \n\t" \
3476 "ldr r4, [%1, #36] \n\t" \
3477 "push {r0, r1, r2, r3, r4} \n\t" \
3478 "ldr r0, [%1, #4] \n\t" \
3479 "ldr r1, [%1, #8] \n\t" \
3480 "ldr r2, [%1, #12] \n\t" \
3481 "ldr r3, [%1, #16] \n\t" \
3482 "ldr r4, [%1] \n\t" /* target->r4 */ \
3483 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003484 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003485 "mov %0, r0" \
3486 : /*out*/ "=r" (_res) \
3487 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003488 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003489 ); \
3490 lval = (__typeof__(lval)) _res; \
3491 } while (0)
3492
3493#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3494 arg6,arg7,arg8,arg9,arg10, \
3495 arg11,arg12) \
3496 do { \
3497 volatile OrigFn _orig = (orig); \
3498 volatile unsigned long _argvec[13]; \
3499 volatile unsigned long _res; \
3500 _argvec[0] = (unsigned long)_orig.nraddr; \
3501 _argvec[1] = (unsigned long)(arg1); \
3502 _argvec[2] = (unsigned long)(arg2); \
3503 _argvec[3] = (unsigned long)(arg3); \
3504 _argvec[4] = (unsigned long)(arg4); \
3505 _argvec[5] = (unsigned long)(arg5); \
3506 _argvec[6] = (unsigned long)(arg6); \
3507 _argvec[7] = (unsigned long)(arg7); \
3508 _argvec[8] = (unsigned long)(arg8); \
3509 _argvec[9] = (unsigned long)(arg9); \
3510 _argvec[10] = (unsigned long)(arg10); \
3511 _argvec[11] = (unsigned long)(arg11); \
3512 _argvec[12] = (unsigned long)(arg12); \
3513 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003514 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003515 "ldr r0, [%1, #40] \n\t" \
3516 "ldr r1, [%1, #44] \n\t" \
3517 "ldr r2, [%1, #48] \n\t" \
3518 "push {r0, r1, r2} \n\t" \
3519 "ldr r0, [%1, #20] \n\t" \
3520 "ldr r1, [%1, #24] \n\t" \
3521 "ldr r2, [%1, #28] \n\t" \
3522 "ldr r3, [%1, #32] \n\t" \
3523 "ldr r4, [%1, #36] \n\t" \
3524 "push {r0, r1, r2, r3, r4} \n\t" \
3525 "ldr r0, [%1, #4] \n\t" \
3526 "ldr r1, [%1, #8] \n\t" \
3527 "ldr r2, [%1, #12] \n\t" \
3528 "ldr r3, [%1, #16] \n\t" \
3529 "ldr r4, [%1] \n\t" /* target->r4 */ \
3530 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003531 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003532 "mov %0, r0" \
3533 : /*out*/ "=r" (_res) \
3534 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003535 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003536 ); \
3537 lval = (__typeof__(lval)) _res; \
3538 } while (0)
3539
3540#endif /* PLAT_arm_linux */
3541
sewardjf0c12502014-01-12 12:54:00 +00003542/* ------------------------ arm64-linux ------------------------ */
3543
3544#if defined(PLAT_arm64_linux)
3545
3546/* These regs are trashed by the hidden call. */
3547#define __CALLER_SAVED_REGS \
3548 "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
3549 "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
sewardjbb9b1b92014-03-09 09:46:04 +00003550 "x18", "x19", "x20", "x30", \
sewardjf0c12502014-01-12 12:54:00 +00003551 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
3552 "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
3553 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
3554 "v26", "v27", "v28", "v29", "v30", "v31"
3555
sewardjbb9b1b92014-03-09 09:46:04 +00003556/* x21 is callee-saved, so we can use it to save and restore SP around
3557 the hidden call. */
3558#define VALGRIND_ALIGN_STACK \
3559 "mov x21, sp\n\t" \
3560 "bic sp, x21, #15\n\t"
3561#define VALGRIND_RESTORE_STACK \
3562 "mov sp, x21\n\t"
sewardjf0c12502014-01-12 12:54:00 +00003563
3564/* These CALL_FN_ macros assume that on arm64-linux,
3565 sizeof(unsigned long) == 8. */
3566
3567#define CALL_FN_W_v(lval, orig) \
3568 do { \
3569 volatile OrigFn _orig = (orig); \
3570 volatile unsigned long _argvec[1]; \
3571 volatile unsigned long _res; \
3572 _argvec[0] = (unsigned long)_orig.nraddr; \
3573 __asm__ volatile( \
3574 VALGRIND_ALIGN_STACK \
3575 "ldr x8, [%1] \n\t" /* target->x8 */ \
3576 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3577 VALGRIND_RESTORE_STACK \
3578 "mov %0, x0\n" \
3579 : /*out*/ "=r" (_res) \
3580 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00003581 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003582 ); \
3583 lval = (__typeof__(lval)) _res; \
3584 } while (0)
3585
3586#define CALL_FN_W_W(lval, orig, arg1) \
3587 do { \
3588 volatile OrigFn _orig = (orig); \
3589 volatile unsigned long _argvec[2]; \
3590 volatile unsigned long _res; \
3591 _argvec[0] = (unsigned long)_orig.nraddr; \
3592 _argvec[1] = (unsigned long)(arg1); \
3593 __asm__ volatile( \
3594 VALGRIND_ALIGN_STACK \
3595 "ldr x0, [%1, #8] \n\t" \
3596 "ldr x8, [%1] \n\t" /* target->x8 */ \
3597 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3598 VALGRIND_RESTORE_STACK \
3599 "mov %0, x0\n" \
3600 : /*out*/ "=r" (_res) \
3601 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00003602 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003603 ); \
3604 lval = (__typeof__(lval)) _res; \
3605 } while (0)
3606
3607#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3608 do { \
3609 volatile OrigFn _orig = (orig); \
3610 volatile unsigned long _argvec[3]; \
3611 volatile unsigned long _res; \
3612 _argvec[0] = (unsigned long)_orig.nraddr; \
3613 _argvec[1] = (unsigned long)(arg1); \
3614 _argvec[2] = (unsigned long)(arg2); \
3615 __asm__ volatile( \
3616 VALGRIND_ALIGN_STACK \
3617 "ldr x0, [%1, #8] \n\t" \
3618 "ldr x1, [%1, #16] \n\t" \
3619 "ldr x8, [%1] \n\t" /* target->x8 */ \
3620 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3621 VALGRIND_RESTORE_STACK \
3622 "mov %0, x0\n" \
3623 : /*out*/ "=r" (_res) \
3624 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003625 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003626 ); \
3627 lval = (__typeof__(lval)) _res; \
3628 } while (0)
3629
3630#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3631 do { \
3632 volatile OrigFn _orig = (orig); \
3633 volatile unsigned long _argvec[4]; \
3634 volatile unsigned long _res; \
3635 _argvec[0] = (unsigned long)_orig.nraddr; \
3636 _argvec[1] = (unsigned long)(arg1); \
3637 _argvec[2] = (unsigned long)(arg2); \
3638 _argvec[3] = (unsigned long)(arg3); \
3639 __asm__ volatile( \
3640 VALGRIND_ALIGN_STACK \
3641 "ldr x0, [%1, #8] \n\t" \
3642 "ldr x1, [%1, #16] \n\t" \
3643 "ldr x2, [%1, #24] \n\t" \
3644 "ldr x8, [%1] \n\t" /* target->x8 */ \
3645 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3646 VALGRIND_RESTORE_STACK \
3647 "mov %0, x0\n" \
3648 : /*out*/ "=r" (_res) \
3649 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003650 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003651 ); \
3652 lval = (__typeof__(lval)) _res; \
3653 } while (0)
3654
3655#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3656 do { \
3657 volatile OrigFn _orig = (orig); \
3658 volatile unsigned long _argvec[5]; \
3659 volatile unsigned long _res; \
3660 _argvec[0] = (unsigned long)_orig.nraddr; \
3661 _argvec[1] = (unsigned long)(arg1); \
3662 _argvec[2] = (unsigned long)(arg2); \
3663 _argvec[3] = (unsigned long)(arg3); \
3664 _argvec[4] = (unsigned long)(arg4); \
3665 __asm__ volatile( \
3666 VALGRIND_ALIGN_STACK \
3667 "ldr x0, [%1, #8] \n\t" \
3668 "ldr x1, [%1, #16] \n\t" \
3669 "ldr x2, [%1, #24] \n\t" \
3670 "ldr x3, [%1, #32] \n\t" \
3671 "ldr x8, [%1] \n\t" /* target->x8 */ \
3672 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3673 VALGRIND_RESTORE_STACK \
3674 "mov %0, x0" \
3675 : /*out*/ "=r" (_res) \
3676 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003677 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3678 ); \
3679 lval = (__typeof__(lval)) _res; \
3680 } while (0)
3681
3682#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3683 do { \
3684 volatile OrigFn _orig = (orig); \
3685 volatile unsigned long _argvec[6]; \
3686 volatile unsigned long _res; \
3687 _argvec[0] = (unsigned long)_orig.nraddr; \
3688 _argvec[1] = (unsigned long)(arg1); \
3689 _argvec[2] = (unsigned long)(arg2); \
3690 _argvec[3] = (unsigned long)(arg3); \
3691 _argvec[4] = (unsigned long)(arg4); \
3692 _argvec[5] = (unsigned long)(arg5); \
3693 __asm__ volatile( \
3694 VALGRIND_ALIGN_STACK \
3695 "ldr x0, [%1, #8] \n\t" \
3696 "ldr x1, [%1, #16] \n\t" \
3697 "ldr x2, [%1, #24] \n\t" \
3698 "ldr x3, [%1, #32] \n\t" \
3699 "ldr x4, [%1, #40] \n\t" \
3700 "ldr x8, [%1] \n\t" /* target->x8 */ \
3701 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3702 VALGRIND_RESTORE_STACK \
3703 "mov %0, x0" \
3704 : /*out*/ "=r" (_res) \
3705 : /*in*/ "0" (&_argvec[0]) \
3706 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3707 ); \
3708 lval = (__typeof__(lval)) _res; \
3709 } while (0)
3710
3711#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3712 do { \
3713 volatile OrigFn _orig = (orig); \
3714 volatile unsigned long _argvec[7]; \
3715 volatile unsigned long _res; \
3716 _argvec[0] = (unsigned long)_orig.nraddr; \
3717 _argvec[1] = (unsigned long)(arg1); \
3718 _argvec[2] = (unsigned long)(arg2); \
3719 _argvec[3] = (unsigned long)(arg3); \
3720 _argvec[4] = (unsigned long)(arg4); \
3721 _argvec[5] = (unsigned long)(arg5); \
3722 _argvec[6] = (unsigned long)(arg6); \
3723 __asm__ volatile( \
3724 VALGRIND_ALIGN_STACK \
3725 "ldr x0, [%1, #8] \n\t" \
3726 "ldr x1, [%1, #16] \n\t" \
3727 "ldr x2, [%1, #24] \n\t" \
3728 "ldr x3, [%1, #32] \n\t" \
3729 "ldr x4, [%1, #40] \n\t" \
3730 "ldr x5, [%1, #48] \n\t" \
3731 "ldr x8, [%1] \n\t" /* target->x8 */ \
3732 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3733 VALGRIND_RESTORE_STACK \
3734 "mov %0, x0" \
3735 : /*out*/ "=r" (_res) \
3736 : /*in*/ "0" (&_argvec[0]) \
3737 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3738 ); \
3739 lval = (__typeof__(lval)) _res; \
3740 } while (0)
3741
3742#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3743 arg7) \
3744 do { \
3745 volatile OrigFn _orig = (orig); \
3746 volatile unsigned long _argvec[8]; \
3747 volatile unsigned long _res; \
3748 _argvec[0] = (unsigned long)_orig.nraddr; \
3749 _argvec[1] = (unsigned long)(arg1); \
3750 _argvec[2] = (unsigned long)(arg2); \
3751 _argvec[3] = (unsigned long)(arg3); \
3752 _argvec[4] = (unsigned long)(arg4); \
3753 _argvec[5] = (unsigned long)(arg5); \
3754 _argvec[6] = (unsigned long)(arg6); \
3755 _argvec[7] = (unsigned long)(arg7); \
3756 __asm__ volatile( \
3757 VALGRIND_ALIGN_STACK \
3758 "ldr x0, [%1, #8] \n\t" \
3759 "ldr x1, [%1, #16] \n\t" \
3760 "ldr x2, [%1, #24] \n\t" \
3761 "ldr x3, [%1, #32] \n\t" \
3762 "ldr x4, [%1, #40] \n\t" \
3763 "ldr x5, [%1, #48] \n\t" \
3764 "ldr x6, [%1, #56] \n\t" \
3765 "ldr x8, [%1] \n\t" /* target->x8 */ \
3766 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3767 VALGRIND_RESTORE_STACK \
3768 "mov %0, x0" \
3769 : /*out*/ "=r" (_res) \
3770 : /*in*/ "0" (&_argvec[0]) \
3771 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3772 ); \
3773 lval = (__typeof__(lval)) _res; \
3774 } while (0)
3775
3776#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3777 arg7,arg8) \
3778 do { \
3779 volatile OrigFn _orig = (orig); \
3780 volatile unsigned long _argvec[9]; \
3781 volatile unsigned long _res; \
3782 _argvec[0] = (unsigned long)_orig.nraddr; \
3783 _argvec[1] = (unsigned long)(arg1); \
3784 _argvec[2] = (unsigned long)(arg2); \
3785 _argvec[3] = (unsigned long)(arg3); \
3786 _argvec[4] = (unsigned long)(arg4); \
3787 _argvec[5] = (unsigned long)(arg5); \
3788 _argvec[6] = (unsigned long)(arg6); \
3789 _argvec[7] = (unsigned long)(arg7); \
3790 _argvec[8] = (unsigned long)(arg8); \
3791 __asm__ volatile( \
3792 VALGRIND_ALIGN_STACK \
3793 "ldr x0, [%1, #8] \n\t" \
3794 "ldr x1, [%1, #16] \n\t" \
3795 "ldr x2, [%1, #24] \n\t" \
3796 "ldr x3, [%1, #32] \n\t" \
3797 "ldr x4, [%1, #40] \n\t" \
3798 "ldr x5, [%1, #48] \n\t" \
3799 "ldr x6, [%1, #56] \n\t" \
3800 "ldr x7, [%1, #64] \n\t" \
3801 "ldr x8, [%1] \n\t" /* target->x8 */ \
3802 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3803 VALGRIND_RESTORE_STACK \
3804 "mov %0, x0" \
3805 : /*out*/ "=r" (_res) \
3806 : /*in*/ "0" (&_argvec[0]) \
3807 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3808 ); \
3809 lval = (__typeof__(lval)) _res; \
3810 } while (0)
3811
3812#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3813 arg7,arg8,arg9) \
3814 do { \
3815 volatile OrigFn _orig = (orig); \
3816 volatile unsigned long _argvec[10]; \
3817 volatile unsigned long _res; \
3818 _argvec[0] = (unsigned long)_orig.nraddr; \
3819 _argvec[1] = (unsigned long)(arg1); \
3820 _argvec[2] = (unsigned long)(arg2); \
3821 _argvec[3] = (unsigned long)(arg3); \
3822 _argvec[4] = (unsigned long)(arg4); \
3823 _argvec[5] = (unsigned long)(arg5); \
3824 _argvec[6] = (unsigned long)(arg6); \
3825 _argvec[7] = (unsigned long)(arg7); \
3826 _argvec[8] = (unsigned long)(arg8); \
3827 _argvec[9] = (unsigned long)(arg9); \
3828 __asm__ volatile( \
3829 VALGRIND_ALIGN_STACK \
3830 "sub sp, sp, #0x20 \n\t" \
3831 "ldr x0, [%1, #8] \n\t" \
3832 "ldr x1, [%1, #16] \n\t" \
3833 "ldr x2, [%1, #24] \n\t" \
3834 "ldr x3, [%1, #32] \n\t" \
3835 "ldr x4, [%1, #40] \n\t" \
3836 "ldr x5, [%1, #48] \n\t" \
3837 "ldr x6, [%1, #56] \n\t" \
3838 "ldr x7, [%1, #64] \n\t" \
3839 "ldr x8, [%1, #72] \n\t" \
3840 "str x8, [sp, #0] \n\t" \
3841 "ldr x8, [%1] \n\t" /* target->x8 */ \
3842 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3843 VALGRIND_RESTORE_STACK \
3844 "mov %0, x0" \
3845 : /*out*/ "=r" (_res) \
3846 : /*in*/ "0" (&_argvec[0]) \
3847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3848 ); \
3849 lval = (__typeof__(lval)) _res; \
3850 } while (0)
3851
3852#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3853 arg7,arg8,arg9,arg10) \
3854 do { \
3855 volatile OrigFn _orig = (orig); \
3856 volatile unsigned long _argvec[11]; \
3857 volatile unsigned long _res; \
3858 _argvec[0] = (unsigned long)_orig.nraddr; \
3859 _argvec[1] = (unsigned long)(arg1); \
3860 _argvec[2] = (unsigned long)(arg2); \
3861 _argvec[3] = (unsigned long)(arg3); \
3862 _argvec[4] = (unsigned long)(arg4); \
3863 _argvec[5] = (unsigned long)(arg5); \
3864 _argvec[6] = (unsigned long)(arg6); \
3865 _argvec[7] = (unsigned long)(arg7); \
3866 _argvec[8] = (unsigned long)(arg8); \
3867 _argvec[9] = (unsigned long)(arg9); \
3868 _argvec[10] = (unsigned long)(arg10); \
3869 __asm__ volatile( \
3870 VALGRIND_ALIGN_STACK \
3871 "sub sp, sp, #0x20 \n\t" \
3872 "ldr x0, [%1, #8] \n\t" \
3873 "ldr x1, [%1, #16] \n\t" \
3874 "ldr x2, [%1, #24] \n\t" \
3875 "ldr x3, [%1, #32] \n\t" \
3876 "ldr x4, [%1, #40] \n\t" \
3877 "ldr x5, [%1, #48] \n\t" \
3878 "ldr x6, [%1, #56] \n\t" \
3879 "ldr x7, [%1, #64] \n\t" \
3880 "ldr x8, [%1, #72] \n\t" \
3881 "str x8, [sp, #0] \n\t" \
3882 "ldr x8, [%1, #80] \n\t" \
3883 "str x8, [sp, #8] \n\t" \
3884 "ldr x8, [%1] \n\t" /* target->x8 */ \
3885 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3886 VALGRIND_RESTORE_STACK \
3887 "mov %0, x0" \
3888 : /*out*/ "=r" (_res) \
3889 : /*in*/ "0" (&_argvec[0]) \
3890 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3891 ); \
3892 lval = (__typeof__(lval)) _res; \
3893 } while (0)
3894
3895#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3896 arg7,arg8,arg9,arg10,arg11) \
3897 do { \
3898 volatile OrigFn _orig = (orig); \
3899 volatile unsigned long _argvec[12]; \
3900 volatile unsigned long _res; \
3901 _argvec[0] = (unsigned long)_orig.nraddr; \
3902 _argvec[1] = (unsigned long)(arg1); \
3903 _argvec[2] = (unsigned long)(arg2); \
3904 _argvec[3] = (unsigned long)(arg3); \
3905 _argvec[4] = (unsigned long)(arg4); \
3906 _argvec[5] = (unsigned long)(arg5); \
3907 _argvec[6] = (unsigned long)(arg6); \
3908 _argvec[7] = (unsigned long)(arg7); \
3909 _argvec[8] = (unsigned long)(arg8); \
3910 _argvec[9] = (unsigned long)(arg9); \
3911 _argvec[10] = (unsigned long)(arg10); \
3912 _argvec[11] = (unsigned long)(arg11); \
3913 __asm__ volatile( \
3914 VALGRIND_ALIGN_STACK \
3915 "sub sp, sp, #0x30 \n\t" \
3916 "ldr x0, [%1, #8] \n\t" \
3917 "ldr x1, [%1, #16] \n\t" \
3918 "ldr x2, [%1, #24] \n\t" \
3919 "ldr x3, [%1, #32] \n\t" \
3920 "ldr x4, [%1, #40] \n\t" \
3921 "ldr x5, [%1, #48] \n\t" \
3922 "ldr x6, [%1, #56] \n\t" \
3923 "ldr x7, [%1, #64] \n\t" \
3924 "ldr x8, [%1, #72] \n\t" \
3925 "str x8, [sp, #0] \n\t" \
3926 "ldr x8, [%1, #80] \n\t" \
3927 "str x8, [sp, #8] \n\t" \
3928 "ldr x8, [%1, #88] \n\t" \
3929 "str x8, [sp, #16] \n\t" \
3930 "ldr x8, [%1] \n\t" /* target->x8 */ \
3931 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3932 VALGRIND_RESTORE_STACK \
3933 "mov %0, x0" \
3934 : /*out*/ "=r" (_res) \
3935 : /*in*/ "0" (&_argvec[0]) \
3936 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3937 ); \
3938 lval = (__typeof__(lval)) _res; \
3939 } while (0)
3940
3941#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3942 arg7,arg8,arg9,arg10,arg11, \
3943 arg12) \
3944 do { \
3945 volatile OrigFn _orig = (orig); \
3946 volatile unsigned long _argvec[13]; \
3947 volatile unsigned long _res; \
3948 _argvec[0] = (unsigned long)_orig.nraddr; \
3949 _argvec[1] = (unsigned long)(arg1); \
3950 _argvec[2] = (unsigned long)(arg2); \
3951 _argvec[3] = (unsigned long)(arg3); \
3952 _argvec[4] = (unsigned long)(arg4); \
3953 _argvec[5] = (unsigned long)(arg5); \
3954 _argvec[6] = (unsigned long)(arg6); \
3955 _argvec[7] = (unsigned long)(arg7); \
3956 _argvec[8] = (unsigned long)(arg8); \
3957 _argvec[9] = (unsigned long)(arg9); \
3958 _argvec[10] = (unsigned long)(arg10); \
3959 _argvec[11] = (unsigned long)(arg11); \
3960 _argvec[12] = (unsigned long)(arg12); \
3961 __asm__ volatile( \
3962 VALGRIND_ALIGN_STACK \
3963 "sub sp, sp, #0x30 \n\t" \
3964 "ldr x0, [%1, #8] \n\t" \
3965 "ldr x1, [%1, #16] \n\t" \
3966 "ldr x2, [%1, #24] \n\t" \
3967 "ldr x3, [%1, #32] \n\t" \
3968 "ldr x4, [%1, #40] \n\t" \
3969 "ldr x5, [%1, #48] \n\t" \
3970 "ldr x6, [%1, #56] \n\t" \
3971 "ldr x7, [%1, #64] \n\t" \
3972 "ldr x8, [%1, #72] \n\t" \
3973 "str x8, [sp, #0] \n\t" \
3974 "ldr x8, [%1, #80] \n\t" \
3975 "str x8, [sp, #8] \n\t" \
3976 "ldr x8, [%1, #88] \n\t" \
3977 "str x8, [sp, #16] \n\t" \
3978 "ldr x8, [%1, #96] \n\t" \
3979 "str x8, [sp, #24] \n\t" \
3980 "ldr x8, [%1] \n\t" /* target->x8 */ \
3981 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3982 VALGRIND_RESTORE_STACK \
3983 "mov %0, x0" \
3984 : /*out*/ "=r" (_res) \
3985 : /*in*/ "0" (&_argvec[0]) \
3986 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003987 ); \
3988 lval = (__typeof__(lval)) _res; \
3989 } while (0)
3990
3991#endif /* PLAT_arm64_linux */
3992
sewardjb5b87402011-03-07 16:05:35 +00003993/* ------------------------- s390x-linux ------------------------- */
3994
3995#if defined(PLAT_s390x_linux)
3996
3997/* Similar workaround as amd64 (see above), but we use r11 as frame
3998 pointer and save the old r11 in r7. r11 might be used for
3999 argvec, therefore we copy argvec in r1 since r1 is clobbered
4000 after the call anyway. */
4001#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4002# define __FRAME_POINTER \
4003 ,"d"(__builtin_dwarf_cfa())
4004# define VALGRIND_CFI_PROLOGUE \
4005 ".cfi_remember_state\n\t" \
4006 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
4007 "lgr 7,11\n\t" \
4008 "lgr 11,%2\n\t" \
4009 ".cfi_def_cfa r11, 0\n\t"
4010# define VALGRIND_CFI_EPILOGUE \
4011 "lgr 11, 7\n\t" \
4012 ".cfi_restore_state\n\t"
4013#else
4014# define __FRAME_POINTER
4015# define VALGRIND_CFI_PROLOGUE \
4016 "lgr 1,%1\n\t"
4017# define VALGRIND_CFI_EPILOGUE
4018#endif
4019
florian9af940f2012-08-03 03:21:42 +00004020/* Nb: On s390 the stack pointer is properly aligned *at all times*
4021 according to the s390 GCC maintainer. (The ABI specification is not
4022 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4023 VALGRIND_RESTORE_STACK are not defined here. */
sewardjb5b87402011-03-07 16:05:35 +00004024
4025/* These regs are trashed by the hidden call. Note that we overwrite
4026 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4027 function a proper return address. All others are ABI defined call
4028 clobbers. */
4029#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4030 "f0","f1","f2","f3","f4","f5","f6","f7"
4031
florian9af940f2012-08-03 03:21:42 +00004032/* Nb: Although r11 is modified in the asm snippets below (inside
4033 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4034 two reasons:
4035 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4036 modified
4037 (2) GCC will complain that r11 cannot appear inside a clobber section,
4038 when compiled with -O -fno-omit-frame-pointer
4039 */
sewardjb5b87402011-03-07 16:05:35 +00004040
4041#define CALL_FN_W_v(lval, orig) \
4042 do { \
4043 volatile OrigFn _orig = (orig); \
4044 volatile unsigned long _argvec[1]; \
4045 volatile unsigned long _res; \
4046 _argvec[0] = (unsigned long)_orig.nraddr; \
4047 __asm__ volatile( \
4048 VALGRIND_CFI_PROLOGUE \
4049 "aghi 15,-160\n\t" \
4050 "lg 1, 0(1)\n\t" /* target->r1 */ \
4051 VALGRIND_CALL_NOREDIR_R1 \
4052 "lgr %0, 2\n\t" \
4053 "aghi 15,160\n\t" \
4054 VALGRIND_CFI_EPILOGUE \
4055 : /*out*/ "=d" (_res) \
4056 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
4057 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4058 ); \
4059 lval = (__typeof__(lval)) _res; \
4060 } while (0)
4061
4062/* The call abi has the arguments in r2-r6 and stack */
4063#define CALL_FN_W_W(lval, orig, arg1) \
4064 do { \
4065 volatile OrigFn _orig = (orig); \
4066 volatile unsigned long _argvec[2]; \
4067 volatile unsigned long _res; \
4068 _argvec[0] = (unsigned long)_orig.nraddr; \
4069 _argvec[1] = (unsigned long)arg1; \
4070 __asm__ volatile( \
4071 VALGRIND_CFI_PROLOGUE \
4072 "aghi 15,-160\n\t" \
4073 "lg 2, 8(1)\n\t" \
4074 "lg 1, 0(1)\n\t" \
4075 VALGRIND_CALL_NOREDIR_R1 \
4076 "lgr %0, 2\n\t" \
4077 "aghi 15,160\n\t" \
4078 VALGRIND_CFI_EPILOGUE \
4079 : /*out*/ "=d" (_res) \
4080 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4081 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4082 ); \
4083 lval = (__typeof__(lval)) _res; \
4084 } while (0)
4085
4086#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
4087 do { \
4088 volatile OrigFn _orig = (orig); \
4089 volatile unsigned long _argvec[3]; \
4090 volatile unsigned long _res; \
4091 _argvec[0] = (unsigned long)_orig.nraddr; \
4092 _argvec[1] = (unsigned long)arg1; \
4093 _argvec[2] = (unsigned long)arg2; \
4094 __asm__ volatile( \
4095 VALGRIND_CFI_PROLOGUE \
4096 "aghi 15,-160\n\t" \
4097 "lg 2, 8(1)\n\t" \
4098 "lg 3,16(1)\n\t" \
4099 "lg 1, 0(1)\n\t" \
4100 VALGRIND_CALL_NOREDIR_R1 \
4101 "lgr %0, 2\n\t" \
4102 "aghi 15,160\n\t" \
4103 VALGRIND_CFI_EPILOGUE \
4104 : /*out*/ "=d" (_res) \
4105 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4106 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4107 ); \
4108 lval = (__typeof__(lval)) _res; \
4109 } while (0)
4110
4111#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
4112 do { \
4113 volatile OrigFn _orig = (orig); \
4114 volatile unsigned long _argvec[4]; \
4115 volatile unsigned long _res; \
4116 _argvec[0] = (unsigned long)_orig.nraddr; \
4117 _argvec[1] = (unsigned long)arg1; \
4118 _argvec[2] = (unsigned long)arg2; \
4119 _argvec[3] = (unsigned long)arg3; \
4120 __asm__ volatile( \
4121 VALGRIND_CFI_PROLOGUE \
4122 "aghi 15,-160\n\t" \
4123 "lg 2, 8(1)\n\t" \
4124 "lg 3,16(1)\n\t" \
4125 "lg 4,24(1)\n\t" \
4126 "lg 1, 0(1)\n\t" \
4127 VALGRIND_CALL_NOREDIR_R1 \
4128 "lgr %0, 2\n\t" \
4129 "aghi 15,160\n\t" \
4130 VALGRIND_CFI_EPILOGUE \
4131 : /*out*/ "=d" (_res) \
4132 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4133 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4134 ); \
4135 lval = (__typeof__(lval)) _res; \
4136 } while (0)
4137
4138#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
4139 do { \
4140 volatile OrigFn _orig = (orig); \
4141 volatile unsigned long _argvec[5]; \
4142 volatile unsigned long _res; \
4143 _argvec[0] = (unsigned long)_orig.nraddr; \
4144 _argvec[1] = (unsigned long)arg1; \
4145 _argvec[2] = (unsigned long)arg2; \
4146 _argvec[3] = (unsigned long)arg3; \
4147 _argvec[4] = (unsigned long)arg4; \
4148 __asm__ volatile( \
4149 VALGRIND_CFI_PROLOGUE \
4150 "aghi 15,-160\n\t" \
4151 "lg 2, 8(1)\n\t" \
4152 "lg 3,16(1)\n\t" \
4153 "lg 4,24(1)\n\t" \
4154 "lg 5,32(1)\n\t" \
4155 "lg 1, 0(1)\n\t" \
4156 VALGRIND_CALL_NOREDIR_R1 \
4157 "lgr %0, 2\n\t" \
4158 "aghi 15,160\n\t" \
4159 VALGRIND_CFI_EPILOGUE \
4160 : /*out*/ "=d" (_res) \
4161 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4162 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4163 ); \
4164 lval = (__typeof__(lval)) _res; \
4165 } while (0)
4166
4167#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
4168 do { \
4169 volatile OrigFn _orig = (orig); \
4170 volatile unsigned long _argvec[6]; \
4171 volatile unsigned long _res; \
4172 _argvec[0] = (unsigned long)_orig.nraddr; \
4173 _argvec[1] = (unsigned long)arg1; \
4174 _argvec[2] = (unsigned long)arg2; \
4175 _argvec[3] = (unsigned long)arg3; \
4176 _argvec[4] = (unsigned long)arg4; \
4177 _argvec[5] = (unsigned long)arg5; \
4178 __asm__ volatile( \
4179 VALGRIND_CFI_PROLOGUE \
4180 "aghi 15,-160\n\t" \
4181 "lg 2, 8(1)\n\t" \
4182 "lg 3,16(1)\n\t" \
4183 "lg 4,24(1)\n\t" \
4184 "lg 5,32(1)\n\t" \
4185 "lg 6,40(1)\n\t" \
4186 "lg 1, 0(1)\n\t" \
4187 VALGRIND_CALL_NOREDIR_R1 \
4188 "lgr %0, 2\n\t" \
4189 "aghi 15,160\n\t" \
4190 VALGRIND_CFI_EPILOGUE \
4191 : /*out*/ "=d" (_res) \
4192 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4193 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4194 ); \
4195 lval = (__typeof__(lval)) _res; \
4196 } while (0)
4197
4198#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4199 arg6) \
4200 do { \
4201 volatile OrigFn _orig = (orig); \
4202 volatile unsigned long _argvec[7]; \
4203 volatile unsigned long _res; \
4204 _argvec[0] = (unsigned long)_orig.nraddr; \
4205 _argvec[1] = (unsigned long)arg1; \
4206 _argvec[2] = (unsigned long)arg2; \
4207 _argvec[3] = (unsigned long)arg3; \
4208 _argvec[4] = (unsigned long)arg4; \
4209 _argvec[5] = (unsigned long)arg5; \
4210 _argvec[6] = (unsigned long)arg6; \
4211 __asm__ volatile( \
4212 VALGRIND_CFI_PROLOGUE \
4213 "aghi 15,-168\n\t" \
4214 "lg 2, 8(1)\n\t" \
4215 "lg 3,16(1)\n\t" \
4216 "lg 4,24(1)\n\t" \
4217 "lg 5,32(1)\n\t" \
4218 "lg 6,40(1)\n\t" \
4219 "mvc 160(8,15), 48(1)\n\t" \
4220 "lg 1, 0(1)\n\t" \
4221 VALGRIND_CALL_NOREDIR_R1 \
4222 "lgr %0, 2\n\t" \
4223 "aghi 15,168\n\t" \
4224 VALGRIND_CFI_EPILOGUE \
4225 : /*out*/ "=d" (_res) \
4226 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4227 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4228 ); \
4229 lval = (__typeof__(lval)) _res; \
4230 } while (0)
4231
4232#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4233 arg6, arg7) \
4234 do { \
4235 volatile OrigFn _orig = (orig); \
4236 volatile unsigned long _argvec[8]; \
4237 volatile unsigned long _res; \
4238 _argvec[0] = (unsigned long)_orig.nraddr; \
4239 _argvec[1] = (unsigned long)arg1; \
4240 _argvec[2] = (unsigned long)arg2; \
4241 _argvec[3] = (unsigned long)arg3; \
4242 _argvec[4] = (unsigned long)arg4; \
4243 _argvec[5] = (unsigned long)arg5; \
4244 _argvec[6] = (unsigned long)arg6; \
4245 _argvec[7] = (unsigned long)arg7; \
4246 __asm__ volatile( \
4247 VALGRIND_CFI_PROLOGUE \
4248 "aghi 15,-176\n\t" \
4249 "lg 2, 8(1)\n\t" \
4250 "lg 3,16(1)\n\t" \
4251 "lg 4,24(1)\n\t" \
4252 "lg 5,32(1)\n\t" \
4253 "lg 6,40(1)\n\t" \
4254 "mvc 160(8,15), 48(1)\n\t" \
4255 "mvc 168(8,15), 56(1)\n\t" \
4256 "lg 1, 0(1)\n\t" \
4257 VALGRIND_CALL_NOREDIR_R1 \
4258 "lgr %0, 2\n\t" \
4259 "aghi 15,176\n\t" \
4260 VALGRIND_CFI_EPILOGUE \
4261 : /*out*/ "=d" (_res) \
4262 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4264 ); \
4265 lval = (__typeof__(lval)) _res; \
4266 } while (0)
4267
4268#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4269 arg6, arg7 ,arg8) \
4270 do { \
4271 volatile OrigFn _orig = (orig); \
4272 volatile unsigned long _argvec[9]; \
4273 volatile unsigned long _res; \
4274 _argvec[0] = (unsigned long)_orig.nraddr; \
4275 _argvec[1] = (unsigned long)arg1; \
4276 _argvec[2] = (unsigned long)arg2; \
4277 _argvec[3] = (unsigned long)arg3; \
4278 _argvec[4] = (unsigned long)arg4; \
4279 _argvec[5] = (unsigned long)arg5; \
4280 _argvec[6] = (unsigned long)arg6; \
4281 _argvec[7] = (unsigned long)arg7; \
4282 _argvec[8] = (unsigned long)arg8; \
4283 __asm__ volatile( \
4284 VALGRIND_CFI_PROLOGUE \
4285 "aghi 15,-184\n\t" \
4286 "lg 2, 8(1)\n\t" \
4287 "lg 3,16(1)\n\t" \
4288 "lg 4,24(1)\n\t" \
4289 "lg 5,32(1)\n\t" \
4290 "lg 6,40(1)\n\t" \
4291 "mvc 160(8,15), 48(1)\n\t" \
4292 "mvc 168(8,15), 56(1)\n\t" \
4293 "mvc 176(8,15), 64(1)\n\t" \
4294 "lg 1, 0(1)\n\t" \
4295 VALGRIND_CALL_NOREDIR_R1 \
4296 "lgr %0, 2\n\t" \
4297 "aghi 15,184\n\t" \
4298 VALGRIND_CFI_EPILOGUE \
4299 : /*out*/ "=d" (_res) \
4300 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4301 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4302 ); \
4303 lval = (__typeof__(lval)) _res; \
4304 } while (0)
4305
4306#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4307 arg6, arg7 ,arg8, arg9) \
4308 do { \
4309 volatile OrigFn _orig = (orig); \
4310 volatile unsigned long _argvec[10]; \
4311 volatile unsigned long _res; \
4312 _argvec[0] = (unsigned long)_orig.nraddr; \
4313 _argvec[1] = (unsigned long)arg1; \
4314 _argvec[2] = (unsigned long)arg2; \
4315 _argvec[3] = (unsigned long)arg3; \
4316 _argvec[4] = (unsigned long)arg4; \
4317 _argvec[5] = (unsigned long)arg5; \
4318 _argvec[6] = (unsigned long)arg6; \
4319 _argvec[7] = (unsigned long)arg7; \
4320 _argvec[8] = (unsigned long)arg8; \
4321 _argvec[9] = (unsigned long)arg9; \
4322 __asm__ volatile( \
4323 VALGRIND_CFI_PROLOGUE \
4324 "aghi 15,-192\n\t" \
4325 "lg 2, 8(1)\n\t" \
4326 "lg 3,16(1)\n\t" \
4327 "lg 4,24(1)\n\t" \
4328 "lg 5,32(1)\n\t" \
4329 "lg 6,40(1)\n\t" \
4330 "mvc 160(8,15), 48(1)\n\t" \
4331 "mvc 168(8,15), 56(1)\n\t" \
4332 "mvc 176(8,15), 64(1)\n\t" \
4333 "mvc 184(8,15), 72(1)\n\t" \
4334 "lg 1, 0(1)\n\t" \
4335 VALGRIND_CALL_NOREDIR_R1 \
4336 "lgr %0, 2\n\t" \
4337 "aghi 15,192\n\t" \
4338 VALGRIND_CFI_EPILOGUE \
4339 : /*out*/ "=d" (_res) \
4340 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4341 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4342 ); \
4343 lval = (__typeof__(lval)) _res; \
4344 } while (0)
4345
4346#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4347 arg6, arg7 ,arg8, arg9, arg10) \
4348 do { \
4349 volatile OrigFn _orig = (orig); \
4350 volatile unsigned long _argvec[11]; \
4351 volatile unsigned long _res; \
4352 _argvec[0] = (unsigned long)_orig.nraddr; \
4353 _argvec[1] = (unsigned long)arg1; \
4354 _argvec[2] = (unsigned long)arg2; \
4355 _argvec[3] = (unsigned long)arg3; \
4356 _argvec[4] = (unsigned long)arg4; \
4357 _argvec[5] = (unsigned long)arg5; \
4358 _argvec[6] = (unsigned long)arg6; \
4359 _argvec[7] = (unsigned long)arg7; \
4360 _argvec[8] = (unsigned long)arg8; \
4361 _argvec[9] = (unsigned long)arg9; \
4362 _argvec[10] = (unsigned long)arg10; \
4363 __asm__ volatile( \
4364 VALGRIND_CFI_PROLOGUE \
4365 "aghi 15,-200\n\t" \
4366 "lg 2, 8(1)\n\t" \
4367 "lg 3,16(1)\n\t" \
4368 "lg 4,24(1)\n\t" \
4369 "lg 5,32(1)\n\t" \
4370 "lg 6,40(1)\n\t" \
4371 "mvc 160(8,15), 48(1)\n\t" \
4372 "mvc 168(8,15), 56(1)\n\t" \
4373 "mvc 176(8,15), 64(1)\n\t" \
4374 "mvc 184(8,15), 72(1)\n\t" \
4375 "mvc 192(8,15), 80(1)\n\t" \
4376 "lg 1, 0(1)\n\t" \
4377 VALGRIND_CALL_NOREDIR_R1 \
4378 "lgr %0, 2\n\t" \
4379 "aghi 15,200\n\t" \
4380 VALGRIND_CFI_EPILOGUE \
4381 : /*out*/ "=d" (_res) \
4382 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4383 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4384 ); \
4385 lval = (__typeof__(lval)) _res; \
4386 } while (0)
4387
4388#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4389 arg6, arg7 ,arg8, arg9, arg10, arg11) \
4390 do { \
4391 volatile OrigFn _orig = (orig); \
4392 volatile unsigned long _argvec[12]; \
4393 volatile unsigned long _res; \
4394 _argvec[0] = (unsigned long)_orig.nraddr; \
4395 _argvec[1] = (unsigned long)arg1; \
4396 _argvec[2] = (unsigned long)arg2; \
4397 _argvec[3] = (unsigned long)arg3; \
4398 _argvec[4] = (unsigned long)arg4; \
4399 _argvec[5] = (unsigned long)arg5; \
4400 _argvec[6] = (unsigned long)arg6; \
4401 _argvec[7] = (unsigned long)arg7; \
4402 _argvec[8] = (unsigned long)arg8; \
4403 _argvec[9] = (unsigned long)arg9; \
4404 _argvec[10] = (unsigned long)arg10; \
4405 _argvec[11] = (unsigned long)arg11; \
4406 __asm__ volatile( \
4407 VALGRIND_CFI_PROLOGUE \
4408 "aghi 15,-208\n\t" \
4409 "lg 2, 8(1)\n\t" \
4410 "lg 3,16(1)\n\t" \
4411 "lg 4,24(1)\n\t" \
4412 "lg 5,32(1)\n\t" \
4413 "lg 6,40(1)\n\t" \
4414 "mvc 160(8,15), 48(1)\n\t" \
4415 "mvc 168(8,15), 56(1)\n\t" \
4416 "mvc 176(8,15), 64(1)\n\t" \
4417 "mvc 184(8,15), 72(1)\n\t" \
4418 "mvc 192(8,15), 80(1)\n\t" \
4419 "mvc 200(8,15), 88(1)\n\t" \
4420 "lg 1, 0(1)\n\t" \
4421 VALGRIND_CALL_NOREDIR_R1 \
4422 "lgr %0, 2\n\t" \
4423 "aghi 15,208\n\t" \
4424 VALGRIND_CFI_EPILOGUE \
4425 : /*out*/ "=d" (_res) \
4426 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4427 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4428 ); \
4429 lval = (__typeof__(lval)) _res; \
4430 } while (0)
4431
4432#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4433 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
4434 do { \
4435 volatile OrigFn _orig = (orig); \
4436 volatile unsigned long _argvec[13]; \
4437 volatile unsigned long _res; \
4438 _argvec[0] = (unsigned long)_orig.nraddr; \
4439 _argvec[1] = (unsigned long)arg1; \
4440 _argvec[2] = (unsigned long)arg2; \
4441 _argvec[3] = (unsigned long)arg3; \
4442 _argvec[4] = (unsigned long)arg4; \
4443 _argvec[5] = (unsigned long)arg5; \
4444 _argvec[6] = (unsigned long)arg6; \
4445 _argvec[7] = (unsigned long)arg7; \
4446 _argvec[8] = (unsigned long)arg8; \
4447 _argvec[9] = (unsigned long)arg9; \
4448 _argvec[10] = (unsigned long)arg10; \
4449 _argvec[11] = (unsigned long)arg11; \
4450 _argvec[12] = (unsigned long)arg12; \
4451 __asm__ volatile( \
4452 VALGRIND_CFI_PROLOGUE \
4453 "aghi 15,-216\n\t" \
4454 "lg 2, 8(1)\n\t" \
4455 "lg 3,16(1)\n\t" \
4456 "lg 4,24(1)\n\t" \
4457 "lg 5,32(1)\n\t" \
4458 "lg 6,40(1)\n\t" \
4459 "mvc 160(8,15), 48(1)\n\t" \
4460 "mvc 168(8,15), 56(1)\n\t" \
4461 "mvc 176(8,15), 64(1)\n\t" \
4462 "mvc 184(8,15), 72(1)\n\t" \
4463 "mvc 192(8,15), 80(1)\n\t" \
4464 "mvc 200(8,15), 88(1)\n\t" \
4465 "mvc 208(8,15), 96(1)\n\t" \
4466 "lg 1, 0(1)\n\t" \
4467 VALGRIND_CALL_NOREDIR_R1 \
4468 "lgr %0, 2\n\t" \
4469 "aghi 15,216\n\t" \
4470 VALGRIND_CFI_EPILOGUE \
4471 : /*out*/ "=d" (_res) \
4472 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4473 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4474 ); \
4475 lval = (__typeof__(lval)) _res; \
4476 } while (0)
4477
4478
4479#endif /* PLAT_s390x_linux */
4480
petarj4df0bfc2013-02-27 23:17:33 +00004481/* ------------------------- mips32-linux ----------------------- */
sewardj5db15402012-06-07 09:13:21 +00004482
4483#if defined(PLAT_mips32_linux)
4484
4485/* These regs are trashed by the hidden call. */
4486#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
4487"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
4488"$25", "$31"
4489
4490/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
4491 long) == 4. */
4492
4493#define CALL_FN_W_v(lval, orig) \
4494 do { \
4495 volatile OrigFn _orig = (orig); \
4496 volatile unsigned long _argvec[1]; \
4497 volatile unsigned long _res; \
4498 _argvec[0] = (unsigned long)_orig.nraddr; \
4499 __asm__ volatile( \
4500 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004501 "sw $28, 0($29) \n\t" \
4502 "sw $31, 4($29) \n\t" \
4503 "subu $29, $29, 16 \n\t" \
4504 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004505 VALGRIND_CALL_NOREDIR_T9 \
4506 "addu $29, $29, 16\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004507 "lw $28, 0($29) \n\t" \
4508 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004509 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004510 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004511 : /*out*/ "=r" (_res) \
4512 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004513 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004514 ); \
4515 lval = (__typeof__(lval)) _res; \
4516 } while (0)
4517
4518#define CALL_FN_W_W(lval, orig, arg1) \
4519 do { \
4520 volatile OrigFn _orig = (orig); \
4521 volatile unsigned long _argvec[2]; \
4522 volatile unsigned long _res; \
4523 _argvec[0] = (unsigned long)_orig.nraddr; \
4524 _argvec[1] = (unsigned long)(arg1); \
4525 __asm__ volatile( \
4526 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004527 "sw $28, 0($29) \n\t" \
4528 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004529 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004530 "lw $4, 4(%1) \n\t" /* arg1*/ \
4531 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004532 VALGRIND_CALL_NOREDIR_T9 \
4533 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004534 "lw $28, 0($29) \n\t" \
4535 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004536 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004537 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004538 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00004539 : /*in*/ "0" (&_argvec[0]) \
4540 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004541 ); \
4542 lval = (__typeof__(lval)) _res; \
4543 } while (0)
4544
4545#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
4546 do { \
4547 volatile OrigFn _orig = (orig); \
4548 volatile unsigned long _argvec[3]; \
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 __asm__ volatile( \
4554 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004555 "sw $28, 0($29) \n\t" \
4556 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004557 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004558 "lw $4, 4(%1) \n\t" \
4559 "lw $5, 8(%1) \n\t" \
4560 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004561 VALGRIND_CALL_NOREDIR_T9 \
4562 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004563 "lw $28, 0($29) \n\t" \
4564 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004565 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004566 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004567 : /*out*/ "=r" (_res) \
4568 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004569 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004570 ); \
4571 lval = (__typeof__(lval)) _res; \
4572 } while (0)
4573
4574#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
4575 do { \
4576 volatile OrigFn _orig = (orig); \
4577 volatile unsigned long _argvec[4]; \
4578 volatile unsigned long _res; \
4579 _argvec[0] = (unsigned long)_orig.nraddr; \
4580 _argvec[1] = (unsigned long)(arg1); \
4581 _argvec[2] = (unsigned long)(arg2); \
4582 _argvec[3] = (unsigned long)(arg3); \
4583 __asm__ volatile( \
4584 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004585 "sw $28, 0($29) \n\t" \
4586 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004587 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004588 "lw $4, 4(%1) \n\t" \
4589 "lw $5, 8(%1) \n\t" \
4590 "lw $6, 12(%1) \n\t" \
4591 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004592 VALGRIND_CALL_NOREDIR_T9 \
4593 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004594 "lw $28, 0($29) \n\t" \
4595 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004596 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004597 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004598 : /*out*/ "=r" (_res) \
4599 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004600 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004601 ); \
4602 lval = (__typeof__(lval)) _res; \
4603 } while (0)
4604
4605#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
4606 do { \
4607 volatile OrigFn _orig = (orig); \
4608 volatile unsigned long _argvec[5]; \
4609 volatile unsigned long _res; \
4610 _argvec[0] = (unsigned long)_orig.nraddr; \
4611 _argvec[1] = (unsigned long)(arg1); \
4612 _argvec[2] = (unsigned long)(arg2); \
4613 _argvec[3] = (unsigned long)(arg3); \
4614 _argvec[4] = (unsigned long)(arg4); \
4615 __asm__ volatile( \
4616 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004617 "sw $28, 0($29) \n\t" \
4618 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004619 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004620 "lw $4, 4(%1) \n\t" \
4621 "lw $5, 8(%1) \n\t" \
4622 "lw $6, 12(%1) \n\t" \
4623 "lw $7, 16(%1) \n\t" \
4624 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004625 VALGRIND_CALL_NOREDIR_T9 \
4626 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004627 "lw $28, 0($29) \n\t" \
4628 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004629 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004630 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004631 : /*out*/ "=r" (_res) \
4632 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004633 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004634 ); \
4635 lval = (__typeof__(lval)) _res; \
4636 } while (0)
4637
4638#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
4639 do { \
4640 volatile OrigFn _orig = (orig); \
4641 volatile unsigned long _argvec[6]; \
4642 volatile unsigned long _res; \
4643 _argvec[0] = (unsigned long)_orig.nraddr; \
4644 _argvec[1] = (unsigned long)(arg1); \
4645 _argvec[2] = (unsigned long)(arg2); \
4646 _argvec[3] = (unsigned long)(arg3); \
4647 _argvec[4] = (unsigned long)(arg4); \
4648 _argvec[5] = (unsigned long)(arg5); \
4649 __asm__ volatile( \
4650 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004651 "sw $28, 0($29) \n\t" \
4652 "sw $31, 4($29) \n\t" \
4653 "lw $4, 20(%1) \n\t" \
4654 "subu $29, $29, 24\n\t" \
4655 "sw $4, 16($29) \n\t" \
4656 "lw $4, 4(%1) \n\t" \
4657 "lw $5, 8(%1) \n\t" \
4658 "lw $6, 12(%1) \n\t" \
4659 "lw $7, 16(%1) \n\t" \
4660 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004661 VALGRIND_CALL_NOREDIR_T9 \
4662 "addu $29, $29, 24 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004663 "lw $28, 0($29) \n\t" \
4664 "lw $31, 4($29) \n\t" \
4665 "addu $29, $29, 8 \n\t" \
4666 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004667 : /*out*/ "=r" (_res) \
4668 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004669 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004670 ); \
4671 lval = (__typeof__(lval)) _res; \
4672 } while (0)
4673#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
4674 do { \
4675 volatile OrigFn _orig = (orig); \
4676 volatile unsigned long _argvec[7]; \
4677 volatile unsigned long _res; \
4678 _argvec[0] = (unsigned long)_orig.nraddr; \
4679 _argvec[1] = (unsigned long)(arg1); \
4680 _argvec[2] = (unsigned long)(arg2); \
4681 _argvec[3] = (unsigned long)(arg3); \
4682 _argvec[4] = (unsigned long)(arg4); \
4683 _argvec[5] = (unsigned long)(arg5); \
4684 _argvec[6] = (unsigned long)(arg6); \
4685 __asm__ volatile( \
4686 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004687 "sw $28, 0($29) \n\t" \
4688 "sw $31, 4($29) \n\t" \
4689 "lw $4, 20(%1) \n\t" \
4690 "subu $29, $29, 32\n\t" \
4691 "sw $4, 16($29) \n\t" \
4692 "lw $4, 24(%1) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004693 "nop\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004694 "sw $4, 20($29) \n\t" \
4695 "lw $4, 4(%1) \n\t" \
4696 "lw $5, 8(%1) \n\t" \
4697 "lw $6, 12(%1) \n\t" \
4698 "lw $7, 16(%1) \n\t" \
4699 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004700 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004701 "addu $29, $29, 32 \n\t" \
4702 "lw $28, 0($29) \n\t" \
4703 "lw $31, 4($29) \n\t" \
4704 "addu $29, $29, 8 \n\t" \
4705 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004706 : /*out*/ "=r" (_res) \
4707 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004708 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004709 ); \
4710 lval = (__typeof__(lval)) _res; \
4711 } while (0)
4712
4713#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4714 arg7) \
4715 do { \
4716 volatile OrigFn _orig = (orig); \
4717 volatile unsigned long _argvec[8]; \
4718 volatile unsigned long _res; \
4719 _argvec[0] = (unsigned long)_orig.nraddr; \
4720 _argvec[1] = (unsigned long)(arg1); \
4721 _argvec[2] = (unsigned long)(arg2); \
4722 _argvec[3] = (unsigned long)(arg3); \
4723 _argvec[4] = (unsigned long)(arg4); \
4724 _argvec[5] = (unsigned long)(arg5); \
4725 _argvec[6] = (unsigned long)(arg6); \
4726 _argvec[7] = (unsigned long)(arg7); \
4727 __asm__ volatile( \
4728 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004729 "sw $28, 0($29) \n\t" \
4730 "sw $31, 4($29) \n\t" \
4731 "lw $4, 20(%1) \n\t" \
4732 "subu $29, $29, 32\n\t" \
4733 "sw $4, 16($29) \n\t" \
4734 "lw $4, 24(%1) \n\t" \
4735 "sw $4, 20($29) \n\t" \
4736 "lw $4, 28(%1) \n\t" \
4737 "sw $4, 24($29) \n\t" \
4738 "lw $4, 4(%1) \n\t" \
4739 "lw $5, 8(%1) \n\t" \
4740 "lw $6, 12(%1) \n\t" \
4741 "lw $7, 16(%1) \n\t" \
4742 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004743 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004744 "addu $29, $29, 32 \n\t" \
4745 "lw $28, 0($29) \n\t" \
4746 "lw $31, 4($29) \n\t" \
4747 "addu $29, $29, 8 \n\t" \
4748 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004749 : /*out*/ "=r" (_res) \
4750 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004751 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004752 ); \
4753 lval = (__typeof__(lval)) _res; \
4754 } while (0)
4755
4756#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4757 arg7,arg8) \
4758 do { \
4759 volatile OrigFn _orig = (orig); \
4760 volatile unsigned long _argvec[9]; \
4761 volatile unsigned long _res; \
4762 _argvec[0] = (unsigned long)_orig.nraddr; \
4763 _argvec[1] = (unsigned long)(arg1); \
4764 _argvec[2] = (unsigned long)(arg2); \
4765 _argvec[3] = (unsigned long)(arg3); \
4766 _argvec[4] = (unsigned long)(arg4); \
4767 _argvec[5] = (unsigned long)(arg5); \
4768 _argvec[6] = (unsigned long)(arg6); \
4769 _argvec[7] = (unsigned long)(arg7); \
4770 _argvec[8] = (unsigned long)(arg8); \
4771 __asm__ volatile( \
4772 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004773 "sw $28, 0($29) \n\t" \
4774 "sw $31, 4($29) \n\t" \
4775 "lw $4, 20(%1) \n\t" \
4776 "subu $29, $29, 40\n\t" \
4777 "sw $4, 16($29) \n\t" \
4778 "lw $4, 24(%1) \n\t" \
4779 "sw $4, 20($29) \n\t" \
4780 "lw $4, 28(%1) \n\t" \
4781 "sw $4, 24($29) \n\t" \
4782 "lw $4, 32(%1) \n\t" \
4783 "sw $4, 28($29) \n\t" \
4784 "lw $4, 4(%1) \n\t" \
4785 "lw $5, 8(%1) \n\t" \
4786 "lw $6, 12(%1) \n\t" \
4787 "lw $7, 16(%1) \n\t" \
4788 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004789 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004790 "addu $29, $29, 40 \n\t" \
4791 "lw $28, 0($29) \n\t" \
4792 "lw $31, 4($29) \n\t" \
4793 "addu $29, $29, 8 \n\t" \
4794 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004795 : /*out*/ "=r" (_res) \
4796 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004797 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004798 ); \
4799 lval = (__typeof__(lval)) _res; \
4800 } while (0)
4801
4802#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4803 arg7,arg8,arg9) \
4804 do { \
4805 volatile OrigFn _orig = (orig); \
4806 volatile unsigned long _argvec[10]; \
4807 volatile unsigned long _res; \
4808 _argvec[0] = (unsigned long)_orig.nraddr; \
4809 _argvec[1] = (unsigned long)(arg1); \
4810 _argvec[2] = (unsigned long)(arg2); \
4811 _argvec[3] = (unsigned long)(arg3); \
4812 _argvec[4] = (unsigned long)(arg4); \
4813 _argvec[5] = (unsigned long)(arg5); \
4814 _argvec[6] = (unsigned long)(arg6); \
4815 _argvec[7] = (unsigned long)(arg7); \
4816 _argvec[8] = (unsigned long)(arg8); \
4817 _argvec[9] = (unsigned long)(arg9); \
4818 __asm__ volatile( \
4819 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004820 "sw $28, 0($29) \n\t" \
4821 "sw $31, 4($29) \n\t" \
4822 "lw $4, 20(%1) \n\t" \
4823 "subu $29, $29, 40\n\t" \
4824 "sw $4, 16($29) \n\t" \
4825 "lw $4, 24(%1) \n\t" \
4826 "sw $4, 20($29) \n\t" \
4827 "lw $4, 28(%1) \n\t" \
4828 "sw $4, 24($29) \n\t" \
4829 "lw $4, 32(%1) \n\t" \
4830 "sw $4, 28($29) \n\t" \
4831 "lw $4, 36(%1) \n\t" \
4832 "sw $4, 32($29) \n\t" \
4833 "lw $4, 4(%1) \n\t" \
4834 "lw $5, 8(%1) \n\t" \
4835 "lw $6, 12(%1) \n\t" \
4836 "lw $7, 16(%1) \n\t" \
4837 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004838 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004839 "addu $29, $29, 40 \n\t" \
4840 "lw $28, 0($29) \n\t" \
4841 "lw $31, 4($29) \n\t" \
4842 "addu $29, $29, 8 \n\t" \
4843 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004844 : /*out*/ "=r" (_res) \
4845 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004846 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004847 ); \
4848 lval = (__typeof__(lval)) _res; \
4849 } while (0)
4850
4851#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4852 arg7,arg8,arg9,arg10) \
4853 do { \
4854 volatile OrigFn _orig = (orig); \
4855 volatile unsigned long _argvec[11]; \
4856 volatile unsigned long _res; \
4857 _argvec[0] = (unsigned long)_orig.nraddr; \
4858 _argvec[1] = (unsigned long)(arg1); \
4859 _argvec[2] = (unsigned long)(arg2); \
4860 _argvec[3] = (unsigned long)(arg3); \
4861 _argvec[4] = (unsigned long)(arg4); \
4862 _argvec[5] = (unsigned long)(arg5); \
4863 _argvec[6] = (unsigned long)(arg6); \
4864 _argvec[7] = (unsigned long)(arg7); \
4865 _argvec[8] = (unsigned long)(arg8); \
4866 _argvec[9] = (unsigned long)(arg9); \
4867 _argvec[10] = (unsigned long)(arg10); \
4868 __asm__ volatile( \
4869 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004870 "sw $28, 0($29) \n\t" \
4871 "sw $31, 4($29) \n\t" \
4872 "lw $4, 20(%1) \n\t" \
4873 "subu $29, $29, 48\n\t" \
4874 "sw $4, 16($29) \n\t" \
4875 "lw $4, 24(%1) \n\t" \
4876 "sw $4, 20($29) \n\t" \
4877 "lw $4, 28(%1) \n\t" \
4878 "sw $4, 24($29) \n\t" \
4879 "lw $4, 32(%1) \n\t" \
4880 "sw $4, 28($29) \n\t" \
4881 "lw $4, 36(%1) \n\t" \
4882 "sw $4, 32($29) \n\t" \
4883 "lw $4, 40(%1) \n\t" \
4884 "sw $4, 36($29) \n\t" \
4885 "lw $4, 4(%1) \n\t" \
4886 "lw $5, 8(%1) \n\t" \
4887 "lw $6, 12(%1) \n\t" \
4888 "lw $7, 16(%1) \n\t" \
4889 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004890 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004891 "addu $29, $29, 48 \n\t" \
4892 "lw $28, 0($29) \n\t" \
4893 "lw $31, 4($29) \n\t" \
4894 "addu $29, $29, 8 \n\t" \
4895 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004896 : /*out*/ "=r" (_res) \
4897 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004898 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004899 ); \
4900 lval = (__typeof__(lval)) _res; \
4901 } while (0)
4902
4903#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4904 arg6,arg7,arg8,arg9,arg10, \
4905 arg11) \
4906 do { \
4907 volatile OrigFn _orig = (orig); \
4908 volatile unsigned long _argvec[12]; \
4909 volatile unsigned long _res; \
4910 _argvec[0] = (unsigned long)_orig.nraddr; \
4911 _argvec[1] = (unsigned long)(arg1); \
4912 _argvec[2] = (unsigned long)(arg2); \
4913 _argvec[3] = (unsigned long)(arg3); \
4914 _argvec[4] = (unsigned long)(arg4); \
4915 _argvec[5] = (unsigned long)(arg5); \
4916 _argvec[6] = (unsigned long)(arg6); \
4917 _argvec[7] = (unsigned long)(arg7); \
4918 _argvec[8] = (unsigned long)(arg8); \
4919 _argvec[9] = (unsigned long)(arg9); \
4920 _argvec[10] = (unsigned long)(arg10); \
4921 _argvec[11] = (unsigned long)(arg11); \
4922 __asm__ volatile( \
4923 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004924 "sw $28, 0($29) \n\t" \
4925 "sw $31, 4($29) \n\t" \
4926 "lw $4, 20(%1) \n\t" \
4927 "subu $29, $29, 48\n\t" \
4928 "sw $4, 16($29) \n\t" \
4929 "lw $4, 24(%1) \n\t" \
4930 "sw $4, 20($29) \n\t" \
4931 "lw $4, 28(%1) \n\t" \
4932 "sw $4, 24($29) \n\t" \
4933 "lw $4, 32(%1) \n\t" \
4934 "sw $4, 28($29) \n\t" \
4935 "lw $4, 36(%1) \n\t" \
4936 "sw $4, 32($29) \n\t" \
4937 "lw $4, 40(%1) \n\t" \
4938 "sw $4, 36($29) \n\t" \
4939 "lw $4, 44(%1) \n\t" \
4940 "sw $4, 40($29) \n\t" \
4941 "lw $4, 4(%1) \n\t" \
4942 "lw $5, 8(%1) \n\t" \
4943 "lw $6, 12(%1) \n\t" \
4944 "lw $7, 16(%1) \n\t" \
4945 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004946 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004947 "addu $29, $29, 48 \n\t" \
4948 "lw $28, 0($29) \n\t" \
4949 "lw $31, 4($29) \n\t" \
4950 "addu $29, $29, 8 \n\t" \
4951 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004952 : /*out*/ "=r" (_res) \
4953 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004954 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004955 ); \
4956 lval = (__typeof__(lval)) _res; \
4957 } while (0)
4958
4959#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4960 arg6,arg7,arg8,arg9,arg10, \
4961 arg11,arg12) \
4962 do { \
4963 volatile OrigFn _orig = (orig); \
4964 volatile unsigned long _argvec[13]; \
4965 volatile unsigned long _res; \
4966 _argvec[0] = (unsigned long)_orig.nraddr; \
4967 _argvec[1] = (unsigned long)(arg1); \
4968 _argvec[2] = (unsigned long)(arg2); \
4969 _argvec[3] = (unsigned long)(arg3); \
4970 _argvec[4] = (unsigned long)(arg4); \
4971 _argvec[5] = (unsigned long)(arg5); \
4972 _argvec[6] = (unsigned long)(arg6); \
4973 _argvec[7] = (unsigned long)(arg7); \
4974 _argvec[8] = (unsigned long)(arg8); \
4975 _argvec[9] = (unsigned long)(arg9); \
4976 _argvec[10] = (unsigned long)(arg10); \
4977 _argvec[11] = (unsigned long)(arg11); \
4978 _argvec[12] = (unsigned long)(arg12); \
4979 __asm__ volatile( \
4980 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004981 "sw $28, 0($29) \n\t" \
4982 "sw $31, 4($29) \n\t" \
4983 "lw $4, 20(%1) \n\t" \
4984 "subu $29, $29, 56\n\t" \
4985 "sw $4, 16($29) \n\t" \
4986 "lw $4, 24(%1) \n\t" \
4987 "sw $4, 20($29) \n\t" \
4988 "lw $4, 28(%1) \n\t" \
4989 "sw $4, 24($29) \n\t" \
4990 "lw $4, 32(%1) \n\t" \
4991 "sw $4, 28($29) \n\t" \
4992 "lw $4, 36(%1) \n\t" \
4993 "sw $4, 32($29) \n\t" \
4994 "lw $4, 40(%1) \n\t" \
4995 "sw $4, 36($29) \n\t" \
4996 "lw $4, 44(%1) \n\t" \
4997 "sw $4, 40($29) \n\t" \
4998 "lw $4, 48(%1) \n\t" \
4999 "sw $4, 44($29) \n\t" \
5000 "lw $4, 4(%1) \n\t" \
5001 "lw $5, 8(%1) \n\t" \
5002 "lw $6, 12(%1) \n\t" \
5003 "lw $7, 16(%1) \n\t" \
5004 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005005 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005006 "addu $29, $29, 56 \n\t" \
5007 "lw $28, 0($29) \n\t" \
5008 "lw $31, 4($29) \n\t" \
5009 "addu $29, $29, 8 \n\t" \
5010 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005011 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00005012 : /*in*/ "r" (&_argvec[0]) \
5013 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005014 ); \
5015 lval = (__typeof__(lval)) _res; \
5016 } while (0)
5017
5018#endif /* PLAT_mips32_linux */
5019
petarj4df0bfc2013-02-27 23:17:33 +00005020/* ------------------------- mips64-linux ------------------------- */
5021
5022#if defined(PLAT_mips64_linux)
5023
5024/* These regs are trashed by the hidden call. */
5025#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5026"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5027"$25", "$31"
5028
5029/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5030 long) == 4. */
5031
5032#define CALL_FN_W_v(lval, orig) \
5033 do { \
5034 volatile OrigFn _orig = (orig); \
5035 volatile unsigned long _argvec[1]; \
5036 volatile unsigned long _res; \
5037 _argvec[0] = (unsigned long)_orig.nraddr; \
5038 __asm__ volatile( \
5039 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5040 VALGRIND_CALL_NOREDIR_T9 \
5041 "move %0, $2\n" \
5042 : /*out*/ "=r" (_res) \
5043 : /*in*/ "0" (&_argvec[0]) \
5044 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5045 ); \
5046 lval = (__typeof__(lval)) _res; \
5047 } while (0)
5048
5049#define CALL_FN_W_W(lval, orig, arg1) \
5050 do { \
5051 volatile OrigFn _orig = (orig); \
5052 volatile unsigned long _argvec[2]; \
5053 volatile unsigned long _res; \
5054 _argvec[0] = (unsigned long)_orig.nraddr; \
5055 _argvec[1] = (unsigned long)(arg1); \
5056 __asm__ volatile( \
5057 "ld $4, 8(%1)\n\t" /* arg1*/ \
5058 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5059 VALGRIND_CALL_NOREDIR_T9 \
5060 "move %0, $2\n" \
5061 : /*out*/ "=r" (_res) \
5062 : /*in*/ "r" (&_argvec[0]) \
5063 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5064 ); \
5065 lval = (__typeof__(lval)) _res; \
5066 } while (0)
5067
5068#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5069 do { \
5070 volatile OrigFn _orig = (orig); \
5071 volatile unsigned long _argvec[3]; \
5072 volatile unsigned long _res; \
5073 _argvec[0] = (unsigned long)_orig.nraddr; \
5074 _argvec[1] = (unsigned long)(arg1); \
5075 _argvec[2] = (unsigned long)(arg2); \
5076 __asm__ volatile( \
5077 "ld $4, 8(%1)\n\t" \
5078 "ld $5, 16(%1)\n\t" \
5079 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5080 VALGRIND_CALL_NOREDIR_T9 \
5081 "move %0, $2\n" \
5082 : /*out*/ "=r" (_res) \
5083 : /*in*/ "r" (&_argvec[0]) \
5084 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5085 ); \
5086 lval = (__typeof__(lval)) _res; \
5087 } while (0)
5088
5089#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5090 do { \
5091 volatile OrigFn _orig = (orig); \
5092 volatile unsigned long _argvec[4]; \
5093 volatile unsigned long _res; \
5094 _argvec[0] = (unsigned long)_orig.nraddr; \
5095 _argvec[1] = (unsigned long)(arg1); \
5096 _argvec[2] = (unsigned long)(arg2); \
5097 _argvec[3] = (unsigned long)(arg3); \
5098 __asm__ volatile( \
5099 "ld $4, 8(%1)\n\t" \
5100 "ld $5, 16(%1)\n\t" \
5101 "ld $6, 24(%1)\n\t" \
5102 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5103 VALGRIND_CALL_NOREDIR_T9 \
5104 "move %0, $2\n" \
5105 : /*out*/ "=r" (_res) \
5106 : /*in*/ "r" (&_argvec[0]) \
5107 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5108 ); \
5109 lval = (__typeof__(lval)) _res; \
5110 } while (0)
5111
5112#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5113 do { \
5114 volatile OrigFn _orig = (orig); \
5115 volatile unsigned long _argvec[5]; \
5116 volatile unsigned long _res; \
5117 _argvec[0] = (unsigned long)_orig.nraddr; \
5118 _argvec[1] = (unsigned long)(arg1); \
5119 _argvec[2] = (unsigned long)(arg2); \
5120 _argvec[3] = (unsigned long)(arg3); \
5121 _argvec[4] = (unsigned long)(arg4); \
5122 __asm__ volatile( \
5123 "ld $4, 8(%1)\n\t" \
5124 "ld $5, 16(%1)\n\t" \
5125 "ld $6, 24(%1)\n\t" \
5126 "ld $7, 32(%1)\n\t" \
5127 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5128 VALGRIND_CALL_NOREDIR_T9 \
5129 "move %0, $2\n" \
5130 : /*out*/ "=r" (_res) \
5131 : /*in*/ "r" (&_argvec[0]) \
5132 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5133 ); \
5134 lval = (__typeof__(lval)) _res; \
5135 } while (0)
5136
5137#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5138 do { \
5139 volatile OrigFn _orig = (orig); \
5140 volatile unsigned long _argvec[6]; \
5141 volatile unsigned long _res; \
5142 _argvec[0] = (unsigned long)_orig.nraddr; \
5143 _argvec[1] = (unsigned long)(arg1); \
5144 _argvec[2] = (unsigned long)(arg2); \
5145 _argvec[3] = (unsigned long)(arg3); \
5146 _argvec[4] = (unsigned long)(arg4); \
5147 _argvec[5] = (unsigned long)(arg5); \
5148 __asm__ volatile( \
5149 "ld $4, 8(%1)\n\t" \
5150 "ld $5, 16(%1)\n\t" \
5151 "ld $6, 24(%1)\n\t" \
5152 "ld $7, 32(%1)\n\t" \
5153 "ld $8, 40(%1)\n\t" \
5154 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5155 VALGRIND_CALL_NOREDIR_T9 \
5156 "move %0, $2\n" \
5157 : /*out*/ "=r" (_res) \
5158 : /*in*/ "r" (&_argvec[0]) \
5159 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5160 ); \
5161 lval = (__typeof__(lval)) _res; \
5162 } while (0)
5163
5164#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5165 do { \
5166 volatile OrigFn _orig = (orig); \
5167 volatile unsigned long _argvec[7]; \
5168 volatile unsigned long _res; \
5169 _argvec[0] = (unsigned long)_orig.nraddr; \
5170 _argvec[1] = (unsigned long)(arg1); \
5171 _argvec[2] = (unsigned long)(arg2); \
5172 _argvec[3] = (unsigned long)(arg3); \
5173 _argvec[4] = (unsigned long)(arg4); \
5174 _argvec[5] = (unsigned long)(arg5); \
5175 _argvec[6] = (unsigned long)(arg6); \
5176 __asm__ volatile( \
5177 "ld $4, 8(%1)\n\t" \
5178 "ld $5, 16(%1)\n\t" \
5179 "ld $6, 24(%1)\n\t" \
5180 "ld $7, 32(%1)\n\t" \
5181 "ld $8, 40(%1)\n\t" \
5182 "ld $9, 48(%1)\n\t" \
5183 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5184 VALGRIND_CALL_NOREDIR_T9 \
5185 "move %0, $2\n" \
5186 : /*out*/ "=r" (_res) \
5187 : /*in*/ "r" (&_argvec[0]) \
5188 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5189 ); \
5190 lval = (__typeof__(lval)) _res; \
5191 } while (0)
5192
5193#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5194 arg7) \
5195 do { \
5196 volatile OrigFn _orig = (orig); \
5197 volatile unsigned long _argvec[8]; \
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 _argvec[3] = (unsigned long)(arg3); \
5203 _argvec[4] = (unsigned long)(arg4); \
5204 _argvec[5] = (unsigned long)(arg5); \
5205 _argvec[6] = (unsigned long)(arg6); \
5206 _argvec[7] = (unsigned long)(arg7); \
5207 __asm__ volatile( \
5208 "ld $4, 8(%1)\n\t" \
5209 "ld $5, 16(%1)\n\t" \
5210 "ld $6, 24(%1)\n\t" \
5211 "ld $7, 32(%1)\n\t" \
5212 "ld $8, 40(%1)\n\t" \
5213 "ld $9, 48(%1)\n\t" \
5214 "ld $10, 56(%1)\n\t" \
5215 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5216 VALGRIND_CALL_NOREDIR_T9 \
5217 "move %0, $2\n" \
5218 : /*out*/ "=r" (_res) \
5219 : /*in*/ "r" (&_argvec[0]) \
5220 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5221 ); \
5222 lval = (__typeof__(lval)) _res; \
5223 } while (0)
5224
5225#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5226 arg7,arg8) \
5227 do { \
5228 volatile OrigFn _orig = (orig); \
5229 volatile unsigned long _argvec[9]; \
5230 volatile unsigned long _res; \
5231 _argvec[0] = (unsigned long)_orig.nraddr; \
5232 _argvec[1] = (unsigned long)(arg1); \
5233 _argvec[2] = (unsigned long)(arg2); \
5234 _argvec[3] = (unsigned long)(arg3); \
5235 _argvec[4] = (unsigned long)(arg4); \
5236 _argvec[5] = (unsigned long)(arg5); \
5237 _argvec[6] = (unsigned long)(arg6); \
5238 _argvec[7] = (unsigned long)(arg7); \
5239 _argvec[8] = (unsigned long)(arg8); \
5240 __asm__ volatile( \
5241 "ld $4, 8(%1)\n\t" \
5242 "ld $5, 16(%1)\n\t" \
5243 "ld $6, 24(%1)\n\t" \
5244 "ld $7, 32(%1)\n\t" \
5245 "ld $8, 40(%1)\n\t" \
5246 "ld $9, 48(%1)\n\t" \
5247 "ld $10, 56(%1)\n\t" \
5248 "ld $11, 64(%1)\n\t" \
5249 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5250 VALGRIND_CALL_NOREDIR_T9 \
5251 "move %0, $2\n" \
5252 : /*out*/ "=r" (_res) \
5253 : /*in*/ "r" (&_argvec[0]) \
5254 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5255 ); \
5256 lval = (__typeof__(lval)) _res; \
5257 } while (0)
5258
5259#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5260 arg7,arg8,arg9) \
5261 do { \
5262 volatile OrigFn _orig = (orig); \
5263 volatile unsigned long _argvec[10]; \
5264 volatile unsigned long _res; \
5265 _argvec[0] = (unsigned long)_orig.nraddr; \
5266 _argvec[1] = (unsigned long)(arg1); \
5267 _argvec[2] = (unsigned long)(arg2); \
5268 _argvec[3] = (unsigned long)(arg3); \
5269 _argvec[4] = (unsigned long)(arg4); \
5270 _argvec[5] = (unsigned long)(arg5); \
5271 _argvec[6] = (unsigned long)(arg6); \
5272 _argvec[7] = (unsigned long)(arg7); \
5273 _argvec[8] = (unsigned long)(arg8); \
5274 _argvec[9] = (unsigned long)(arg9); \
5275 __asm__ volatile( \
5276 "dsubu $29, $29, 8\n\t" \
5277 "ld $4, 72(%1)\n\t" \
5278 "sd $4, 0($29)\n\t" \
5279 "ld $4, 8(%1)\n\t" \
5280 "ld $5, 16(%1)\n\t" \
5281 "ld $6, 24(%1)\n\t" \
5282 "ld $7, 32(%1)\n\t" \
5283 "ld $8, 40(%1)\n\t" \
5284 "ld $9, 48(%1)\n\t" \
5285 "ld $10, 56(%1)\n\t" \
5286 "ld $11, 64(%1)\n\t" \
5287 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5288 VALGRIND_CALL_NOREDIR_T9 \
5289 "daddu $29, $29, 8\n\t" \
5290 "move %0, $2\n" \
5291 : /*out*/ "=r" (_res) \
5292 : /*in*/ "r" (&_argvec[0]) \
5293 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5294 ); \
5295 lval = (__typeof__(lval)) _res; \
5296 } while (0)
5297
5298#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5299 arg7,arg8,arg9,arg10) \
5300 do { \
5301 volatile OrigFn _orig = (orig); \
5302 volatile unsigned long _argvec[11]; \
5303 volatile unsigned long _res; \
5304 _argvec[0] = (unsigned long)_orig.nraddr; \
5305 _argvec[1] = (unsigned long)(arg1); \
5306 _argvec[2] = (unsigned long)(arg2); \
5307 _argvec[3] = (unsigned long)(arg3); \
5308 _argvec[4] = (unsigned long)(arg4); \
5309 _argvec[5] = (unsigned long)(arg5); \
5310 _argvec[6] = (unsigned long)(arg6); \
5311 _argvec[7] = (unsigned long)(arg7); \
5312 _argvec[8] = (unsigned long)(arg8); \
5313 _argvec[9] = (unsigned long)(arg9); \
5314 _argvec[10] = (unsigned long)(arg10); \
5315 __asm__ volatile( \
5316 "dsubu $29, $29, 16\n\t" \
5317 "ld $4, 72(%1)\n\t" \
5318 "sd $4, 0($29)\n\t" \
5319 "ld $4, 80(%1)\n\t" \
5320 "sd $4, 8($29)\n\t" \
5321 "ld $4, 8(%1)\n\t" \
5322 "ld $5, 16(%1)\n\t" \
5323 "ld $6, 24(%1)\n\t" \
5324 "ld $7, 32(%1)\n\t" \
5325 "ld $8, 40(%1)\n\t" \
5326 "ld $9, 48(%1)\n\t" \
5327 "ld $10, 56(%1)\n\t" \
5328 "ld $11, 64(%1)\n\t" \
5329 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5330 VALGRIND_CALL_NOREDIR_T9 \
5331 "daddu $29, $29, 16\n\t" \
5332 "move %0, $2\n" \
5333 : /*out*/ "=r" (_res) \
5334 : /*in*/ "r" (&_argvec[0]) \
5335 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5336 ); \
5337 lval = (__typeof__(lval)) _res; \
5338 } while (0)
5339
5340#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5341 arg6,arg7,arg8,arg9,arg10, \
5342 arg11) \
5343 do { \
5344 volatile OrigFn _orig = (orig); \
5345 volatile unsigned long _argvec[12]; \
5346 volatile unsigned long _res; \
5347 _argvec[0] = (unsigned long)_orig.nraddr; \
5348 _argvec[1] = (unsigned long)(arg1); \
5349 _argvec[2] = (unsigned long)(arg2); \
5350 _argvec[3] = (unsigned long)(arg3); \
5351 _argvec[4] = (unsigned long)(arg4); \
5352 _argvec[5] = (unsigned long)(arg5); \
5353 _argvec[6] = (unsigned long)(arg6); \
5354 _argvec[7] = (unsigned long)(arg7); \
5355 _argvec[8] = (unsigned long)(arg8); \
5356 _argvec[9] = (unsigned long)(arg9); \
5357 _argvec[10] = (unsigned long)(arg10); \
5358 _argvec[11] = (unsigned long)(arg11); \
5359 __asm__ volatile( \
5360 "dsubu $29, $29, 24\n\t" \
5361 "ld $4, 72(%1)\n\t" \
5362 "sd $4, 0($29)\n\t" \
5363 "ld $4, 80(%1)\n\t" \
5364 "sd $4, 8($29)\n\t" \
5365 "ld $4, 88(%1)\n\t" \
5366 "sd $4, 16($29)\n\t" \
5367 "ld $4, 8(%1)\n\t" \
5368 "ld $5, 16(%1)\n\t" \
5369 "ld $6, 24(%1)\n\t" \
5370 "ld $7, 32(%1)\n\t" \
5371 "ld $8, 40(%1)\n\t" \
5372 "ld $9, 48(%1)\n\t" \
5373 "ld $10, 56(%1)\n\t" \
5374 "ld $11, 64(%1)\n\t" \
5375 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5376 VALGRIND_CALL_NOREDIR_T9 \
5377 "daddu $29, $29, 24\n\t" \
5378 "move %0, $2\n" \
5379 : /*out*/ "=r" (_res) \
5380 : /*in*/ "r" (&_argvec[0]) \
5381 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5382 ); \
5383 lval = (__typeof__(lval)) _res; \
5384 } while (0)
5385
5386#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5387 arg6,arg7,arg8,arg9,arg10, \
5388 arg11,arg12) \
5389 do { \
5390 volatile OrigFn _orig = (orig); \
5391 volatile unsigned long _argvec[13]; \
5392 volatile unsigned long _res; \
5393 _argvec[0] = (unsigned long)_orig.nraddr; \
5394 _argvec[1] = (unsigned long)(arg1); \
5395 _argvec[2] = (unsigned long)(arg2); \
5396 _argvec[3] = (unsigned long)(arg3); \
5397 _argvec[4] = (unsigned long)(arg4); \
5398 _argvec[5] = (unsigned long)(arg5); \
5399 _argvec[6] = (unsigned long)(arg6); \
5400 _argvec[7] = (unsigned long)(arg7); \
5401 _argvec[8] = (unsigned long)(arg8); \
5402 _argvec[9] = (unsigned long)(arg9); \
5403 _argvec[10] = (unsigned long)(arg10); \
5404 _argvec[11] = (unsigned long)(arg11); \
5405 _argvec[12] = (unsigned long)(arg12); \
5406 __asm__ volatile( \
5407 "dsubu $29, $29, 32\n\t" \
5408 "ld $4, 72(%1)\n\t" \
5409 "sd $4, 0($29)\n\t" \
5410 "ld $4, 80(%1)\n\t" \
5411 "sd $4, 8($29)\n\t" \
5412 "ld $4, 88(%1)\n\t" \
5413 "sd $4, 16($29)\n\t" \
5414 "ld $4, 96(%1)\n\t" \
5415 "sd $4, 24($29)\n\t" \
5416 "ld $4, 8(%1)\n\t" \
5417 "ld $5, 16(%1)\n\t" \
5418 "ld $6, 24(%1)\n\t" \
5419 "ld $7, 32(%1)\n\t" \
5420 "ld $8, 40(%1)\n\t" \
5421 "ld $9, 48(%1)\n\t" \
5422 "ld $10, 56(%1)\n\t" \
5423 "ld $11, 64(%1)\n\t" \
5424 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5425 VALGRIND_CALL_NOREDIR_T9 \
5426 "daddu $29, $29, 32\n\t" \
5427 "move %0, $2\n" \
5428 : /*out*/ "=r" (_res) \
5429 : /*in*/ "r" (&_argvec[0]) \
5430 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5431 ); \
5432 lval = (__typeof__(lval)) _res; \
5433 } while (0)
5434
5435#endif /* PLAT_mips64_linux */
5436
sewardj0ec07f32006-01-12 12:32:32 +00005437
5438/* ------------------------------------------------------------------ */
5439/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
5440/* */
njn30d76c62005-06-18 15:07:39 +00005441/* ------------------------------------------------------------------ */
5442
sewardj2e93c502002-04-12 11:12:52 +00005443/* Some request codes. There are many more of these, but most are not
5444 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00005445 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00005446
sewardj0ec07f32006-01-12 12:32:32 +00005447 Core ones are in the range 0x00000000--0x0000ffff. The non-public
5448 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00005449*/
5450
sewardj0ec07f32006-01-12 12:32:32 +00005451/* These macros are used by tools -- they must be public, but don't
5452 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00005453#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00005454 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00005455#define VG_IS_TOOL_USERREQ(a, b, v) \
5456 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00005457
sewardj5ce4b152006-03-11 12:57:41 +00005458/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
5459 This enum comprises an ABI exported by Valgrind to programs
5460 which use client requests. DO NOT CHANGE THE ORDER OF THESE
5461 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00005462typedef
njn4c791212003-05-02 17:53:54 +00005463 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
5464 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00005465
sewardj0ec07f32006-01-12 12:32:32 +00005466 /* These allow any function to be called from the simulated
5467 CPU but run on the real CPU. Nb: the first arg passed to
5468 the function is always the ThreadId of the running
5469 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00005470 function, etc. */
njn4c791212003-05-02 17:53:54 +00005471 VG_USERREQ__CLIENT_CALL0 = 0x1101,
5472 VG_USERREQ__CLIENT_CALL1 = 0x1102,
5473 VG_USERREQ__CLIENT_CALL2 = 0x1103,
5474 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00005475
sewardj0ec07f32006-01-12 12:32:32 +00005476 /* Can be useful in regression testing suites -- eg. can
5477 send Valgrind's output to /dev/null and still count
5478 errors. */
njn4c791212003-05-02 17:53:54 +00005479 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00005480
philippe46207652013-01-20 17:11:58 +00005481 /* Allows the client program and/or gdbserver to execute a monitor
5482 command. */
sewardj3b290482011-05-06 21:02:55 +00005483 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
5484
sewardj0ec07f32006-01-12 12:32:32 +00005485 /* These are useful and can be interpreted by any tool that
5486 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00005487 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00005488 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00005489 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00005490 /* Memory pool support. */
5491 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
5492 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
5493 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
5494 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00005495 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00005496 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
5497 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
5498 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00005499
fitzhardinge39de4b42003-10-31 07:12:21 +00005500 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00005501 /* The first two pass the va_list argument by value, which
5502 assumes it is the same size as or smaller than a UWord,
5503 which generally isn't the case. Hence are deprecated.
5504 The second two pass the vargs by reference and so are
5505 immune to this problem. */
5506 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00005507 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00005508 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00005509 /* both :: char* fmt, va_list* vargs */
5510 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
5511 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00005512
5513 /* Stack support. */
5514 VG_USERREQ__STACK_REGISTER = 0x1501,
5515 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00005516 VG_USERREQ__STACK_CHANGE = 0x1503,
5517
5518 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00005519 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
5520
5521 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00005522 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
5523
5524 /* Disable/enable error reporting level. Takes a single
5525 Word arg which is the delta to this thread's error
5526 disablement indicator. Hence 1 disables or further
5527 disables errors, and -1 moves back towards enablement.
5528 Other values are not allowed. */
florianbb913cd2012-08-28 16:50:39 +00005529 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
5530
5531 /* Initialise IR injection */
5532 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901
njn25e49d8e72002-09-23 09:36:25 +00005533 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00005534
sewardj0ec07f32006-01-12 12:32:32 +00005535#if !defined(__GNUC__)
5536# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00005537#endif
sewardj2e93c502002-04-12 11:12:52 +00005538
bartfa5115a2010-09-02 09:33:02 +00005539
sewardj0ec07f32006-01-12 12:32:32 +00005540/* Returns the number of Valgrinds this code is running under. That
5541 is, 0 if running natively, 1 if running under Valgrind, 2 if
5542 running under Valgrind which is running under another Valgrind,
5543 etc. */
bartfa5115a2010-09-02 09:33:02 +00005544#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00005545 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00005546 VG_USERREQ__RUNNING_ON_VALGRIND, \
5547 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00005548
5549
sewardj18d75132002-05-16 11:06:21 +00005550/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
5551 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
5552 since it provides a way to make sure valgrind will retranslate the
5553 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00005554#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
5555 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
5556 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00005557
njn26aba4d2005-05-16 13:31:23 +00005558
sewardj0ec07f32006-01-12 12:32:32 +00005559/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00005560 Possibly with a backtrace. This is a really ugly hack. The return value
5561 is the number of characters printed, excluding the "**<pid>** " part at the
5562 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00005563
bart42f83fe2012-01-31 10:13:51 +00005564#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00005565/* Modern GCC will optimize the static routine out if unused,
5566 and unused attribute will shut down warnings about it. */
5567static int VALGRIND_PRINTF(const char *format, ...)
5568 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00005569#endif
sewardj7eca0cc2006-04-12 17:15:35 +00005570static int
bart0da2c772010-09-01 10:18:36 +00005571#if defined(_MSC_VER)
5572__inline
5573#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00005574VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00005575{
bart8c7e25f2011-03-04 16:55:56 +00005576#if defined(NVALGRIND)
5577 return 0;
5578#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00005579#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005580 uintptr_t _qzz_res;
5581#else
njnc6168192004-11-29 13:54:10 +00005582 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00005583#endif
sewardjc560fb32010-01-28 15:23:54 +00005584 va_list vargs;
5585 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00005586#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005587 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00005588 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00005589 (uintptr_t)format,
5590 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00005591 0, 0, 0);
5592#else
bart575ce8e2011-05-15 07:04:03 +00005593 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00005594 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00005595 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00005596 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00005597 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00005598#endif
sewardjc560fb32010-01-28 15:23:54 +00005599 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00005600 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00005601#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00005602}
5603
bart42f83fe2012-01-31 10:13:51 +00005604#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00005605static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
5606 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00005607#endif
sewardj7eca0cc2006-04-12 17:15:35 +00005608static int
bart0da2c772010-09-01 10:18:36 +00005609#if defined(_MSC_VER)
5610__inline
5611#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00005612VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00005613{
bart8c7e25f2011-03-04 16:55:56 +00005614#if defined(NVALGRIND)
5615 return 0;
5616#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00005617#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005618 uintptr_t _qzz_res;
5619#else
njnc6168192004-11-29 13:54:10 +00005620 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00005621#endif
sewardjc560fb32010-01-28 15:23:54 +00005622 va_list vargs;
5623 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00005624#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005625 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00005626 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00005627 (uintptr_t)format,
5628 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00005629 0, 0, 0);
5630#else
bart575ce8e2011-05-15 07:04:03 +00005631 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00005632 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00005633 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00005634 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00005635 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00005636#endif
sewardjc560fb32010-01-28 15:23:54 +00005637 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00005638 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00005639#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00005640}
sewardj18d75132002-05-16 11:06:21 +00005641
sewardj0ec07f32006-01-12 12:32:32 +00005642
njn3e884182003-04-15 13:03:23 +00005643/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00005644 real CPU, calling an arbitary function.
5645
5646 Note that the current ThreadId is inserted as the first argument.
5647 So this call:
5648
5649 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
5650
5651 requires f to have this signature:
5652
5653 Word f(Word tid, Word arg1, Word arg2)
5654
5655 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00005656
5657 Note that these client requests are not entirely reliable. For example,
5658 if you call a function with them that subsequently calls printf(),
5659 there's a high chance Valgrind will crash. Generally, your prospects of
5660 these working are made higher if the called function does not refer to
5661 any global variables, and does not refer to any libc or other functions
5662 (printf et al). Any kind of entanglement with libc or dynamic linking is
5663 likely to have a bad outcome, for tricky reasons which we've grappled
5664 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00005665*/
sewardj0ec07f32006-01-12 12:32:32 +00005666#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00005667 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5668 VG_USERREQ__CLIENT_CALL0, \
5669 _qyy_fn, \
5670 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00005671
bart575ce8e2011-05-15 07:04:03 +00005672#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
5673 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5674 VG_USERREQ__CLIENT_CALL1, \
5675 _qyy_fn, \
5676 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00005677
bart575ce8e2011-05-15 07:04:03 +00005678#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
5679 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5680 VG_USERREQ__CLIENT_CALL2, \
5681 _qyy_fn, \
5682 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00005683
sewardj0ec07f32006-01-12 12:32:32 +00005684#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00005685 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5686 VG_USERREQ__CLIENT_CALL3, \
5687 _qyy_fn, \
5688 _qyy_arg1, _qyy_arg2, \
5689 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00005690
5691
nethercote7cc9c232004-01-21 15:08:04 +00005692/* Counts the number of errors that have been recorded by a tool. Nb:
5693 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00005694 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00005695#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00005696 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
5697 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00005698 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00005699 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00005700
njn3ac96952009-07-09 23:35:44 +00005701/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
5702 when heap blocks are allocated in order to give accurate results. This
5703 happens automatically for the standard allocator functions such as
5704 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
5705 delete[], etc.
njnd7994182003-10-02 13:44:04 +00005706
njn3ac96952009-07-09 23:35:44 +00005707 But if your program uses a custom allocator, this doesn't automatically
5708 happen, and Valgrind will not do as well. For example, if you allocate
5709 superblocks with mmap() and then allocates chunks of the superblocks, all
5710 Valgrind's observations will be at the mmap() level and it won't know that
5711 the chunks should be considered separate entities. In Memcheck's case,
5712 that means you probably won't get heap block overrun detection (because
5713 there won't be redzones marked as unaddressable) and you definitely won't
5714 get any leak detection.
5715
5716 The following client requests allow a custom allocator to be annotated so
5717 that it can be handled accurately by Valgrind.
5718
5719 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
5720 by a malloc()-like function. For Memcheck (an illustrative case), this
5721 does two things:
5722
5723 - It records that the block has been allocated. This means any addresses
5724 within the block mentioned in error messages will be
5725 identified as belonging to the block. It also means that if the block
5726 isn't freed it will be detected by the leak checker.
5727
5728 - It marks the block as being addressable and undefined (if 'is_zeroed' is
5729 not set), or addressable and defined (if 'is_zeroed' is set). This
5730 controls how accesses to the block by the program are handled.
5731
5732 'addr' is the start of the usable block (ie. after any
5733 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
5734 can apply redzones -- these are blocks of padding at the start and end of
5735 each block. Adding redzones is recommended as it makes it much more likely
5736 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
5737 zeroed (or filled with another predictable value), as is the case for
5738 calloc().
5739
5740 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
5741 heap block -- that will be used by the client program -- is allocated.
5742 It's best to put it at the outermost level of the allocator if possible;
5743 for example, if you have a function my_alloc() which calls
5744 internal_alloc(), and the client request is put inside internal_alloc(),
5745 stack traces relating to the heap block will contain entries for both
5746 my_alloc() and internal_alloc(), which is probably not what you want.
5747
njnb965efb2009-08-10 07:36:54 +00005748 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
5749 custom blocks from within a heap block, B, that has been allocated with
5750 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
5751 -- the custom blocks will take precedence.
5752
njn3ac96952009-07-09 23:35:44 +00005753 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
5754 Memcheck, it does two things:
5755
5756 - It records that the block has been deallocated. This assumes that the
5757 block was annotated as having been allocated via
5758 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
5759
5760 - It marks the block as being unaddressable.
5761
5762 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
5763 heap block is deallocated.
5764
bart91347382011-03-25 20:07:25 +00005765 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
5766 Memcheck, it does four things:
5767
5768 - It records that the size of a block has been changed. This assumes that
5769 the block was annotated as having been allocated via
5770 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
5771
5772 - If the block shrunk, it marks the freed memory as being unaddressable.
5773
5774 - If the block grew, it marks the new area as undefined and defines a red
5775 zone past the end of the new block.
5776
5777 - The V-bits of the overlap between the old and the new block are preserved.
5778
5779 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
5780 and before deallocation of the old block.
5781
5782 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00005783 allocator working well with Memcheck. More specifically, if your allocator
5784 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
5785 will be necessary to mark the memory as addressable just before the zeroing
5786 occurs, otherwise you'll get a lot of invalid write errors. For example,
5787 you'll need to do this if your allocator recycles freed blocks, but it
5788 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
5789 Alternatively, if your allocator reuses freed blocks for allocator-internal
5790 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
5791
5792 Really, what's happening is a blurring of the lines between the client
5793 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
5794 memory should be considered unaddressable to the client program, but the
5795 allocator knows more than the rest of the client program and so may be able
5796 to safely access it. Extra client requests are necessary for Valgrind to
5797 understand the distinction between the allocator and the rest of the
5798 program.
5799
njn32f8d8c2009-07-15 02:31:45 +00005800 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00005801*/
sewardj4b3a7422011-10-24 13:21:57 +00005802#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
5803 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
5804 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00005805
njn32f8d8c2009-07-15 02:31:45 +00005806/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
5807 Ignored if addr == 0.
5808*/
sewardj4b3a7422011-10-24 13:21:57 +00005809#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
5810 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
5811 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00005812
5813/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
5814 Ignored if addr == 0.
5815*/
sewardj4b3a7422011-10-24 13:21:57 +00005816#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
5817 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
5818 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00005819
rjwalshbc0bb832004-06-19 18:12:36 +00005820/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005821#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00005822 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
5823 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005824
5825/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005826#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00005827 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
5828 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005829
5830/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005831#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005832 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
5833 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005834
5835/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005836#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00005837 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
5838 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005839
sewardj2c1c9df2006-07-28 00:06:37 +00005840/* Disassociate any pieces outside a particular range. */
5841#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005842 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
5843 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00005844
sewardjc740d762006-10-05 17:59:23 +00005845/* Resize and/or move a piece associated with a memory pool. */
5846#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00005847 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
5848 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00005849
5850/* Resize and/or move a piece associated with a memory pool. */
5851#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005852 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
5853 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00005854
5855/* Return 1 if a mempool exists, else 0. */
5856#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00005857 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00005858 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00005859 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00005860
rjwalsh0140af52005-06-04 20:42:33 +00005861/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00005862#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00005863 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00005864 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00005865 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005866
5867/* Unmark the piece of memory associated with a stack id as being a
5868 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00005869#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00005870 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
5871 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005872
5873/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00005874#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00005875 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
5876 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005877
sewardjc8259b82009-04-22 22:42:10 +00005878/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00005879#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
5880 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
5881 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00005882
sewardj5c659622010-08-20 18:22:07 +00005883/* Map a code address to a source file name and line number. buf64
5884 must point to a 64-byte buffer in the caller's address space. The
5885 result will be dumped in there and is guaranteed to be zero
5886 terminated. If no info is found, the first byte is set to zero. */
5887#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00005888 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00005889 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00005890 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00005891
sewardjdc873c02011-07-24 16:02:33 +00005892/* Disable error reporting for this thread. Behaves in a stack like
5893 way, so you can safely call this multiple times provided that
5894 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
5895 to re-enable reporting. The first call of this macro disables
5896 reporting. Subsequent calls have no effect except to increase the
5897 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
5898 reporting. Child threads do not inherit this setting from their
5899 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00005900#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00005901 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
5902 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00005903
5904/* Re-enable error reporting, as per comments on
5905 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00005906#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00005907 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
5908 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00005909
philippe46207652013-01-20 17:11:58 +00005910/* Execute a monitor command from the client program.
5911 If a connection is opened with GDB, the output will be sent
5912 according to the output mode set for vgdb.
5913 If no connection is opened, output will go to the log output.
5914 Returns 1 if command not recognised, 0 otherwise. */
5915#define VALGRIND_MONITOR_COMMAND(command) \
5916 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
5917 command, 0, 0, 0, 0)
5918
5919
sewardjc112c8e2011-06-24 18:26:11 +00005920#undef PLAT_x86_darwin
5921#undef PLAT_amd64_darwin
5922#undef PLAT_x86_win32
bartaaaf21d2013-08-25 06:10:24 +00005923#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +00005924#undef PLAT_x86_linux
5925#undef PLAT_amd64_linux
5926#undef PLAT_ppc32_linux
5927#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00005928#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00005929#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +00005930#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +00005931#undef PLAT_mips64_linux
sewardj0ec07f32006-01-12 12:32:32 +00005932
njn3e884182003-04-15 13:03:23 +00005933#endif /* __VALGRIND_H */